From 9b87f4ba5e20048f17ab73fbefd18223e2c20e58 Mon Sep 17 00:00:00 2001 From: Quantum Date: Sun, 8 Aug 2021 06:11:01 -0400 Subject: [PATCH] [client] egl: cycle through multiple textures for dmabuf This avoids race conditions in GL drivers when attempting to render and call glEGLImageTargetTexture2DOES on the same texture. Also, when using glEGLImageTargetTexture2DOES, we do not need to allocate storage for textures. --- client/renderers/EGL/texture_dmabuf.c | 73 ++++++++++++++++++++------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/client/renderers/EGL/texture_dmabuf.c b/client/renderers/EGL/texture_dmabuf.c index 63fcfffd..0279bfd0 100644 --- a/client/renderers/EGL/texture_dmabuf.c +++ b/client/renderers/EGL/texture_dmabuf.c @@ -63,7 +63,7 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGLDisplay * display) *texture = &this->base.base; EGL_Texture * parent = &this->base.base; - if (!egl_texBufferInit(&parent, display)) + if (!egl_texBufferStreamInit(&parent, display)) { free(this); *texture = NULL; @@ -93,21 +93,7 @@ static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup egl_texDMABUFCleanup(this); - if (!egl_texBufferSetup(&parent->base, setup)) - return false; - - glBindTexture(GL_TEXTURE_2D, parent->tex[0]); - glTexImage2D(GL_TEXTURE_2D, - 0, - texture->format.intFormat, - texture->format.width, - texture->format.height, - 0, - texture->format.format, - texture->format.dataType, - NULL); - - return true; + return egl_texBufferSetup(&parent->base, setup); } static bool egl_texDMABUFUpdate(EGL_Texture * texture, @@ -172,8 +158,17 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture, this->images[index].image = image; } - glBindTexture(GL_TEXTURE_2D, parent->tex[0]); - g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + INTERLOCKED_SECTION(parent->copyLock, + { + glBindTexture(GL_TEXTURE_2D, parent->tex[parent->bufIndex]); + g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + + if (parent->sync) + glDeleteSync(parent->sync); + + parent->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + }); + glFlush(); return true; } @@ -185,8 +180,48 @@ static EGL_TexStatus egl_texDMABUFProcess(EGL_Texture * texture) static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex) { TextureBuffer * parent = UPCAST(TextureBuffer, texture); + GLsync sync = 0; - *tex = parent->tex[0]; + INTERLOCKED_SECTION(parent->copyLock, + { + if (parent->sync) + { + sync = parent->sync; + parent->sync = 0; + parent->rIndex = parent->bufIndex; + if (++parent->bufIndex == parent->texCount) + parent->bufIndex = 0; + } + }); + + if (sync) + { + switch(glClientWaitSync(sync, 0, 20000000)) // 20ms + { + case GL_ALREADY_SIGNALED: + case GL_CONDITION_SATISFIED: + glDeleteSync(sync); + break; + + case GL_TIMEOUT_EXPIRED: + INTERLOCKED_SECTION(parent->copyLock, + { + if (!parent->sync) + parent->sync = sync; + else + glDeleteSync(sync); + }); + return EGL_TEX_STATUS_NOTREADY; + + case GL_WAIT_FAILED: + case GL_INVALID_VALUE: + glDeleteSync(sync); + DEBUG_GL_ERROR("glClientWaitSync failed"); + return EGL_TEX_STATUS_ERROR; + } + } + + *tex = parent->tex[parent->rIndex]; return EGL_TEX_STATUS_OK; }