static EGLBoolean dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, EGLint numRects, const EGLint *rects) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); EGLBoolean ret; xcb_xfixes_region_t region; xcb_rectangle_t rectangles[16]; int i; if (numRects > (int)ARRAY_SIZE(rectangles)) return dri2_copy_region(drv, disp, draw, dri2_surf->region); for (i = 0; i < numRects; i++) { rectangles[i].x = rects[i * 4]; rectangles[i].y = dri2_surf->base.Height - rects[i * 4 + 1] - rects[i * 4 + 3]; rectangles[i].width = rects[i * 4 + 2]; rectangles[i].height = rects[i * 4 + 3]; } region = xcb_generate_id(dri2_dpy->conn); xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles); ret = dri2_copy_region(drv, disp, draw, region); xcb_xfixes_destroy_region(dri2_dpy->conn, region); return ret; }
static int64_t dri2_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, int64_t msc, int64_t divisor, int64_t remainder) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); uint32_t msc_hi = msc >> 32; uint32_t msc_lo = msc & 0xffffffff; uint32_t divisor_hi = divisor >> 32; uint32_t divisor_lo = divisor & 0xffffffff; uint32_t remainder_hi = remainder >> 32; uint32_t remainder_lo = remainder & 0xffffffff; xcb_dri2_swap_buffers_cookie_t cookie; xcb_dri2_swap_buffers_reply_t *reply; int64_t swap_count = -1; /* No-op for a pixmap or pbuffer surface */ if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) return 0; if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available) return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; if (dri2_dpy->flush) (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable, msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo); reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL); if (reply) { swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo; free(reply); } /* Since we aren't watching for the server's invalidate events like we're * supposed to (due to XCB providing no mechanism for filtering the events * the way xlib does), and SwapBuffers is a common cause of invalidate * events, just shove one down to the driver, even though we haven't told * the driver that we're the kind of loader that provides reliable * invalidate events. This causes the driver to request buffers again at * its next draw, so that we get the correct buffers if a pageflip * happened. The driver should still be using the viewport hack to catch * window resizes. */ if (dri2_dpy->flush && dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate) (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); return swap_count; }
static EGLBoolean dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); if (dri2_dpy->dri2) { return dri2_copy_region(drv, disp, draw, dri2_surf->region); } else { assert(dri2_dpy->swrast); dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); return EGL_TRUE; } }
static int64_t dri2_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, int64_t msc, int64_t divisor, int64_t remainder) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); uint32_t msc_hi = msc >> 32; uint32_t msc_lo = msc & 0xffffffff; uint32_t divisor_hi = divisor >> 32; uint32_t divisor_lo = divisor & 0xffffffff; uint32_t remainder_hi = remainder >> 32; uint32_t remainder_lo = remainder & 0xffffffff; xcb_dri2_swap_buffers_cookie_t cookie; xcb_dri2_swap_buffers_reply_t *reply; int64_t swap_count = -1; /* No-op for a pixmap or pbuffer surface */ if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT) return 0; if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available) return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1; if (dri2_dpy->flush) (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable, msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo); reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL); if (reply) { swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo; free(reply); } return swap_count; }