diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2010-05-06 22:01:35 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2010-05-13 20:30:45 -0400 |
commit | 52c554a79d3ed3104a9f7d112faa9129073b5a25 (patch) | |
tree | d4b4f76dd045425751065b0679131ba3d8a5350b /src/egl/drivers/dri2 | |
parent | 13ef7a4be8ecfd87a09ef1cfa48348297ed7b0e3 (diff) |
egl: Implement EGL_NOK_swap_region
This extension adds a new function which provides an alternative to
eglSwapBuffers. eglSwapBuffersRegionNOK accepts two new parameters in
addition to those in eglSwapBuffers. The new parameters consist of a
pointer to a list of 4-integer blocks defining rectangles (x, y,
width, height) and an integer specifying the number of rectangles in
the list.
Diffstat (limited to 'src/egl/drivers/dri2')
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 6386737376..82f409d294 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -51,6 +51,8 @@ #include "eglsurface.h" #include "eglimage.h" +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + struct dri2_egl_driver { _EGLDriver base; @@ -778,6 +780,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, disp->Extensions.KHR_image_pixmap = EGL_TRUE; disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; + disp->Extensions.NOK_swap_region = EGL_TRUE; /* we're supporting EGL 1.4 */ *major = 1; @@ -1067,7 +1070,8 @@ dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, } static EGLBoolean -dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) +dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp, + _EGLSurface *draw, xcb_xfixes_region_t region) { struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); @@ -1099,7 +1103,7 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn, dri2_surf->drawable, - dri2_surf->region, + region, XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT); free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL)); @@ -1107,6 +1111,44 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) return EGL_TRUE; } +static EGLBoolean +dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) +{ + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); + + return dri2_copy_region(drv, disp, draw, dri2_surf->region); +} + +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 > ARRAY_SIZE(rectangles)) + return dri2_copy_region(drv, disp, draw, dri2_surf->region); + + /* FIXME: Invert y here? */ + for (i = 0; i < numRects; i++) { + rectangles[i].x = rects[i * 4]; + rectangles[i].y = rects[i * 4 + 1]; + 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; +} + /* * Called from eglGetProcAddress() via drv->API.GetProcAddress(). */ @@ -1415,6 +1457,7 @@ _eglMain(const char *args) dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; + dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region; dri2_drv->base.Name = "DRI2"; dri2_drv->base.Unload = dri2_unload; |