summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2010-05-06 22:01:35 -0400
committerKristian Høgsberg <krh@bitplanet.net>2010-05-13 20:30:45 -0400
commit52c554a79d3ed3104a9f7d112faa9129073b5a25 (patch)
treed4b4f76dd045425751065b0679131ba3d8a5350b
parent13ef7a4be8ecfd87a09ef1cfa48348297ed7b0e3 (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.
-rw-r--r--include/EGL/eglext.h12
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c47
-rw-r--r--src/egl/main/eglapi.c32
-rw-r--r--src/egl/main/eglapi.h7
-rw-r--r--src/egl/main/egldisplay.h1
-rw-r--r--src/egl/main/eglmisc.c1
6 files changed, 98 insertions, 2 deletions
diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
index a9e598d6dd..61626d20df 100644
--- a/include/EGL/eglext.h
+++ b/include/EGL/eglext.h
@@ -227,6 +227,18 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOPYCONTEXTMESA) (EGLDisplay dpy, EGLCont
#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
#endif
+
+#ifndef EGL_NOK_swap_region
+#define EGL_NOK_swap_region 1
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint* rects);
+#endif
+
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint* rects);
+#endif
+
+
#ifdef __cplusplus
}
#endif
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;
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index f57dda8883..923992da48 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -838,6 +838,9 @@ eglGetProcAddress(const char *procname)
{ "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
{ "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
#endif /* EGL_KHR_image_base */
+#ifdef EGL_NOK_swap_region
+ { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
+#endif
{ NULL, NULL }
};
EGLint i;
@@ -1246,3 +1249,32 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
#endif /* EGL_KHR_image_base */
+
+
+#ifdef EGL_NOK_swap_region
+
+EGLBoolean
+eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
+ EGLint numRects, const EGLint *rects)
+{
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSurface *surf = _eglLookupSurface(surface, disp);
+ _EGLDriver *drv;
+ EGLBoolean ret;
+
+ _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+
+ /* surface must be bound to current context in EGL 1.4 */
+ if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
+ RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
+
+ if (drv->API.SwapBuffersRegionNOK)
+ ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
+ else
+ ret = drv->API.SwapBuffers(drv, disp, surf);
+
+ RETURN_EGL_EVAL(disp, ret);
+}
+
+#endif /* EGL_NOK_swap_region */
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 3e2ba8dd41..d8c8b49a49 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -76,6 +76,9 @@ typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLCo
typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
#endif /* EGL_KHR_image_base */
+#ifdef EGL_NOK_swap_region
+typedef EGLBoolean (*SwapBuffersRegionNOK_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint numRects, const EGLint *rects);
+#endif
/**
* The API dispatcher jumps through these functions
@@ -134,6 +137,10 @@ struct _egl_api
CreateImageKHR_t CreateImageKHR;
DestroyImageKHR_t DestroyImageKHR;
#endif /* EGL_KHR_image_base */
+
+#ifdef EGL_NOK_swap_region
+ SwapBuffersRegionNOK_t SwapBuffersRegionNOK;
+#endif
};
#endif /* EGLAPI_INCLUDED */
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 21bf22b5fe..0b7f9d8303 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -46,6 +46,7 @@ struct _egl_extensions
EGLBoolean KHR_gl_texture_cubemap_image;
EGLBoolean KHR_gl_texture_3D_image;
EGLBoolean KHR_gl_renderbuffer_image;
+ EGLBoolean NOK_swap_region;
char String[_EGL_MAX_EXTENSIONS_LEN];
};
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 984e426686..82ddb6cad9 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -96,6 +96,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
_EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
_EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
+ _EGL_CHECK_EXTENSION(NOK_swap_region);
#undef _EGL_CHECK_EXTENSION
}