cairo_t * MoonEGLContext::Push (Cairo extents) { Target *target = Top ()->GetTarget (); Target *cairo = target->GetCairoTarget (); Rect box; Top ()->GetClip (&box); box = box.Intersection (extents.r); if (box.IsEmpty ()) return Context::Push (extents); if (cairo) { Rect r = cairo->GetData (NULL); Region *region = new Region (r); if (region->RectIn (box) != CAIRO_REGION_OVERLAP_IN) { ForceCurrent (); SyncDrawable (); } delete region; } if (!target->GetCairoTarget ()) { MoonSurface *ms; Rect r = target->GetData (&ms); if (HasDrawable ()) { MoonEGLSurface *surface = new MoonEGLSurface (box.width, box.height); Target *cairo = new Target (surface, box); target->SetCairoTarget (cairo); cairo->unref (); surface->unref (); } else { // mark target contents as initialized target->SetInit (ms); } ms->unref (); } return Context::Push (extents); }
gboolean MoonWindowGtk::ExposeEvent (GtkWidget *w, GdkEventExpose *event) { SetCurrentDeployment (); if (!surface) return true; #ifdef USE_GLX Display *dpy = gdk_x11_drawable_get_xdisplay (w->window); XID win = gdk_x11_drawable_get_xid (w->window); _XxVisual *visual = GDK_VISUAL_XVISUAL (gdk_drawable_get_visual (w->window)); int width, height; gdk_drawable_get_size (w->window, &width, &height); if (!glxtarget && (moonlight_flags & RUNTIME_INIT_HW_ACCELERATION)) { GLXContext ctx = (GLXContext) 0; XVisualInfo templ, *visinfo; int n; templ.visualid = XVisualIDFromVisual (visual); visinfo = XGetVisualInfo (dpy, VisualIDMask, &templ, &n); g_assert (visinfo); ctx = glXCreateContext (dpy, visinfo, 0, True); if (ctx) { gdk_error_trap_push (); glXMakeCurrent (dpy, win, ctx); gdk_flush (); if (gdk_error_trap_pop ()) { g_warning ("Failed to make GLX context current for window: " "0x%x", (int) win); glXDestroyContext (dpy, ctx); ctx = (GLXContext) 0; } } else { g_warning ("Failed to create GLX context for VisualID: 0x%x", (int) XVisualIDFromVisual (visual)); } glxtarget = new MoonGLXSurface (); if (ctx) { OpenGLContext *context = new MoonGLXContext (glxtarget, dpy, ctx); if (context->Initialize ()) { const char *extensions = (const char *) glXGetClientString (dpy, GLX_EXTENSIONS); if (strstr (extensions, "GLX_MESA_copy_sub_buffer")) glxcopysubbuffer = glxtarget->GetProcAddress ("glXCopySubBufferMESA"); glxctx = context; } else { glXDestroyContext (dpy, ctx); delete context; } } } if (glxtarget && glxctx) { Rect r0 = Rect (0, 0, width, height); Rect r = Rect (event->area.x, event->area.y, event->area.width, event->area.height); Region *region = new Region (r); int y = height - (event->area.y + event->area.height); glXMakeCurrent (dpy, win, static_cast<MoonGLXContext *> (glxctx)->GetGLXContext ()); glxtarget->Reshape (width, height); glxctx->Push (Context::Clip (r)); surface->Paint (glxctx, region, GetTransparent (), true); glxctx->Pop (); glxctx->Flush (); if (region->RectIn (r0) == CAIRO_REGION_OVERLAP_IN) { glXSwapBuffers (dpy, win); } else if (glxcopysubbuffer) { PFNGLXCOPYSUBBUFFERPROC glXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERPROC) glxcopysubbuffer; glXCopySubBufferMESA (dpy, win, event->area.x, y, event->area.width, event->area.height); } else { glDrawBuffer (GL_FRONT); glViewport (-1, -1, 2, 2); glRasterPos2f (0, 0); glViewport (0, 0, width, height); glBitmap (0, 0, 0, 0, event->area.x, y, NULL); glCopyPixels (event->area.x, y, event->area.width, event->area.height, GL_COLOR); glDrawBuffer (GL_BACK); glFlush (); } return true; } #endif // we draw to a backbuffer pixmap, then transfer the contents // to the widget's window. if (backing_store == NULL || backing_store_width < (event->area.x + event->area.width) || backing_store_height < (event->area.y + event->area.height)) { if (backing_store) g_object_unref (backing_store); if (backing_store_gc) g_object_unref (backing_store_gc); if (backing_image_data) { g_free (backing_image_data); backing_image_data = NULL; } #if FULLSCREEN_BACKING_STORE_SOPTIMIZATION if (IsFullScreen ()) { backing_store_width = MAX (event->area.x + event->area.width, 1); backing_store_height = MAX (event->area.y + event->area.height, 1); } else #endif { backing_store_width = MAX (GetWidth(), 1); backing_store_height = MAX (GetHeight(), 1); } backing_store = gdk_pixmap_new (w->window, backing_store_width, backing_store_height, -1); backing_store_gc = gdk_gc_new (backing_store); } PaintToDrawable (backing_store, gdk_drawable_get_visual (w->window), event, - event->area.x, - event->area.y, GetTransparent (), true); gdk_gc_set_clip_region (backing_store_gc, event->region); gdk_draw_drawable (w->window, backing_store_gc, backing_store, 0, 0, event->area.x, event->area.y, event->area.width, event->area.height); #if FULLSCREEN_BACKING_STORE_SOPTIMIZATION if (IsFullScreen ()) { g_object_unref (backing_store); backing_store = NULL; g_object_unref (backing_store_gc); backing_store_gc = NULL; backing_store_width = backing_store_height = 0; } #endif return true; }
/** * @fn gboolean ExposeEvent (GtkWidget *w, cairo_t *cr) * @brief event handler for expose event * @param w GtkWidget * * @param cr cairo_t * * @return gboolean */ gboolean MoonWindowGtk::ExposeEvent (GtkWidget *w, cairo_t *cr) { SetCurrentDeployment (); if (!surface) return true; GtkAllocation allocation; gtk_widget_get_allocation (widget, &allocation); #ifdef USE_GLX Display *dpy = GDK_WINDOW_XDISPLAY (gtk_widget_get_window(w)); XID win = gdk_x11_window_get_xid (gtk_widget_get_window(w)); _XxVisual *visual = GDK_VISUAL_XVISUAL (gdk_window_get_visual (gtk_widget_get_window(w))); int width, height; width=gdk_window_get_width (gtk_widget_get_window(w)); height=gdk_window_get_height (gtk_widget_get_window(w)); if (!glxtarget && (moonlight_flags & RUNTIME_INIT_HW_ACCELERATION)) { GLXContext ctx = (GLXContext) 0; XVisualInfo templ, *visinfo; int n; templ.visualid = XVisualIDFromVisual (visual); visinfo = XGetVisualInfo (dpy, VisualIDMask, &templ, &n); g_assert (visinfo); ctx = glXCreateContext (dpy, visinfo, 0, True); if (ctx) { gdk_error_trap_push (); glXMakeCurrent (dpy, win, ctx); gdk_flush (); if (gdk_error_trap_pop ()) { g_warning ("Failed to make GLX context current for window: " "0x%x", (int) win); glXDestroyContext (dpy, ctx); ctx = (GLXContext) 0; } } else { g_warning ("Failed to create GLX context for VisualID: 0x%x", (int) XVisualIDFromVisual (visual)); } glxtarget = new MoonGLXSurface (); if (ctx) { OpenGLContext *context = new MoonGLXContext (glxtarget, dpy, ctx); if (context->Initialize ()) { const char *extensions = (const char *) glXGetClientString (dpy, GLX_EXTENSIONS); if (strstr (extensions, "GLX_MESA_copy_sub_buffer")) glxcopysubbuffer = glxtarget->GetProcAddress ("glXCopySubBufferMESA"); glxctx = context; } else { glXDestroyContext (dpy, ctx); delete context; } } } if (glxtarget && glxctx) { cairo_rectangle_int_t area; Rect r0 = Rect (0, 0, width, height); Rect r = Rect (area.x, area.y, area.width, area.height); Region *region = new Region (r); int y = height - (area.y + area.height); glXMakeCurrent (dpy, win, static_cast<MoonGLXContext *> (glxctx)->GetGLXContext ()); glxtarget->Reshape (width, height); glxctx->Push (Context::Clip (r)); surface->Paint (glxctx, region, GetTransparent (), true); glxctx->Pop (); glxctx->Flush (); if (region->RectIn (r0) == CAIRO_REGION_OVERLAP_IN) { glXSwapBuffers (dpy, win); } else if (glxcopysubbuffer) { PFNGLXCOPYSUBBUFFERPROC glXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERPROC) glxcopysubbuffer; glXCopySubBufferMESA (dpy, win, area.x, y, area.width, area.height); } else { glDrawBuffer (GL_FRONT); glViewport (-1, -1, 2, 2); glRasterPos2f (0, 0); glViewport (0, 0, width, height); glBitmap (0, 0, 0, 0, area.x, y, NULL); glCopyPixels (area.x, y, area.width, area.height, GL_COLOR); glDrawBuffer (GL_BACK); glFlush (); } return true; } #endif PaintToDrawable (gdk_window_get_visual (gtk_widget_get_window(w)), cr, allocation, GetTransparent (), true); return true; }