diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 3b2984a8e..25f76076a 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -176,6 +176,15 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EG #define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 #endif +#ifndef EGL_KHR_partial_update +#define EGL_KHR_partial_update 1 +#define EGL_BUFFER_AGE_KHR 0x313D +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_KHR_partial_update */ + #ifndef EGL_NV_coverage_sample #define EGL_NV_coverage_sample 1 #define EGL_COVERAGE_BUFFERS_NV 0x30E0 @@ -440,6 +449,14 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC)(EGLDisplay dpy, E /* No tokens/entry points, just relaxes an error condition */ #endif +#ifndef EGL_KHR_swap_buffers_with_damage +#define EGL_KHR_swap_buffers_with_damage 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_KHR_swap_buffers_with_damage */ + #ifdef EGL_KHR_stream /* Requires KHR_stream extension */ #ifndef EGL_KHR_stream_cross_process_fd #define EGL_KHR_stream_cross_process_fd 1 diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 11a13c311..f5b90dd84 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -80,6 +80,7 @@ struct extention_map_t { extern char const * const gBuiltinExtensionString = "EGL_KHR_get_all_proc_addresses " "EGL_ANDROID_presentation_time " + "EGL_KHR_swap_buffers_with_damage " ; extern char const * const gExtensionString = "EGL_KHR_image " // mandatory @@ -100,6 +101,8 @@ extern char const * const gExtensionString = "EGL_ANDROID_image_native_buffer " // mandatory "EGL_KHR_wait_sync " // strongly recommended "EGL_ANDROID_recordable " // mandatory + "EGL_KHR_partial_update " // strongly recommended + "EGL_EXT_buffer_age " // strongly recommended with partial_update ; // extensions not exposed to applications but used by the ANDROID system @@ -152,6 +155,14 @@ static const extention_map_t sExtensionMap[] = { // EGL_ANDROID_presentation_time { "eglPresentationTimeANDROID", (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, + + // EGL_KHR_swap_buffers_with_damage + { "eglSwapBuffersWithDamageKHR", + (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR }, + + // EGL_KHR_partial_update + { "eglSetDamageRegionKHR", + (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR }, }; /* @@ -1021,7 +1032,8 @@ private: Mutex mMutex; }; -EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) +EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, + EGLint *rects, EGLint n_rects) { ATRACE_CALL(); clearError(); @@ -1080,7 +1092,38 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) } } - return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); + if (n_rects == 0) { + return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); + } + + Vector androidRects; + for (int r = 0; r < n_rects; ++r) { + int offset = r * 4; + int x = rects[offset]; + int y = rects[offset + 1]; + int width = rects[offset + 2]; + int height = rects[offset + 3]; + android_native_rect_t androidRect; + androidRect.left = x; + androidRect.top = y + height; + androidRect.right = x + width; + androidRect.bottom = y; + androidRects.push_back(androidRect); + } + native_window_set_surface_damage(s->win.get(), androidRects.array(), + androidRects.size()); + + if (s->cnx->egl.eglSwapBuffersWithDamageKHR) { + return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface, + rects, n_rects); + } else { + return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); + } +} + +EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) +{ + return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0); } EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, @@ -1569,3 +1612,32 @@ EGLuint64NV eglGetSystemTimeNV() return setErrorQuiet(EGL_BAD_DISPLAY, 0); } + +// ---------------------------------------------------------------------------- +// Partial update extension +// ---------------------------------------------------------------------------- +EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, + EGLint *rects, EGLint n_rects) +{ + clearError(); + + const egl_display_ptr dp = validate_display(dpy); + if (!dp) { + setError(EGL_BAD_DISPLAY, EGL_FALSE); + return EGL_FALSE; + } + + SurfaceRef _s(dp.get(), surface); + if (!_s.get()) { + setError(EGL_BAD_SURFACE, EGL_FALSE); + return EGL_FALSE; + } + + egl_surface_t const * const s = get_surface(surface); + if (s->cnx->egl.eglSetDamageRegionKHR) { + return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface, + rects, n_rects); + } + + return EGL_FALSE; +} diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in index 70d0e52fd..1e27cb64f 100644 --- a/opengl/libs/EGL/egl_entries.in +++ b/opengl/libs/EGL/egl_entries.in @@ -89,4 +89,9 @@ EGL_ENTRY(EGLuint64NV, eglGetSystemTimeNV, void) /* IMG extensions */ EGL_ENTRY(EGLBoolean, eglHibernateProcessIMG, void) -EGL_ENTRY(EGLBoolean, eglAwakenProcessIMG, void) \ No newline at end of file +EGL_ENTRY(EGLBoolean, eglAwakenProcessIMG, void) + +/* Partial update extensions */ + +EGL_ENTRY(EGLBoolean, eglSwapBuffersWithDamageKHR, EGLDisplay, EGLSurface, EGLint *, EGLint) +EGL_ENTRY(EGLBoolean, eglSetDamageRegionKHR, EGLDisplay, EGLSurface, EGLint *, EGLint)