Add deletePending field for EGLSurface
This is specified in the spec:
https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglDestroySurface.xhtml
Also fix this bug:
b/63918908
Change-Id: I4aa5824d85e7f4394547ad0babfdf03a5f155544
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index ec1c186..01398ff 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -282,7 +282,7 @@
virtual void setCollectingTimestamps(EGLint collect) { }
virtual EGLint isCollectingTimestamps() const { return EGL_FALSE; }
-
+ EGLint deletePending;
private:
//
//Surface attributes
@@ -296,7 +296,6 @@
// Give it some default values.
int nativeWidth;
int nativeHeight;
-
protected:
void setWidth(EGLint w) { width = w; }
void setHeight(EGLint h) { height = h; }
@@ -308,7 +307,8 @@
};
egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
- : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0)
+ : dpy(dpy), config(config), surfaceType(surfaceType), rcSurface(0),
+ deletePending(0)
{
width = 0;
height = 0;
@@ -603,6 +603,29 @@
}
}
+// Destroy a pending surface and set it to NULL.
+
+static void s_destroyPendingSurfaceAndSetNull(EGLSurface* surface) {
+ egl_surface_t* surf = static_cast<egl_surface_t *>(*surface);
+ if (surf && surf->deletePending) {
+ delete surf;
+ *surface = NULL;
+ }
+}
+
+static void s_destroyPendingSurfacesInContext(EGLContext_t* context) {
+ if (context->read == context->draw) {
+ // If they are the same, delete it only once
+ s_destroyPendingSurfaceAndSetNull(&context->draw);
+ if (context->draw == NULL) {
+ context->read = NULL;
+ }
+ } else {
+ s_destroyPendingSurfaceAndSetNull(&context->draw);
+ s_destroyPendingSurfaceAndSetNull(&context->read);
+ }
+}
+
EGLBoolean egl_pbuffer_surface_t::init(GLenum pixelFormat)
{
DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
@@ -984,8 +1007,15 @@
VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
+ EGLThreadInfo* tInfo = getEGLThreadInfo();
egl_surface_t* surface(static_cast<egl_surface_t*>(eglSurface));
- delete surface;
+ if (tInfo->currentContext
+ && (tInfo->currentContext->draw == eglSurface
+ || tInfo->currentContext->read == eglSurface)) {
+ surface->deletePending = 1;
+ } else {
+ delete surface;
+ }
return EGL_TRUE;
}
@@ -1160,6 +1190,9 @@
// anyway once we are on the host, so skip rcMakeCurrent here.
// rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
context->flags &= ~EGLContext_t::IS_CURRENT;
+
+ s_destroyPendingSurfacesInContext(context);
+
if (context->deletePending) {
if (context->rcContext) {
rcEnc->rcDestroyContext(rcEnc, context->rcContext);
@@ -1516,20 +1549,20 @@
//
EGLThreadInfo *tInfo = getEGLThreadInfo();
- // we cannot use the following code block because of this bug:
- // b/63918908
+ if (tInfo->currentContext == context &&
+ (context == NULL ||
+ (context && context->draw == draw && context->read == read))) {
+ return EGL_TRUE;
+ }
- //if (tInfo->currentContext == context &&
- // (context == NULL ||
- // (context && context->draw == draw && context->read == read))) {
- // return EGL_TRUE;
- //}
+ if (tInfo->currentContext) {
+ EGLContext_t* prevCtx = tInfo->currentContext;
- if (tInfo->currentContext && tInfo->currentContext->deletePending) {
- if (tInfo->currentContext != context) {
- EGLContext_t * contextToDelete = tInfo->currentContext;
+ s_destroyPendingSurfacesInContext(tInfo->currentContext);
+
+ if (prevCtx->deletePending && prevCtx != context) {
tInfo->currentContext = 0;
- eglDestroyContext(dpy, contextToDelete);
+ eglDestroyContext(dpy, prevCtx);
}
}