1 /***************************************************************************
3 * Copyright 2010, 2011 BMW Car IT GmbH
4 * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
21 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
24 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
25 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 ****************************************************************************/
30 #include "WindowSystems/WaylandBaseWindowSystem.h"
44 #include "WindowSystems/WaylandServerinfoServerProtocol.h"
48 struct wl_resource base;
49 WaylandBaseWindowSystem* windowSystem;
52 struct serverinfoClient {
53 struct wl_client *client;
58 void WaylandBaseWindowSystem::serverinfoIFCreateConnection(struct wl_client *client, struct wl_resource *resource)
60 struct serverinfo* deliver = (struct serverinfo*)resource->data;
62 // creates new connection id and store it in memory
63 struct serverinfoClient* clientPair = (struct serverinfoClient*)malloc( sizeof *clientPair );
65 clientPair->client = client;
66 clientPair->connectionId = deliver->windowSystem->m_manageConnectionId;
67 deliver->windowSystem->m_manageConnectionId++;
69 wl_list_init(&clientPair->link);
70 wl_list_insert(&deliver->windowSystem->m_connectionList, &clientPair->link);
72 // send native client handle to this client.
73 // by protocol default, this information is not needed.
74 wl_resource_post_event(resource, SERVERINFO_CONNECTION_ID, clientPair->connectionId);
75 LOG_DEBUG("WaylandBaseWindowSystem", "serverinfoIFCreateConnection() create connection id" << clientPair->connectionId << " for client " << clientPair->client);
78 struct serverinfo_interface g_serverinfoImplementation = {
79 WaylandBaseWindowSystem::serverinfoIFCreateConnection,
82 void WaylandBaseWindowSystem::bindServerinfo(struct wl_client *client, void *data, uint32_t version, uint32_t id)
84 LOG_DEBUG("WaylandBaseWindowSystem", "bindServerinfo client:" << client << ", data:" << data << ", version:" << version << ", id:" << id);
85 wl_client_add_object(client, &serverinfo_interface, &g_serverinfoImplementation, id, data);
88 void WaylandBaseWindowSystem::createServerinfo(WaylandBaseWindowSystem* windowSystem)
90 struct serverinfo* serverInfo;
92 serverInfo = (struct serverinfo*)malloc(sizeof *serverInfo);
93 if (NULL == serverInfo){
94 LOG_ERROR("WaylandBaseWindowSystem", "failed to alloc serverinfo");
98 serverInfo->base.object.interface = &serverinfo_interface;
99 serverInfo->base.object.implementation = (void(**)(void)) &g_serverinfoImplementation;
100 serverInfo->base.client = NULL;
101 serverInfo->base.data = NULL;
102 serverInfo->windowSystem = windowSystem;
104 m_serverInfoGlobal = wl_display_add_global(windowSystem->m_wlDisplay, &serverinfo_interface, serverInfo, WaylandBaseWindowSystem::bindServerinfo);
105 if (NULL == m_serverInfoGlobal)
107 LOG_ERROR("WaylandBaseWindowSystem", "failed wl_display_add_global");
112 m_serverInfo = (void*)serverInfo;
116 WaylandBaseWindowSystem::WaylandBaseWindowSystem(const char* displayname, int width, int height, Scene* pScene)
117 : BaseWindowSystem(pScene)
119 , m_wlDisplayClient(NULL)
120 , m_wlCompositorClient(NULL)
121 , m_wlSurfaceClient(NULL)
124 , graphicSystem(NULL)
126 , m_serverInfoGlobal(NULL)
128 , m_wlCompositorGlobal(NULL)
129 , m_initialized(false)
130 , m_takeScreenshot(ScreenShotNone)
131 , m_displayname(displayname)
133 , m_systemState(IDLE_STATE)
134 , m_manageConnectionId(256)
136 , m_screenShotSurfaceID(0)
137 , m_screenShotLayerID(0)
142 , m_listFrameCallback()
145 LOG_DEBUG("WaylandBaseWindowSystem", "creating WaylandBaseWindowSystem width:" << width << " height:" << height);
147 // init and take mutex, so windowsystem only does init phase until mutex is released again
148 pthread_mutex_init(&run_lock, NULL);
149 pthread_mutex_lock(&run_lock);
152 WaylandBaseWindowSystem::~WaylandBaseWindowSystem()
156 void WaylandBaseWindowSystem::printDebug()
158 // print stuff about layerlist
159 std::stringstream debugmessage;
160 debugmessage << "Layer: ID | X | Y | W | H | Al. \n";
162 LayerList list = m_pScene->getCurrentRenderOrder();
165 LayerListConstIterator iter = list.begin();
166 LayerListConstIterator iterEnd = list.end();
168 for(; iter != iterEnd; ++iter)
170 Rectangle dest = (*iter)->getDestinationRegion();
171 debugmessage << " " << std::setw(4) << (*iter)->getID() << " " << std::setw(3) << dest.x << " " << std::setw(3) << dest.y << " " << std::setw(3) << dest.width << " " << std::setw(3) << dest.height << " " << std::setw(3) << (*iter)->opacity << "\n";
173 debugmessage << " Surface: ID |Al.| SVP: X | Y | W | H DVP: X | Y | W | H \n";
175 // loop the surfaces of within each layer
176 SurfaceList surfaceList = (*iter)->getAllSurfaces();
177 SurfaceListIterator surfaceIter = surfaceList.begin();
178 SurfaceListIterator surfaceIterEnd = surfaceList.end();
180 for(; surfaceIter != surfaceIterEnd ; ++surfaceIter)
182 Rectangle src = (*surfaceIter)->getSourceRegion();
183 Rectangle dest = (*surfaceIter)->getDestinationRegion();
184 debugmessage << " " << std::setw(4) << (*surfaceIter)->getID() << " " << std::setprecision(3) << (*surfaceIter)->opacity<< " " << std::setw(3) << src.x << " " << std::setw(3) << src.y << " " << std::setw(3) << src.width << " " << std::setw(3) << src.height << " " << std::setw(3) << dest.x << " " << std::setw(3) << dest.y << " " << std::setw(3) << dest.width << " " << std::setw(3) << dest.height << "\n";
187 LOG_DEBUG("WaylandBaseWindowSystem",debugmessage.str());
190 Surface* WaylandBaseWindowSystem::getSurfaceFromNativeSurface(struct native_surface* nativeSurface)
192 // go though all surfaces
193 const std::map<unsigned int,Surface*> surfaces = m_pScene->getAllSurfaces();
194 for(std::map<unsigned int, Surface*>::const_iterator currentS = surfaces.begin(); currentS != surfaces.end(); ++currentS)
196 Surface* currentSurface = (*currentS).second;
201 WaylandPlatformSurface* nativePlatform = (WaylandPlatformSurface*)currentSurface->platform;
206 if (nativePlatform->connectionId != nativeSurface->connectionId)
210 if (nativePlatform->surfaceId != nativeSurface->surface.resource.object.id)
214 return currentSurface;
216 LOG_DEBUG("WaylandBaseWindowSystem", "could not find surface for surface " << nativeSurface);
220 void WaylandBaseWindowSystem::checkForNewSurfaceNativeContent()
222 m_pScene->lockScene();
223 LayerList layers = m_pScene->getCurrentRenderOrder();
224 for(LayerListConstIterator current = layers.begin(); current != layers.end(); current++)
226 SurfaceList surfaces = (*current)->getAllSurfaces();
227 for(SurfaceListConstIterator currentS = surfaces.begin(); currentS != surfaces.end(); currentS++)
229 if ((*currentS)->hasNativeContent())
231 allocatePlatformSurface(*currentS);
233 else // While we are at it, also cleanup any stale native content
235 deallocatePlatformSurface(*currentS);
239 m_pScene->unlockScene();
242 static struct timeval tv0;
243 static struct timeval tv0_forRender;
246 void WaylandBaseWindowSystem::calculateSurfaceFps(Surface *currentSurface, float time )
248 char floatStringBuffer[256];
249 float surfaceUpdateFps = ((float)(currentSurface->updateCounter)) / time ;
250 float surfaceDrawFps = ((float)(currentSurface->drawCounter)) / time ;
251 sprintf(floatStringBuffer, "0x%08x update fps: %3.2f", currentSurface->getID(),surfaceUpdateFps);
252 currentSurface->updateCounter = 0;
253 LOG_INFO("WaylandBaseWindowSystem", "Surface " << floatStringBuffer);
254 sprintf(floatStringBuffer, "0x%08x draw fps: %3.2f", currentSurface->getID(),surfaceDrawFps);
255 currentSurface->drawCounter = 0;
256 LOG_INFO("WaylandBaseWindowSystem", "Surface " << floatStringBuffer);
259 void WaylandBaseWindowSystem::calculateFps()
264 float timeSinceLastCalc = 0.0;
266 // we have rendered a frame
268 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
269 // every 3 seconds, calculate & print fps
270 gettimeofday(&tv, NULL);
271 timeSinceLastCalc = (float)(tv.tv_sec-tv0.tv_sec) + 0.000001*((float)(tv.tv_usec-tv0.tv_usec));
273 // calculate every rendering because of event driven
274 // if (timeSinceLastCalc > 10.0f)
276 //LOG_INFO("WaylandBaseWindowSystem", "tv.tv_sec:" << tv.tv_sec << ", tv.tv_usec:" << tv.tv_usec);
277 //LOG_INFO("WaylandBaseWindowSystem", "timeSinceLastCalc " << timeSinceLastCalc);
278 FPS = ((float)(Frame)) / timeSinceLastCalc;
279 char floatStringBuffer[256];
280 sprintf(floatStringBuffer, "Overall fps: %f", FPS);
282 timeSinceLastCalc = (float)(tv.tv_sec-tv0_forRender.tv_sec) + 0.000001*((float)(tv.tv_usec-tv0_forRender.tv_usec));
283 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
285 SurfaceList surfaceList = (*current)->getAllSurfaces();
286 SurfaceListIterator surfaceIter = surfaceList.begin();
287 SurfaceListIterator surfaceIterEnd = surfaceList.end();
288 for(; surfaceIter != surfaceIterEnd ; ++surfaceIter)
290 calculateSurfaceFps((*surfaceIter),timeSinceLastCalc);
293 LOG_INFO("WaylandBaseWindowSystem", floatStringBuffer);
299 void WaylandBaseWindowSystem::CheckRedrawAllLayers()
301 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
302 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
304 Layer* currentLayer = (Layer*)*current;
305 graphicSystem->beginLayer(currentLayer);
306 graphicSystem->checkRenderLayer();
307 graphicSystem->endLayer();
311 void WaylandBaseWindowSystem::RedrawAllLayers()
313 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
314 bool bRedraw = m_forceComposition || m_damaged || (m_systemState == REDRAW_STATE);
316 // m_damaged represents that SW composition is required
317 // At this point if a layer has damaged = true then it must be a HW layer that needs update.
318 // A SW layer which needs update will make m_damaged = true
321 graphicSystem->activateGraphicContext();
322 #ifndef WL_OMIT_CLEAR_GB
323 graphicSystem->clearBackground();
324 #endif /* WL_OMIT_CLEAR_GB */
326 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
328 if ((*current)->getLayerType() == Hardware)
330 if (m_forceComposition || (*current)->damaged)
332 renderHWLayer(*current);
333 (*current)->damaged = false;
338 graphicSystem->beginLayer(*current);
339 graphicSystem->renderSWLayer();
340 graphicSystem->endLayer();
345 #ifdef WL_LOG_DETAIL_TIMER
348 float timeSinceLastCalc = 0.0;
349 gettimeofday(&tv_s, NULL);
350 graphicSystem->swapBuffers();
351 gettimeofday(&tv_e, NULL);
352 timeSinceLastCalc = (float)(tv_e.tv_sec-tv_s.tv_sec) + 0.000001*((float)(tv_e.tv_usec-tv_s.tv_usec));
353 LOG_INFO("WaylandBaseWindowSystem", "swapBuffers" << timeSinceLastCalc);
355 graphicSystem->swapBuffers();
357 graphicSystem->releaseGraphicContext();
361 void WaylandBaseWindowSystem::renderHWLayer(Layer *layer)
366 void WaylandBaseWindowSystem::Redraw()
368 gettimeofday(&tv0_forRender, NULL);
370 // draw all the layers
371 //graphicSystem->clearBackground();
372 /*LOG_INFO("WaylandBaseWindowSystem","Locking List");*/
373 m_pScene->lockScene();
375 CheckRedrawAllLayers();
378 m_pScene->unlockScene();
380 if (m_forceComposition || m_damaged || (m_systemState == REDRAW_STATE))
382 // TODO: This block won't be executed for HW only changes
383 // Is that acceptable?
391 /* Reset the damage flag, all is up to date */
392 m_forceComposition = false;
394 m_systemState = IDLE_STATE;
398 void WaylandBaseWindowSystem::Screenshot()
400 /*LOG_INFO("WaylandBaseWindowSystem","Locking List");*/
401 m_pScene->lockScene();
402 graphicSystem->activateGraphicContext();
403 graphicSystem->clearBackground();
405 if (m_takeScreenshot==ScreenshotOfDisplay)
407 LOG_DEBUG("WaylandBaseWindowSystem", "Taking screenshot");
408 std::list<Layer*> layers = m_pScene->getCurrentRenderOrder();
410 for(std::list<Layer*>::const_iterator current = layers.begin(); current != layers.end(); current++)
412 if ((*current)->getLayerType() != Hardware)
414 graphicSystem->beginLayer(*current);
415 graphicSystem->renderSWLayer();
416 graphicSystem->endLayer();
420 else if(m_takeScreenshot==ScreenshotOfLayer)
422 LOG_DEBUG("WaylandBaseWindowSystem", "Taking screenshot of layer");
423 Layer* currentLayer = m_pScene->getLayer(m_screenShotLayerID);
425 if (currentLayer!=NULL){
426 graphicSystem->beginLayer(currentLayer);
427 graphicSystem->renderSWLayer();
428 graphicSystem->endLayer();
431 else if(m_takeScreenshot==ScreenshotOfSurface)
433 LOG_DEBUG("WaylandBaseWindowSystem", "Taking screenshot of surface");
434 Layer* currentLayer = m_pScene->getLayer(m_screenShotLayerID);
435 Surface* currentSurface = m_pScene->getSurface(m_screenShotSurfaceID);
437 if (currentLayer!=NULL && currentSurface!=NULL){
438 graphicSystem->beginLayer(currentLayer);
439 graphicSystem->renderSurface(currentSurface);
440 graphicSystem->endLayer();
444 graphicSystem->saveScreenShotOfFramebuffer(m_screenShotFile);
445 // graphicSystem->swapBuffers();
446 m_takeScreenshot = ScreenShotNone;
447 LOG_DEBUG("WaylandBaseWindowSystem", "Done taking screenshot");
449 graphicSystem->releaseGraphicContext();
450 m_pScene->unlockScene();
451 /*LOG_INFO("WaylandBaseWindowSystem","UnLocking List");*/
454 void WaylandBaseWindowSystem::destroyListenerSurfaceBuffer(struct wl_listener* listener, struct wl_resource* resource, uint32_t time)
456 LOG_DEBUG("WaylandBaseWindowSystem", "destroyListenerSurfaceBuffer listener:" << listener << ", resource:" << resource << ", time:" << time);
457 struct native_surface *es = container_of(listener, struct native_surface, buffer_destroy_listener);
462 struct native_surface* WaylandBaseWindowSystem::createNativeSurface()
464 LOG_DEBUG("WaylandBaseWindowSystem", "createNativeSurface IN");
465 struct native_surface* surface = (struct native_surface*)calloc(1, sizeof *surface);
468 LOG_ERROR("WaylandBaseWindowSystem", "failed to create native surface");
472 wl_list_init(&surface->link);
473 wl_list_init(&surface->buffer_link);
475 surface->surface.resource.client = NULL;
477 surface->windowSystem = this;
479 // surface->visual = NONE_VISUAL;
481 surface->buffer = NULL;
482 surface->buffer_destroy_listener.func = destroyListenerSurfaceBuffer;
484 LOG_DEBUG("WaylandBaseWindowSystem", "createNativeSurface OUT");
488 uint32_t WaylandBaseWindowSystem::getTime(void)
490 #ifdef WL_OMIT_GETTIME
492 #else /* WL_OMIT_GETTIME */
495 gettimeofday(&tv, NULL);
497 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
498 #endif /* WL_OMIT_GETTIME */
501 void WaylandBaseWindowSystem::destroySurfaceCallback(struct wl_resource* resource)
503 struct native_surface* nativeSurface = container_of(resource, struct native_surface, surface.resource);
504 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*)nativeSurface->windowSystem);
505 Surface* ilmSurface = windowSystem->getSurfaceFromNativeSurface(nativeSurface);
507 if (NULL != ilmSurface)
509 if (NULL != ilmSurface->platform)
511 delete ilmSurface->platform;
512 ilmSurface->platform = NULL;
514 windowSystem->graphicSystem->getTextureBinder()->destroyClientBuffer(ilmSurface);
517 wl_list_remove(&nativeSurface->link);
518 wl_list_remove(&nativeSurface->buffer_link);
520 if (nativeSurface->buffer)
522 wl_list_remove(&nativeSurface->buffer_destroy_listener.link);
528 extern "C" void WaylandBaseWindowSystem::surfaceIFDestroy(struct wl_client *client, struct wl_resource *resource)
530 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFDestroy client:" << client << ", resource:" << resource);
531 wl_resource_destroy(resource, getTime());
534 void WaylandBaseWindowSystem::postReleaseBuffer(struct wl_buffer *buffer)
536 LOG_DEBUG("WaylandBaseWindowSystem", "postReleaseBufferIN");
537 if (--buffer->busy_count > 0)
542 if (NULL == buffer->resource.client)
544 LOG_ERROR("WaylandBaseWindowSystem", "Release client is NULL");
546 wl_resource_queue_event(&buffer->resource, WL_BUFFER_RELEASE);
547 LOG_DEBUG("WaylandBaseWindowSystem", "postReleaseBuffer OUT");
550 void WaylandBaseWindowSystem::attachBufferToNativeSurface(struct wl_buffer* buffer, struct wl_surface* surface)
552 LOG_DEBUG("WaylandBaseWindowSystem", "attachBufferToNativeSurface IN");
553 struct native_surface* nativeSurface = (struct native_surface*)surface;
554 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*)nativeSurface->windowSystem);
555 Surface* ilmSurface = windowSystem->getSurfaceFromNativeSurface(nativeSurface);
556 if (NULL == ilmSurface)
558 LOG_ERROR("WaylandBaseWindowSystem", "failed to get surface for wl_surface");
561 struct wl_list* surfaces_attached_to;
563 ilmSurface->updateCounter++;
564 ilmSurface->removeNativeContent();
565 ilmSurface->setNativeContent((long int)buffer);
566 WaylandPlatformSurface* nativePlatformSurface = (WaylandPlatformSurface*)ilmSurface->platform;
567 if (0 != nativePlatformSurface)
569 windowSystem->graphicSystem->getTextureBinder()->createClientBuffer(ilmSurface);
570 LOG_DEBUG("WaylandBaseWindowSystem","nativePlatformSurface->enable");
571 nativePlatformSurface->enableRendering();
574 if (wl_buffer_is_shm(buffer))
576 LOG_DEBUG("WaylandBaseWindowSystem", "shm buffer" << buffer);
579 //switch (wl_shm_buffer_get_format(buffer)) {
580 //case WL_SHM_FORMAT_ARGB32:
581 //es->visual = WLSC_ARGB_VISUAL;
583 //case WL_SHM_FORMAT_PREMULTIPLIED_ARGB32:
584 //es->visual = WLSC_PREMUL_ARGB_VISUAL;
586 //case WL_SHM_FORMAT_XRGB32:
587 //es->visual = WLSC_RGB_VISUAL;
591 surfaces_attached_to = (wl_list*)buffer->user_data;
593 wl_list_remove(&nativeSurface->buffer_link);
594 wl_list_insert(surfaces_attached_to, &nativeSurface->buffer_link);
597 LOG_DEBUG("WaylandBaseWindowSystem", "wl buffer");
599 // TODO: we need to get the visual from the wl_buffer */
600 // es->visual = WLSC_PREMUL_ARGB_VISUAL;
601 // es->pitch = es->width;
603 LOG_DEBUG("WaylandBaseWindowSystem", "attachBufferToNativeSurface OUT");
606 extern "C" void WaylandBaseWindowSystem::surfaceIFAttach(struct wl_client* client,
607 struct wl_resource* resource,
608 struct wl_resource* buffer_resource, int32_t x, int32_t y)
610 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFAttach client:" << client << ", resource:" << resource << ", buffer_resource:" << buffer_resource << ", x:" << x << ", y:" << y);
611 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFAttach IN");
612 struct native_surface* nativeSurface = (struct native_surface*)resource->data;
613 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*)nativeSurface->windowSystem);
614 struct wl_buffer* buffer = (struct wl_buffer*)buffer_resource->data;
616 if (nativeSurface->buffer)
618 windowSystem->postReleaseBuffer(nativeSurface->buffer);
619 wl_list_remove(&nativeSurface->buffer_destroy_listener.link);
622 buffer->busy_count++;
623 nativeSurface->buffer = buffer;
624 wl_list_insert(nativeSurface->buffer->resource.destroy_listener_list.prev, &nativeSurface->buffer_destroy_listener.link);
626 windowSystem->attachBufferToNativeSurface(buffer, &nativeSurface->surface);
628 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFAttach OUT");
631 extern "C" void WaylandBaseWindowSystem::surfaceIFDamage(struct wl_client *client,
632 struct wl_resource *resource,
633 int32_t x, int32_t y, int32_t width, int32_t height)
635 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFDamage client:" << client << ", resource:" << resource << ", x:" << x << ", y:" << y << ", width:" << width << ", height:" << height);
636 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFDamage IN");
637 struct native_surface* nativeSurface = (struct native_surface*)resource->data;
638 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*)nativeSurface->windowSystem);
640 Surface* surface = windowSystem->getSurfaceFromNativeSurface(nativeSurface);
643 LOG_ERROR("WaylandBaseWindowSystem", "invalid surface");
646 surface->damaged = true;
648 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFDamage OUT");
651 extern "C" void WaylandBaseWindowSystem::destroyFrameCallback(struct wl_resource *resource)
653 struct native_frame_callback* cb = (struct native_frame_callback*)resource->data;
655 wl_list_remove(&cb->link);
659 extern "C" void WaylandBaseWindowSystem::surfaceIFFrame(struct wl_client *client,
660 struct wl_resource *resource, uint32_t callback)
662 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFFrame IN");
663 struct native_frame_callback* cb;
664 struct native_surface* es = (struct native_surface*)resource->data;
665 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*)es->windowSystem);
667 cb = (struct native_frame_callback*)malloc(sizeof *cb);
670 wl_resource_post_no_memory(resource);
674 cb->resource.object.interface = &wl_callback_interface;
675 cb->resource.object.id = callback;
676 cb->resource.destroy = destroyFrameCallback;
677 cb->resource.client = client;
678 cb->resource.data = cb;
680 wl_client_add_resource(client, &cb->resource);
681 wl_list_insert(windowSystem->m_listFrameCallback.prev, &cb->link);
683 windowSystem->checkForNewSurfaceNativeContent();
684 idleEventRepaint(windowSystem);
686 LOG_DEBUG("WaylandBaseWindowSystem", "surfaceIFFrame OUT");
689 extern "C" const struct wl_surface_interface g_surfaceInterface = {
690 WaylandBaseWindowSystem::surfaceIFDestroy,
691 WaylandBaseWindowSystem::surfaceIFAttach,
692 WaylandBaseWindowSystem::surfaceIFDamage,
693 WaylandBaseWindowSystem::surfaceIFFrame
696 extern "C" void WaylandBaseWindowSystem::compositorIFCreateSurface
697 (struct wl_client *client, struct wl_resource* resource, uint32_t id)
699 LOG_DEBUG("WaylandBaseWindowSystem", "compositorIFCreateSurface IN");
700 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*) resource->data);
701 struct native_surface* surface;
703 surface = windowSystem->createNativeSurface();
706 wl_resource_post_no_memory(resource);
710 surface->surface.resource.destroy = destroySurfaceCallback;
711 surface->windowSystem = windowSystem;
713 surface->surface.resource.object.id = id;
714 surface->surface.resource.object.interface = &wl_surface_interface;
715 surface->surface.resource.object.implementation = (void (**)(void))&g_surfaceInterface;
716 surface->surface.resource.data = surface;
718 struct serverinfoClient* serverinfoPairNode;
720 wl_list_for_each(serverinfoPairNode, &windowSystem->m_connectionList, link) {
721 if (serverinfoPairNode->client != client)
725 surface->connectionId = serverinfoPairNode->connectionId;
729 windowSystem->checkForNewSurface();
730 wl_client_add_resource(client, &surface->surface.resource);
731 LOG_DEBUG("WaylandBaseWindowSystem", "compositorIFCreateSurface OUT");
734 const static struct wl_compositor_interface g_compositorInterface = {
735 WaylandBaseWindowSystem::compositorIFCreateSurface,
738 extern "C" void WaylandBaseWindowSystem::shmIFBufferCreated(struct wl_buffer *buffer)
740 LOG_DEBUG("WaylandBaseWindowSystem", "shmIFBufferCreated IN");
741 struct wl_list* surfaces_attached_to;
743 surfaces_attached_to = (struct wl_list*)malloc(sizeof *surfaces_attached_to);
744 if (NULL == surfaces_attached_to)
746 buffer->user_data = NULL;
750 wl_list_init(surfaces_attached_to);
752 buffer->user_data = surfaces_attached_to;
753 LOG_DEBUG("WaylandBaseWindowSystem", "shmIFBufferCreated OUT");
756 extern "C" void WaylandBaseWindowSystem::shmIFBufferDamaged(struct wl_buffer* buffer, int32_t x, int32_t y, int32_t width, int32_t height)
758 LOG_DEBUG("WaylandBaseWindowSystem", "shmIFBufferDamaged buffer:" << buffer << ", x:" << x << ", y:" << y << ", width:" << width << ", height:" << height);
761 extern "C" void WaylandBaseWindowSystem::shmIFBufferDestroyed(struct wl_buffer *buffer)
763 LOG_DEBUG("WaylandBaseWindowSystem", "shmIFBufferDestroyed IN");
764 struct wl_list* surfaces_attached_to = (struct wl_list*)buffer->user_data;
765 struct native_surface* nativeSurface;
766 struct native_surface* next;
768 wl_list_for_each_safe(nativeSurface, next, surfaces_attached_to, buffer_link)
770 wl_list_remove(&nativeSurface->buffer_link);
771 wl_list_init(&nativeSurface->buffer_link);
774 free(surfaces_attached_to);
775 LOG_DEBUG("WaylandBaseWindowSystem", "shmIFBufferDestroyed OUT");
778 const static struct wl_shm_callbacks g_shmCallbacks = {
779 WaylandBaseWindowSystem::shmIFBufferCreated,
780 WaylandBaseWindowSystem::shmIFBufferDamaged,
781 WaylandBaseWindowSystem::shmIFBufferDestroyed
785 * Thread in charge of the CompositorWindow eventloop
786 * Friend function of class WaylandBaseWindowSystem
788 extern "C" void* WaylandBaseWindowSystem::eventLoopCallback(void *ptr)
790 WaylandBaseWindowSystem *windowsys = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*) ptr);
791 return windowsys->eventLoop();
794 void WaylandBaseWindowSystem::bindCompositor(struct wl_client* client, void* data, uint32_t version, uint32_t id)
796 LOG_DEBUG("WaylandBaseWindowSystem", "bindCompositor client:" << client << ", data:" << data << ", version:" << version << ", id:" << id);
797 wl_client_add_object(client, &wl_compositor_interface, &g_compositorInterface, id, data);
800 void WaylandBaseWindowSystem::repaint(int msecs)
802 LOG_DEBUG("WaylandBaseWindowSystem", "repaint IN");
803 struct native_frame_callback* cb;
804 struct native_frame_callback* cnext;
808 wl_list_for_each_safe(cb, cnext, &m_listFrameCallback, link)
810 wl_resource_post_event(&cb->resource, WL_CALLBACK_DONE, msecs);
811 wl_resource_destroy(&cb->resource, 0);
813 LOG_DEBUG("WaylandBaseWindowSystem", "repaint OUT");
816 void WaylandBaseWindowSystem::idleEventRepaint(void *data)
818 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*)data);
819 LOG_DEBUG("WaylandBaseWindowSystem", "idleEventRepaint IN");
820 windowSystem->repaint(getTime());
821 LOG_DEBUG("WaylandBaseWindowSystem", "idleEventRepaint OUT");
824 bool WaylandBaseWindowSystem::initCompositor()
826 LOG_DEBUG("WaylandBaseWindowSystem", "initCompositor START");
828 m_wlCompositorGlobal = wl_display_add_global(m_wlDisplay, &wl_compositor_interface, this, bindCompositor);
829 if (NULL == m_wlCompositorGlobal)
831 LOG_ERROR("WaylandBaseWindowSystem", "wl_display_add_global:failed to set wl_compositor_interface");
834 LOG_DEBUG("WaylandBaseWindowSystem", "wl_display_add_global:SUCCESS");
836 m_wlShm = wl_shm_init(m_wlDisplay, &g_shmCallbacks);
839 LOG_ERROR("WaylandBaseWindowSystem", "failed to init wl_shm");
843 wl_list_init(&m_listFrameCallback);
845 wl_list_init(&m_connectionList);
846 createServerinfo(this);
848 LOG_DEBUG("WaylandBaseWindowSystem", "initCompositor END");
852 void WaylandBaseWindowSystem::shutdownCompositor()
854 if (NULL != m_serverInfoGlobal)
856 wl_display_remove_global(m_wlDisplay, m_serverInfoGlobal);
857 m_serverInfoGlobal = NULL;
859 if (NULL != m_serverInfo)
866 wl_shm_finish(m_wlShm);
869 if (NULL != m_wlCompositorGlobal)
871 wl_display_remove_global(m_wlDisplay, m_wlCompositorGlobal);
872 m_wlCompositorGlobal = NULL;
876 void WaylandBaseWindowSystem::wakeUpRendererThread()
880 int WaylandBaseWindowSystem::signalEventOnTerm(int signal_number, void *data)
882 WaylandBaseWindowSystem* windowSystem = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*)data);
884 LOG_INFO("WaylandBaseWindowSystem", "caught signal " << signal_number);
885 windowSystem->cleanup();
890 void* WaylandBaseWindowSystem::eventLoop()
893 LOG_DEBUG("WaylandBaseWindowSystem", "Enter thread");
896 struct wl_event_loop *loop;
900 m_wlDisplay = wl_display_create();
902 if (NULL == m_wlDisplay)
904 LOG_ERROR("WaylandBaseWindowSystem", "failed to create wayland display");
907 LOG_DEBUG("WaylandBaseWindowSystem", "create wayland display");
909 loop = wl_display_get_event_loop(m_wlDisplay);
910 wl_event_loop_add_signal(loop, SIGTERM, signalEventOnTerm, this);
911 wl_event_loop_add_signal(loop, SIGINT, signalEventOnTerm, this);
912 wl_event_loop_add_signal(loop, SIGQUIT, signalEventOnTerm, this);
913 wl_event_loop_add_signal(loop, SIGKILL, signalEventOnTerm, this);
915 LOG_DEBUG("WaylandBaseWindowSystem", "wl_event_loop_add_signal");
917 status = this->initCompositor();
920 LOG_ERROR("WaylandBaseWindowSystem", "failed to init compositor");
923 LOG_DEBUG("WaylandBaseWindowSystem", "SUCCESS:initCompositor");
925 //. create Native Context
926 status = createNativeContext();
929 LOG_ERROR("WaylandBaseWindowSystem", "failed to create Native context");
932 LOG_DEBUG("WaylandBaseWindowSystem", "SUCCESS:createNativeContext");
934 //. create egl context
935 status = initGraphicSystem();
938 LOG_ERROR("WaylandBaseWindowSystem", "failed to init graphicSystem");
941 LOG_DEBUG("WaylandBaseWindowSystem", "SUCCESS:init GraphicSystem");
943 this->m_success = status;
944 this->m_initialized = true;
946 // Done with init, wait for lock to actually run (ie start/stop method called)
947 pthread_mutex_lock(&this->run_lock);
949 LOG_DEBUG("WaylandBaseWindowSystem", "Starting Event loop");
951 // run the main event loop while rendering
952 gettimeofday(&tv0, NULL);
953 LOG_DEBUG("WaylandBaseWindowSystem", "Enter render loop");
955 // clear screen to avoid garbage on startup
956 this->graphicSystem->clearBackground();
957 this->graphicSystem->swapBuffers();
959 if (wl_display_add_socket(m_wlDisplay, NULL))
961 LOG_ERROR("WaylandBaseWindowSystem", "failed to add socket");
962 this->m_success = false;
963 this->m_initialized = false;
967 wl_display_run(m_wlDisplay);
972 LOG_DEBUG("WaylandBaseWindowSystem", "Renderer thread finished");
976 extern "C" void WaylandBaseWindowSystem::surfaceListenerFrame(void* data, struct wl_callback* callback, uint32_t time)
978 data = data; // TODO:to avoid warning
979 time = time; // TODO:to avoid warining
982 wl_callback_destroy(callback);
986 extern "C" const struct wl_callback_listener g_frameListener = {
987 WaylandBaseWindowSystem::surfaceListenerFrame
990 void WaylandBaseWindowSystem::signalRedrawEvent()
992 LOG_DEBUG("WaylandBaseWindowSystem", "signalRedrawEvent");
993 // set flag that redraw is needed
994 this->m_systemState = REDRAW_STATE;
996 struct wl_callback* callback = wl_surface_frame(m_wlSurfaceClient);
997 wl_callback_add_listener(callback, &g_frameListener, NULL);
998 wl_display_flush(m_wlDisplayClient);
1001 void WaylandBaseWindowSystem::cleanup()
1003 LOG_DEBUG("WaylandBaseWindowSystem", "Cleanup");
1005 shutdownCompositor();
1007 if (NULL != m_wlDisplay)
1009 wl_display_terminate(m_wlDisplay);
1014 extern "C" void WaylandBaseWindowSystem::bindDisplayClient(struct wl_display* display, uint32_t id, const char* interface, uint32_t version, void* data)
1016 LOG_DEBUG("WaylandBaseWindowSystem", "version " << version);
1017 WaylandBaseWindowSystem* windowsys = static_cast<WaylandBaseWindowSystem*>( (WaylandBaseWindowSystem*) data);
1022 ans_strcmp = strcmp(interface, "wl_compositor");
1023 if (0 == ans_strcmp)
1025 windowsys->m_wlCompositorClient = (wl_compositor*)wl_display_bind(display, id, &wl_compositor_interface);
1031 bool WaylandBaseWindowSystem::createWaylandClient()
1035 while (NULL == m_wlDisplayClient)
1038 LOG_DEBUG("WaylandBaseWindowSystem", "Waiting start wayland server");
1040 m_wlDisplayClient = wl_display_connect(NULL);
1043 LOG_DEBUG("WaylandBaseWindowSystem", "connect display");
1045 m_wlCompositorGlobalListener = wl_display_add_global_listener(m_wlDisplayClient, WaylandBaseWindowSystem::bindDisplayClient, this);
1046 if (NULL == m_wlCompositorGlobalListener)
1048 LOG_ERROR("WaylandBaseWindowSystem", "Waiting start wayland server");
1051 wl_display_iterate(m_wlDisplayClient, WL_DISPLAY_READABLE);
1052 wl_display_roundtrip(m_wlDisplayClient);
1054 m_wlSurfaceClient = wl_compositor_create_surface(m_wlCompositorClient);
1055 if (NULL == m_wlSurfaceClient)
1057 LOG_ERROR("WaylandBaseWindowSystem", "failed to create client surface");
1060 LOG_DEBUG("WaylandBaseWindowSystem", "create client surface");
1065 releaseWaylandClient();
1070 void WaylandBaseWindowSystem::releaseWaylandClient()
1072 if (NULL != m_wlSurfaceClient)
1074 wl_surface_destroy(m_wlSurfaceClient);
1075 m_wlSurfaceClient = NULL;
1077 if (NULL != m_wlCompositorClient)
1079 wl_compositor_destroy(m_wlCompositorClient);
1080 m_wlCompositorClient = NULL;
1082 if (NULL != m_wlDisplayClient)
1084 #if 0 // will add wayland version more than 0.85.0
1085 wl_display_disconnect(m_wlDisplayClient);
1087 m_wlDisplayClient = NULL;
1091 bool WaylandBaseWindowSystem::init(BaseGraphicSystem<void*, void*>* base)
1093 LOG_DEBUG("WaylandBaseWindowSystem", "init base:" << base);
1094 graphicSystem = base;
1095 int status = pthread_create(&renderThread, NULL, eventLoopCallback, (void*)this);
1101 while (false == m_initialized)
1103 usleep(10000); // TODO
1104 LOG_DEBUG("WaylandBaseWindowSystem","Waiting start compositor complete " << m_initialized);
1106 LOG_INFO("WaylandBaseWindowSystem","Start complete [connect display]" << m_initialized << " success " << m_success);
1110 bool WaylandBaseWindowSystem::start()
1113 LOG_DEBUG("WaylandBaseWindowSystem", "Starting / Creating thread");
1114 // let thread actually run
1115 if ( m_error == false )
1117 pthread_mutex_unlock(&run_lock);
1119 pthread_mutex_unlock(&run_lock);
1123 result = createWaylandClient();
1124 if (false == result)
1126 LOG_DEBUG("WaylandBaseWindowSystem", "Failed to create wayland client");
1132 void WaylandBaseWindowSystem::stop()
1134 LOG_INFO("WaylandBaseWindowSystem","Stopping..");
1135 // needed if start was never called, we wake up thread, so it can immediatly finish
1136 // this->signalRedrawEvent();
1138 releaseWaylandClient();
1140 pthread_mutex_unlock(&run_lock);
1141 pthread_join(renderThread, NULL);
1144 void WaylandBaseWindowSystem::allocatePlatformSurface(Surface* surface)
1146 LOG_INFO("WaylandBaseWindowSystem","allocatePlatformSurface begin");
1147 WaylandPlatformSurface* nativeSurface = (WaylandPlatformSurface*)surface->platform;
1150 LOG_DEBUG("WaylandBaseWindowSystem","creating native surface for new window");
1151 // this surface does not have a native platform surface attached yet!
1152 nativeSurface = (WaylandPlatformSurface*)graphicSystem->getTextureBinder()->createPlatformSurface(surface);
1153 if (0 != nativeSurface)
1155 unsigned int surfaceId = surface->getNativeContent();
1156 LOG_DEBUG("WaylandBaseWindowSystem","surface->getNativeContent()"<<surfaceId);
1157 nativeSurface->connectionId = (unsigned short)((surfaceId >> 16) & 0xFFFF);
1158 nativeSurface->surfaceId = (unsigned short)(surfaceId & 0xFFFF);
1159 surface->platform = nativeSurface;
1163 LOG_ERROR("WaylandBaseWindowSystem","failed to allocate platformsurface");
1166 LOG_INFO("WaylandBaseWindowSystem","allocatePlatformSurface end");
1169 void WaylandBaseWindowSystem::deallocatePlatformSurface(Surface* surface)
1171 LOG_DEBUG("WaylandBaseWindowSystem","deallocatePlatformSurface begin");
1172 WaylandPlatformSurface* nativeSurface = (WaylandPlatformSurface*)surface->platform;
1175 LOG_DEBUG("WaylandBaseWindowSystem","destroyingnative surface");
1177 graphicSystem->getTextureBinder()->destroyClientBuffer(surface);
1179 surface->renderPropertyChanged = true;
1180 delete surface->platform;
1181 surface->platform = NULL;
1184 LOG_DEBUG("WaylandBaseWindowSystem","deallocatePlatformSurface end");
1187 void WaylandBaseWindowSystem::doScreenShot(std::string fileName)
1189 m_takeScreenshot = ScreenshotOfDisplay;
1190 m_screenShotFile = fileName;
1193 void WaylandBaseWindowSystem::doScreenShotOfLayer(std::string fileName, const uint id)
1195 m_takeScreenshot = ScreenshotOfLayer;
1196 m_screenShotFile = fileName;
1197 m_screenShotLayerID = id;
1200 void WaylandBaseWindowSystem::doScreenShotOfSurface(std::string fileName, const uint id, const uint layer_id)
1202 m_takeScreenshot = ScreenshotOfSurface;
1203 m_screenShotFile = fileName;
1204 m_screenShotSurfaceID = id;
1205 m_screenShotLayerID = layer_id;