From b4b4a37b2b905b44a8c9691004ec767efb443056 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Thu, 9 Mar 2023 09:20:01 +1100 Subject: [PATCH] [client] egl: switch to using GL_TEXTURE_EXTERNAL_OES for DMABUF According to Erik @ NVidia the open source NVidia driver will not create a EGLImage from a DMABUF if the target is not GL_TEXTURE_EXTERNAL_OES. This change set converts the dmabuf texture from GL_TEXTURE_2D to GL_TEXTURE_EXTERNAL_OES and at runtime performs a global search & replace on fragment shaders as needed to remain compatible, replacing `sampler2D` with `samplerExternalOES`. Ref: https://github.com/NVIDIA/open-gpu-kernel-modules/discussions/243#discussioncomment-3283415 --- client/renderers/EGL/cursor.c | 2 +- client/renderers/EGL/damage.c | 3 +- client/renderers/EGL/desktop.c | 62 +++++++++----- client/renderers/EGL/filter.h | 19 +++-- client/renderers/EGL/filter_downscale.c | 85 +++++++++++-------- client/renderers/EGL/filter_ffx_cas.c | 48 ++++++----- client/renderers/EGL/filter_ffx_fsr1.c | 57 ++++++++----- client/renderers/EGL/framebuffer.c | 6 +- client/renderers/EGL/framebuffer.h | 2 +- client/renderers/EGL/postprocess.c | 17 ++-- client/renderers/EGL/postprocess.h | 4 +- client/renderers/EGL/shader.c | 68 ++++++++++++++- client/renderers/EGL/shader.h | 5 +- client/renderers/EGL/shader/compat.h | 15 ++-- client/renderers/EGL/shader/desktop_rgb.frag | 6 ++ client/renderers/EGL/shader/downscale.frag | 8 +- .../EGL/shader/downscale_lanczos2.frag | 8 +- .../EGL/shader/downscale_linear.frag | 6 +- client/renderers/EGL/shader/ffx_cas.frag | 8 +- .../renderers/EGL/shader/ffx_fsr1_easu.frag | 21 ++--- .../renderers/EGL/shader/ffx_fsr1_rcas.frag | 6 +- client/renderers/EGL/texture.c | 11 +-- client/renderers/EGL/texture.h | 3 + client/renderers/EGL/texture_buffer.c | 19 ++++- client/renderers/EGL/texture_buffer.h | 1 + client/renderers/EGL/texture_dmabuf.c | 59 +++++++++++-- client/renderers/EGL/texture_framebuffer.c | 3 +- 27 files changed, 372 insertions(+), 180 deletions(-) diff --git a/client/renderers/EGL/cursor.c b/client/renderers/EGL/cursor.c index 4228697f..b856c706 100644 --- a/client/renderers/EGL/cursor.c +++ b/client/renderers/EGL/cursor.c @@ -100,7 +100,7 @@ static bool cursorTexInit(struct CursorTex * t, } if (!egl_shaderCompile(t->shader, - vertex_code, vertex_size, fragment_code, fragment_size)) + vertex_code, vertex_size, fragment_code, fragment_size, false)) { DEBUG_ERROR("Failed to compile the cursor shader"); return false; diff --git a/client/renderers/EGL/damage.c b/client/renderers/EGL/damage.c index e0cad82a..8eb769ac 100644 --- a/client/renderers/EGL/damage.c +++ b/client/renderers/EGL/damage.c @@ -76,7 +76,8 @@ bool egl_damageInit(EGL_Damage ** damage) if (!egl_shaderCompile((*damage)->shader, b_shader_damage_vert, b_shader_damage_vert_size, - b_shader_damage_frag, b_shader_damage_frag_size)) + b_shader_damage_frag, b_shader_damage_frag_size, + false)) { DEBUG_ERROR("Failed to compile the damage shader"); return false; diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index ba2ad761..b2c607c4 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -46,6 +46,7 @@ struct DesktopShader EGL_Shader * shader; GLint uTransform; GLint uDesktopSize; + GLint uSamplerType; GLint uScaleAlgo; GLint uNVGain; GLint uCBMode; @@ -57,7 +58,7 @@ struct EGL_Desktop EGLDisplay * display; EGL_Texture * texture; - struct DesktopShader shader; + struct DesktopShader dmaShader, shader; EGL_DesktopRects * mesh; CountedBuffer * matrix; @@ -92,7 +93,8 @@ void toggleNV(int key, void * opaque); static bool egl_initDesktopShader( struct DesktopShader * shader, const char * vertex_code , size_t vertex_size, - const char * fragment_code, size_t fragment_size + const char * fragment_code, size_t fragment_size, + bool useDMA ) { if (!egl_shaderInit(&shader->shader)) @@ -100,7 +102,8 @@ static bool egl_initDesktopShader( if (!egl_shaderCompile(shader->shader, vertex_code , vertex_size, - fragment_code, fragment_size)) + fragment_code, fragment_size, + useDMA)) { return false; } @@ -135,15 +138,6 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display, return false; } - if (!egl_initDesktopShader( - &desktop->shader, - b_shader_desktop_vert , b_shader_desktop_vert_size, - b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size)) - { - DEBUG_ERROR("Failed to initialize the generic desktop shader"); - return false; - } - if (!egl_desktopRectsInit(&desktop->mesh, maxRects)) { DEBUG_ERROR("Failed to initialize the desktop mesh"); @@ -157,6 +151,27 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display, return false; } + if (!egl_initDesktopShader( + &desktop->shader, + b_shader_desktop_vert , b_shader_desktop_vert_size, + b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size, + false)) + { + DEBUG_ERROR("Failed to initialize the desktop shader"); + return false; + } + + if (useDMA) + if (!egl_initDesktopShader( + &desktop->dmaShader, + b_shader_desktop_vert , b_shader_desktop_vert_size, + b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size, + true)) + { + DEBUG_ERROR("Failed to initialize the desktop DMA shader"); + return false; + } + app_registerKeybind(0, 'N', toggleNV, desktop, "Toggle night vision mode"); @@ -205,11 +220,12 @@ void egl_desktopFree(EGL_Desktop ** desktop) if (!*desktop) return; - egl_textureFree (&(*desktop)->texture ); - egl_textureFree (&(*desktop)->spiceTexture ); - egl_shaderFree (&(*desktop)->shader.shader); - egl_desktopRectsFree(&(*desktop)->mesh ); - countedBufferRelease(&(*desktop)->matrix ); + egl_textureFree (&(*desktop)->texture ); + egl_textureFree (&(*desktop)->spiceTexture ); + egl_shaderFree (&(*desktop)->shader .shader); + egl_shaderFree (&(*desktop)->dmaShader.shader); + egl_desktopRectsFree(&(*desktop)->mesh ); + countedBufferRelease(&(*desktop)->matrix ); egl_postProcessFree(&(*desktop)->pp); @@ -399,18 +415,17 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, if (atomic_exchange(&desktop->processFrame, false) || egl_postProcessConfigModified(desktop->pp)) egl_postProcessRun(desktop->pp, tex, desktop->mesh, - width, height, outputWidth, outputHeight); + width, height, outputWidth, outputHeight, desktop->useDMA); unsigned int finalSizeX, finalSizeY; - GLuint texture = egl_postProcessGetOutput(desktop->pp, + EGL_Texture * texture = egl_postProcessGetOutput(desktop->pp, &finalSizeX, &finalSizeY); glBindFramebuffer(GL_FRAMEBUFFER, 0); egl_resetViewport(desktop->egl); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); - glBindSampler(0, tex->sampler); + egl_textureBind(texture); if (finalSizeX > width || finalSizeY > height) scaleType = EGL_DESKTOP_DOWNSCALE; @@ -435,7 +450,10 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, scaleAlgo = desktop->scaleAlgo; } - const struct DesktopShader * shader = &desktop->shader; + const struct DesktopShader * shader = + desktop->useDMA && texture == desktop->texture ? + &desktop->dmaShader : &desktop->shader; + EGL_Uniform uniforms[] = { { diff --git a/client/renderers/EGL/filter.h b/client/renderers/EGL/filter.h index b03bd886..62aa5534 100644 --- a/client/renderers/EGL/filter.h +++ b/client/renderers/EGL/filter.h @@ -68,9 +68,11 @@ typedef struct EGL_FilterOps /* reads filter state from options */ void (*loadState)(EGL_Filter * filter); - /* set the input format of the filter */ + /* set the input format of the filter + * useDMA will be true if the texture provided needs to use samplerExternalOES + */ bool (*setup)(EGL_Filter * filter, enum EGL_PixelFormat pixFmt, - unsigned int width, unsigned int height); + unsigned int width, unsigned int height, bool useDMA); /* set the output resolution hint for the filter * this is optional and only a hint */ @@ -87,8 +89,8 @@ typedef struct EGL_FilterOps /* runs the filter on the provided texture * returns the processed texture as the output */ - GLuint (*run)(EGL_Filter * filter, EGL_FilterRects * rects, - GLuint texture); + EGL_Texture * (*run)(EGL_Filter * filter, EGL_FilterRects * rects, + EGL_Texture * texture); /* called when the filter output is no loger needed so it can release memory * this is optional */ @@ -133,9 +135,10 @@ static inline void egl_filterLoadState(EGL_Filter * filter) } static inline bool egl_filterSetup(EGL_Filter * filter, - enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height) + enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height, + bool useDMA) { - return filter->ops.setup(filter, pixFmt, width, height); + return filter->ops.setup(filter, pixFmt, width, height, useDMA); } static inline void egl_filterSetOutputResHint(EGL_Filter * filter, @@ -156,8 +159,8 @@ static inline bool egl_filterPrepare(EGL_Filter * filter) return filter->ops.prepare(filter); } -static inline GLuint egl_filterRun(EGL_Filter * filter, - EGL_FilterRects * rects, GLuint texture) +static inline EGL_Texture * egl_filterRun(EGL_Filter * filter, + EGL_FilterRects * rects, EGL_Texture * texture) { return filter->ops.run(filter, rects, texture); } diff --git a/client/renderers/EGL/filter_downscale.c b/client/renderers/EGL/filter_downscale.c index 43be4be4..df9b0062 100644 --- a/client/renderers/EGL/filter_downscale.c +++ b/client/renderers/EGL/filter_downscale.c @@ -60,6 +60,7 @@ typedef struct EGL_FilterDownscale EGL_Shader * lanczos2; DownscaleFilter filter; + int useDMA; enum EGL_PixelFormat pixFmt; unsigned int width, height; float pixelSize; @@ -157,55 +158,26 @@ static bool egl_filterDownscaleInit(EGL_Filter ** filter) return false; } + this->useDMA = -1; + if (!egl_shaderInit(&this->nearest)) { DEBUG_ERROR("Failed to initialize the shader"); goto error_this; } - if (!egl_shaderCompile(this->nearest, - b_shader_basic_vert , b_shader_basic_vert_size, - b_shader_downscale_frag, b_shader_downscale_frag_size) - ) - { - DEBUG_ERROR("Failed to compile the shader"); - goto error_shader; - } - if (!egl_shaderInit(&this->linear)) { DEBUG_ERROR("Failed to initialize the shader"); goto error_this; } - if (!egl_shaderCompile(this->linear, - b_shader_basic_vert, b_shader_basic_vert_size, - b_shader_downscale_linear_frag, b_shader_downscale_linear_frag_size) - ) - { - DEBUG_ERROR("Failed to compile the shader"); - goto error_shader; - } - if (!egl_shaderInit(&this->lanczos2)) { DEBUG_ERROR("Failed to initialize the shader"); goto error_this; } - if (!egl_shaderCompile(this->lanczos2, - b_shader_basic_vert, b_shader_basic_vert_size, - b_shader_downscale_lanczos2_frag, b_shader_downscale_lanczos2_frag_size) - ) - { - DEBUG_ERROR("Failed to compile the shader"); - goto error_shader; - } - - this->uNearest.type = EGL_UNIFORM_TYPE_3F; - this->uNearest.location = - egl_shaderGetUniform(this->nearest, "uConfig"); - if (!egl_framebufferInit(&this->fb)) { DEBUG_ERROR("Failed to initialize the framebuffer"); @@ -326,7 +298,8 @@ static bool egl_filterDownscaleImguiConfig(EGL_Filter * filter) } static bool egl_filterDownscaleSetup(EGL_Filter * filter, - enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height) + enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height, + bool useDMA) { EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter); @@ -336,6 +309,48 @@ static bool egl_filterDownscaleSetup(EGL_Filter * filter, if (!this->enable) return false; + if (this->useDMA != useDMA) + { + if (!egl_shaderCompile(this->nearest, + b_shader_basic_vert , b_shader_basic_vert_size, + b_shader_downscale_frag, + b_shader_downscale_frag_size, + useDMA) + ) + { + DEBUG_ERROR("Failed to compile the shader"); + return false; + } + + if (!egl_shaderCompile(this->linear, + b_shader_basic_vert, b_shader_basic_vert_size, + b_shader_downscale_linear_frag, + b_shader_downscale_linear_frag_size, + useDMA) + ) + { + DEBUG_ERROR("Failed to compile the shader"); + return false; + } + + if (!egl_shaderCompile(this->lanczos2, + b_shader_basic_vert, b_shader_basic_vert_size, + b_shader_downscale_lanczos2_frag, + b_shader_downscale_lanczos2_frag_size, + useDMA) + ) + { + DEBUG_ERROR("Failed to compile the shader"); + return false; + } + + this->uNearest.type = EGL_UNIFORM_TYPE_3F; + this->uNearest.location = + egl_shaderGetUniform(this->nearest, "uConfig"); + + this->useDMA = useDMA; + } + if (this->prepared && pixFmt == this->pixFmt && this->width == width && @@ -385,15 +400,15 @@ static bool egl_filterDownscalePrepare(EGL_Filter * filter) return true; } -static GLuint egl_filterDownscaleRun(EGL_Filter * filter, - EGL_FilterRects * rects, GLuint texture) +static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter, + EGL_FilterRects * rects, EGL_Texture * texture) { EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter); egl_framebufferBind(this->fb); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); + egl_textureBind(texture); EGL_Shader * shader; diff --git a/client/renderers/EGL/filter_ffx_cas.c b/client/renderers/EGL/filter_ffx_cas.c index 866525b2..e7eaac30 100644 --- a/client/renderers/EGL/filter_ffx_cas.c +++ b/client/renderers/EGL/filter_ffx_cas.c @@ -37,6 +37,7 @@ typedef struct EGL_FilterFFXCAS EGL_Shader * shader; bool enable; + int useDMA; enum EGL_PixelFormat pixFmt; unsigned int width, height; float sharpness; @@ -106,21 +107,14 @@ static bool egl_filterFFXCASInit(EGL_Filter ** filter) return false; } + this->useDMA = -1; + if (!egl_shaderInit(&this->shader)) { DEBUG_ERROR("Failed to initialize the shader"); goto error_this; } - if (!egl_shaderCompile(this->shader, - b_shader_basic_vert , b_shader_basic_vert_size, - b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size) - ) - { - DEBUG_ERROR("Failed to compile the shader"); - goto error_shader; - } - this->consts = countedBufferNew(8 * sizeof(GLuint)); if (!this->consts) { @@ -128,12 +122,6 @@ static bool egl_filterFFXCASInit(EGL_Filter ** filter) goto error_shader; } - egl_shaderSetUniforms(this->shader, &(EGL_Uniform) { - .type = EGL_UNIFORM_TYPE_4UIV, - .location = egl_shaderGetUniform(this->shader, "uConsts"), - .v = this->consts, - }, 1); - egl_filterFFXCASLoadState(&this->base); if (!egl_framebufferInit(&this->fb)) @@ -220,13 +208,35 @@ static bool egl_filterFFXCASImguiConfig(EGL_Filter * filter) } static bool egl_filterFFXCASSetup(EGL_Filter * filter, - enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height) + enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height, + bool useDMA) { EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter); if (!this->enable) return false; + if (this->useDMA != useDMA) + { + if (!egl_shaderCompile(this->shader, + b_shader_basic_vert , b_shader_basic_vert_size, + b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size, + useDMA) + ) + { + DEBUG_ERROR("Failed to compile the shader"); + return false; + } + + egl_shaderSetUniforms(this->shader, &(EGL_Uniform) { + .type = EGL_UNIFORM_TYPE_4UIV, + .location = egl_shaderGetUniform(this->shader, "uConsts"), + .v = this->consts, + }, 1); + + this->useDMA = useDMA; + } + if (pixFmt == this->pixFmt && this->width == width && this->height == height) return true; @@ -262,15 +272,15 @@ static bool egl_filterFFXCASPrepare(EGL_Filter * filter) return true; } -static GLuint egl_filterFFXCASRun(EGL_Filter * filter, - EGL_FilterRects * rects, GLuint texture) +static EGL_Texture * egl_filterFFXCASRun(EGL_Filter * filter, + EGL_FilterRects * rects, EGL_Texture * texture) { EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter); egl_framebufferBind(this->fb); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); + egl_textureBind(texture); glBindSampler(0, this->sampler); egl_shaderUse(this->shader); diff --git a/client/renderers/EGL/filter_ffx_fsr1.c b/client/renderers/EGL/filter_ffx_fsr1.c index 3dbabacc..7887bc22 100644 --- a/client/renderers/EGL/filter_ffx_fsr1.c +++ b/client/renderers/EGL/filter_ffx_fsr1.c @@ -42,6 +42,7 @@ typedef struct EGL_FilterFFXFSR1 CountedBuffer * consts; EGL_Uniform easuUniform[2], rcasUniform; + int useDMA; enum EGL_PixelFormat pixFmt; unsigned int width, height; unsigned int inWidth, inHeight; @@ -109,6 +110,8 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter) return false; } + this->useDMA = -1; + if (!egl_shaderInit(&this->easu)) { DEBUG_ERROR("Failed to initialize the Easu shader"); @@ -121,18 +124,10 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter) goto error_esau; } - if (!egl_shaderCompile(this->easu, - b_shader_basic_vert , b_shader_basic_vert_size, - b_shader_ffx_fsr1_easu_frag, b_shader_ffx_fsr1_easu_frag_size) - ) - { - DEBUG_ERROR("Failed to compile the Easu shader"); - goto error_rcas; - } - if (!egl_shaderCompile(this->rcas, b_shader_basic_vert , b_shader_basic_vert_size, - b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size) + b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size, + false) ) { DEBUG_ERROR("Failed to compile the Rcas shader"); @@ -148,14 +143,6 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter) egl_filterFFXFSR1LoadState(&this->base); - this->easuUniform[0].type = EGL_UNIFORM_TYPE_4UIV; - this->easuUniform[0].location = - egl_shaderGetUniform(this->easu, "uConsts"); - this->easuUniform[0].v = this->consts; - this->easuUniform[1].type = EGL_UNIFORM_TYPE_2F; - this->easuUniform[1].location = - egl_shaderGetUniform(this->easu, "uOutRes"); - this->rcasUniform.type = EGL_UNIFORM_TYPE_4UI; this->rcasUniform.location = egl_shaderGetUniform(this->rcas, "uConsts"); rcasUpdateUniform(this); @@ -335,13 +322,37 @@ static void egl_filterFFXFSR1SetOutputResHint(EGL_Filter * filter, } static bool egl_filterFFXFSR1Setup(EGL_Filter * filter, - enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height) + enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height, + bool useDMA) { EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter); if (!this->enable) return false; + if (this->useDMA != useDMA) + { + if (!egl_shaderCompile(this->easu, + b_shader_basic_vert , b_shader_basic_vert_size, + b_shader_ffx_fsr1_easu_frag, b_shader_ffx_fsr1_easu_frag_size, + useDMA) + ) + { + DEBUG_ERROR("Failed to compile the Easu shader"); + return false; + } + + this->easuUniform[0].type = EGL_UNIFORM_TYPE_4UIV; + this->easuUniform[0].location = + egl_shaderGetUniform(this->easu, "uConsts"); + this->easuUniform[0].v = this->consts; + this->easuUniform[1].type = EGL_UNIFORM_TYPE_2F; + this->easuUniform[1].location = + egl_shaderGetUniform(this->easu, "uOutRes"); + + this->useDMA = useDMA; + } + this->active = this->width > width && this->height > height; if (!this->active) return false; @@ -395,15 +406,15 @@ static bool egl_filterFFXFSR1Prepare(EGL_Filter * filter) return true; } -static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter, - EGL_FilterRects * rects, GLuint texture) +static EGL_Texture * egl_filterFFXFSR1Run(EGL_Filter * filter, + EGL_FilterRects * rects, EGL_Texture * texture) { EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter); // pass 1, Easu egl_framebufferBind(this->easuFb); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); + egl_textureBind(texture); glBindSampler(0, this->sampler); egl_shaderUse(this->easu); egl_filterRectsRender(this->easu, rects); @@ -412,7 +423,7 @@ static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter, // pass 2, Rcas egl_framebufferBind(this->rcasFb); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); + egl_textureBind(texture); glBindSampler(0, this->sampler); egl_shaderUse(this->rcas); egl_filterRectsRender(this->rcas, rects); diff --git a/client/renderers/EGL/framebuffer.c b/client/renderers/EGL/framebuffer.c index 0ad54159..f5a1ca09 100644 --- a/client/renderers/EGL/framebuffer.c +++ b/client/renderers/EGL/framebuffer.c @@ -100,9 +100,7 @@ void egl_framebufferBind(EGL_Framebuffer * this) glViewport(0, 0, this->tex->format.width, this->tex->format.height); } -GLuint egl_framebufferGetTexture(EGL_Framebuffer * this) +EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this) { - GLuint output; - egl_textureGet(this->tex, &output, NULL, NULL); - return output; + return this->tex; } diff --git a/client/renderers/EGL/framebuffer.h b/client/renderers/EGL/framebuffer.h index dd8b779d..8899a431 100644 --- a/client/renderers/EGL/framebuffer.h +++ b/client/renderers/EGL/framebuffer.h @@ -32,4 +32,4 @@ bool egl_framebufferSetup(EGL_Framebuffer * this, enum EGL_PixelFormat pixFmt, void egl_framebufferBind(EGL_Framebuffer * this); -GLuint egl_framebufferGetTexture(EGL_Framebuffer * this); +EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this); diff --git a/client/renderers/EGL/postprocess.c b/client/renderers/EGL/postprocess.c index ca4c703c..9634115e 100644 --- a/client/renderers/EGL/postprocess.c +++ b/client/renderers/EGL/postprocess.c @@ -49,7 +49,7 @@ static const EGL_FilterOps * EGL_Filters[] = struct EGL_PostProcess { Vector filters; - GLuint output; + EGL_Texture * output; unsigned int outputX, outputY; _Atomic(bool) modified; @@ -606,7 +606,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this) bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, EGL_DesktopRects * rects, int desktopWidth, int desktopHeight, - unsigned int targetX, unsigned int targetY) + unsigned int targetX, unsigned int targetY, bool useDMA) { if (targetX == 0 && targetY == 0) DEBUG_FATAL("targetX || targetY == 0"); @@ -614,8 +614,9 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, EGL_Filter * lastFilter = NULL; unsigned int sizeX, sizeY; - GLuint texture; - if (egl_textureGet(tex, &texture, &sizeX, &sizeY) != EGL_TEX_STATUS_OK) + //TODO: clean this up + GLuint _unused; + if (egl_textureGet(tex, &_unused, &sizeX, &sizeY) != EGL_TEX_STATUS_OK) return false; if (atomic_exchange(&this->modified, false)) @@ -636,11 +637,12 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, }; EGL_Filter * filter; + EGL_Texture * texture = tex; vector_forEach(filter, &this->filters) { egl_filterSetOutputResHint(filter, targetX, targetY); - if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY) || + if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY, useDMA) || !egl_filterPrepare(filter)) continue; @@ -651,6 +653,9 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, egl_filterRelease(lastFilter); lastFilter = filter; + + // the first filter to run will convert to a normal texture + useDMA = false; } this->output = texture; @@ -659,7 +664,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, return true; } -GLuint egl_postProcessGetOutput(EGL_PostProcess * this, +EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this, unsigned int * outputX, unsigned int * outputY) { *outputX = this->outputX; diff --git a/client/renderers/EGL/postprocess.h b/client/renderers/EGL/postprocess.h index 8550b482..601c53d9 100644 --- a/client/renderers/EGL/postprocess.h +++ b/client/renderers/EGL/postprocess.h @@ -41,7 +41,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this); * targetX/Y is the final target output dimension hint if scalers are present */ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, EGL_DesktopRects * rects, int desktopWidth, int desktopHeight, - unsigned int targetX, unsigned int targetY); + unsigned int targetX, unsigned int targetY, bool useDMA); -GLuint egl_postProcessGetOutput(EGL_PostProcess * this, +EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this, unsigned int * outputX, unsigned int * outputY); diff --git a/client/renderers/EGL/shader.c b/client/renderers/EGL/shader.c index 7f0f8d97..d75f4939 100644 --- a/client/renderers/EGL/shader.c +++ b/client/renderers/EGL/shader.c @@ -64,7 +64,8 @@ void egl_shaderFree(EGL_Shader ** shader) *shader = NULL; } -bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fragment_file) +bool egl_shaderLoad(EGL_Shader * this, + const char * vertex_file, const char * fragment_file, bool useDMA) { char * vertex_code, * fragment_code; size_t vertex_size, fragment_size; @@ -86,13 +87,16 @@ bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fr DEBUG_INFO("Loaded fragment shader: %s", fragment_file); - bool ret = egl_shaderCompile(this, vertex_code, vertex_size, fragment_code, fragment_size); + bool ret = egl_shaderCompile(this, + vertex_code, vertex_size, fragment_code, fragment_size, + useDMA); + free(vertex_code); free(fragment_code); return ret; } -bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, +static bool shaderCompile(EGL_Shader * this, const char * vertex_code, size_t vertex_size, const char * fragment_code, size_t fragment_size) { if (this->hasShader) @@ -204,6 +208,64 @@ bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, return true; } +bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, + size_t vertex_size, const char * fragment_code, size_t fragment_size, + bool useDMA) +{ + if (useDMA) + { + const char * search = "sampler2D"; + const char * replace = "samplerExternalOES"; + + const char * src = fragment_code; + int instances = 0; + while((src = strstr(src, search))) + { + ++instances; + src += strlen(search); + } + + const int diff = (strlen(replace) - strlen(search)) * instances; + char * newCode = malloc(fragment_size + diff); + if (!newCode) + { + DEBUG_ERROR("Out of memory"); + return false; + } + + src = fragment_code; + char * dst = newCode; + for(int i = 0; i < instances; ++i) + { + const char * pos = strstr(src, search); + const int offset = pos - src; + + memcpy(dst, src, offset); + dst += offset; + src = pos + strlen(search); + + memcpy(dst, replace, strlen(replace)); + dst += strlen(replace); + } + + const int final = fragment_size - (src - fragment_code); + memcpy(dst, src, final); + dst[final] = 0; + + bool result = shaderCompile( + this, + vertex_code, vertex_size, + newCode , fragment_size + diff); + + free(newCode); + return result; + } + + return shaderCompile(this, + vertex_code , vertex_size, + fragment_code, fragment_size); +} + void egl_shaderSetUniforms(EGL_Shader * this, EGL_Uniform * uniforms, int count) { egl_shaderFreeUniforms(this); diff --git a/client/renderers/EGL/shader.h b/client/renderers/EGL/shader.h index 94da1b2c..b8f0a113 100644 --- a/client/renderers/EGL/shader.h +++ b/client/renderers/EGL/shader.h @@ -97,10 +97,11 @@ bool egl_shaderInit(EGL_Shader ** shader); void egl_shaderFree(EGL_Shader ** shader); bool egl_shaderLoad(EGL_Shader * model, const char * vertex_file, - const char * fragment_file); + const char * fragment_file, bool useDMA); bool egl_shaderCompile(EGL_Shader * model, const char * vertex_code, - size_t vertex_size, const char * fragment_code, size_t fragment_size); + size_t vertex_size, const char * fragment_code, size_t fragment_size, + bool useDMA); void egl_shaderSetUniforms(EGL_Shader * shader, EGL_Uniform * uniforms, int count); diff --git a/client/renderers/EGL/shader/compat.h b/client/renderers/EGL/shader/compat.h index 49958876..a960216a 100644 --- a/client/renderers/EGL/shader/compat.h +++ b/client/renderers/EGL/shader/compat.h @@ -1,16 +1,21 @@ #if __VERSION__ == 300 vec4 textureGather(sampler2D tex, vec2 uv, int comp) { - vec4 c0 = textureOffset(tex, uv, ivec2(0,1)); - vec4 c1 = textureOffset(tex, uv, ivec2(1,1)); - vec4 c2 = textureOffset(tex, uv, ivec2(1,0)); - vec4 c3 = textureOffset(tex, uv, ivec2(0,0)); + vec2 res = vec2(textureSize(tex, 0)); + ivec2 p = ivec2((uv * res) - 0.5f); + + // NOTE: we can't use texelFecthOffset because sampler2D may actually be samplerExternalOES + vec4 c0 = texelFetch(tex, p+ivec2(0,1), 0); + vec4 c1 = texelFetch(tex, p+ivec2(1,1), 0); + vec4 c2 = texelFetch(tex, p+ivec2(1,0), 0); + vec4 c3 = texelFetch(tex, p+ivec2(0,0), 0); + return vec4(c0[comp], c1[comp], c2[comp],c3[comp]); } #elif __VERSION__ < 300 vec4 textureGather(sampler2D tex, vec2 uv, int comp) { - vec4 c3 = texture2D(tex, uv); + vec4 c3 = texture(tex, uv); return vec4(c3[comp], c3[comp], c3[comp],c3[comp]); } #endif diff --git a/client/renderers/EGL/shader/desktop_rgb.frag b/client/renderers/EGL/shader/desktop_rgb.frag index ed4ec1ad..2b54747f 100644 --- a/client/renderers/EGL/shader/desktop_rgb.frag +++ b/client/renderers/EGL/shader/desktop_rgb.frag @@ -1,4 +1,6 @@ #version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable + precision highp float; #define EGL_SCALE_AUTO 0 @@ -23,13 +25,17 @@ void main() switch (scaleAlgo) { case EGL_SCALE_NEAREST: + { vec2 ts = vec2(textureSize(sampler1, 0)); color = texelFetch(sampler1, ivec2(uv * ts), 0); break; + } case EGL_SCALE_LINEAR: + { color = texture(sampler1, uv); break; + } } if (cbMode > 0) diff --git a/client/renderers/EGL/shader/downscale.frag b/client/renderers/EGL/shader/downscale.frag index 2561ed7e..1aa60870 100644 --- a/client/renderers/EGL/shader/downscale.frag +++ b/client/renderers/EGL/shader/downscale.frag @@ -1,10 +1,12 @@ #version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable + precision highp float; in vec2 fragCoord; out vec4 fragColor; -uniform sampler2D texture; +uniform sampler2D sampler1; uniform vec3 uConfig; void main() @@ -13,7 +15,7 @@ void main() float vOffset = uConfig.y; float hOffset = uConfig.z; - vec2 inRes = vec2(textureSize(texture, 0)); + vec2 inRes = vec2(textureSize(sampler1, 0)); ivec2 point = ivec2( (floor((fragCoord * inRes) / pixelSize) * pixelSize) + pixelSize / 2.0f @@ -22,5 +24,5 @@ void main() point.x += int(pixelSize * hOffset); point.y += int(pixelSize * vOffset); - fragColor = texelFetch(texture, point, 0); + fragColor = texelFetch(sampler1, point, 0); } diff --git a/client/renderers/EGL/shader/downscale_lanczos2.frag b/client/renderers/EGL/shader/downscale_lanczos2.frag index 08675f56..e6f81ac7 100644 --- a/client/renderers/EGL/shader/downscale_lanczos2.frag +++ b/client/renderers/EGL/shader/downscale_lanczos2.frag @@ -1,4 +1,6 @@ #version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable + precision highp float; #define PI 3.141592653589793 @@ -6,7 +8,7 @@ precision highp float; in vec2 fragCoord; out vec4 fragColor; -uniform sampler2D texture; +uniform sampler2D sampler1; float sinc(float x) { return x == 0.0 ? 1.0 : sin(x * PI) / (x * PI); @@ -24,7 +26,7 @@ float lanczos(vec2 v) void main() { - vec2 size = vec2(textureSize(texture, 0)); + vec2 size = vec2(textureSize(sampler1, 0)); vec2 pos = fragCoord * size; vec2 invSize = 1.0 / size; vec2 uvc = floor(pos) + vec2(0.5, 0.5); @@ -54,7 +56,7 @@ void main() vec3 color = vec3(0.0); for (int i = 0; i < 9; ++i) - color += texture2D(texture, uvs[i] * invSize).rgb * factors[i]; + color += texture(sampler1, uvs[i] * invSize).rgb * factors[i]; fragColor = vec4(color, 1.0); } diff --git a/client/renderers/EGL/shader/downscale_linear.frag b/client/renderers/EGL/shader/downscale_linear.frag index e345c0e2..9e599acd 100644 --- a/client/renderers/EGL/shader/downscale_linear.frag +++ b/client/renderers/EGL/shader/downscale_linear.frag @@ -1,12 +1,14 @@ #version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable + precision highp float; in vec2 fragCoord; out vec4 fragColor; -uniform sampler2D texture; +uniform sampler2D sampler1; void main() { - fragColor = texture2D(texture, fragCoord); + fragColor = texture(sampler1, fragCoord); } diff --git a/client/renderers/EGL/shader/ffx_cas.frag b/client/renderers/EGL/shader/ffx_cas.frag index 5e799b2d..49fc6261 100644 --- a/client/renderers/EGL/shader/ffx_cas.frag +++ b/client/renderers/EGL/shader/ffx_cas.frag @@ -1,4 +1,6 @@ #version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable + precision highp float; #include "compat.h" @@ -6,7 +8,7 @@ precision highp float; in vec2 fragCoord; out vec4 fragColor; -uniform sampler2D texture; +uniform sampler2D sampler1; uniform uvec4 uConsts[2]; #define A_GPU 1 @@ -16,7 +18,7 @@ uniform uvec4 uConsts[2]; vec3 imageLoad(ivec2 point) { - return texelFetch(texture, point, 0).rgb; + return texelFetch(sampler1, point, 0).rgb; } AF3 CasLoad(ASU2 p) @@ -30,7 +32,7 @@ void CasInput(inout AF1 r,inout AF1 g,inout AF1 b) {} void main() { - vec2 res = vec2(textureSize(texture, 0)); + vec2 res = vec2(textureSize(sampler1, 0)); uvec2 point = uvec2(fragCoord * res); CasFilter( diff --git a/client/renderers/EGL/shader/ffx_fsr1_easu.frag b/client/renderers/EGL/shader/ffx_fsr1_easu.frag index 2812a1cd..1d7da825 100644 --- a/client/renderers/EGL/shader/ffx_fsr1_easu.frag +++ b/client/renderers/EGL/shader/ffx_fsr1_easu.frag @@ -1,4 +1,6 @@ #version 300 es +#extension GL_OES_EGL_image_external_essl3 : enable + precision highp float; #include "compat.h" @@ -6,7 +8,7 @@ precision highp float; in vec2 fragCoord; out vec4 fragColor; -uniform sampler2D texture; +uniform sampler2D sampler1; uniform vec2 uOutRes; uniform uvec4 uConsts[4]; @@ -18,20 +20,9 @@ uniform uvec4 uConsts[4]; #define FSR_EASU_F 1 -vec4 _textureGather(sampler2D tex, vec2 uv, int comp) -{ - vec2 res = vec2(textureSize(tex, 0)); - ivec2 p = ivec2((uv * res) - 0.5f); - vec4 c0 = texelFetchOffset(tex, p, 0, ivec2(0,1)); - vec4 c1 = texelFetchOffset(tex, p, 0, ivec2(1,1)); - vec4 c2 = texelFetchOffset(tex, p, 0, ivec2(1,0)); - vec4 c3 = texelFetchOffset(tex, p, 0, ivec2(0,0)); - return vec4(c0[comp], c1[comp], c2[comp],c3[comp]); -} - -AF4 FsrEasuRF(AF2 p){return AF4(_textureGather(texture, p, 0));} -AF4 FsrEasuGF(AF2 p){return AF4(_textureGather(texture, p, 1));} -AF4 FsrEasuBF(AF2 p){return AF4(_textureGather(texture, p, 2));} +AF4 FsrEasuRF(AF2 p){return AF4(textureGather(sampler1, p, 0));} +AF4 FsrEasuGF(AF2 p){return AF4(textureGather(sampler1, p, 1));} +AF4 FsrEasuBF(AF2 p){return AF4(textureGather(sampler1, p, 2));} #include "ffx_fsr1.h" diff --git a/client/renderers/EGL/shader/ffx_fsr1_rcas.frag b/client/renderers/EGL/shader/ffx_fsr1_rcas.frag index b7dc4881..6233e889 100644 --- a/client/renderers/EGL/shader/ffx_fsr1_rcas.frag +++ b/client/renderers/EGL/shader/ffx_fsr1_rcas.frag @@ -6,7 +6,7 @@ precision highp float; in vec2 fragCoord; out vec4 fragColor; -uniform sampler2D texture; +uniform sampler2D sampler1; uniform uvec4 uConsts; #define A_GPU 1 @@ -15,7 +15,7 @@ uniform uvec4 uConsts; #include "ffx_a.h" -AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(texture, ASU2(p), 0); } +AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(sampler1, ASU2(p), 0); } void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {} #define FSR_RCAS_F 1 @@ -24,7 +24,7 @@ void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {} void main() { - vec2 inRes = vec2(textureSize(texture, 0)); + vec2 inRes = vec2(textureSize(sampler1, 0)); uvec2 point = uvec2(fragCoord * (inRes + 0.5f)); FsrRcasF(fragColor.r, fragColor.g, fragColor.b, point, uConsts); diff --git a/client/renderers/EGL/texture.c b/client/renderers/EGL/texture.c index b1f2fbf7..7b58a2f9 100644 --- a/client/renderers/EGL/texture.c +++ b/client/renderers/EGL/texture.c @@ -25,6 +25,7 @@ #include "shader.h" #include "common/framebuffer.h" #include "common/debug.h" +#include "common/array.h" #include #include @@ -76,6 +77,7 @@ bool egl_textureInit(EGL_Texture ** texture_, EGLDisplay * display, glSamplerParameteri(this->sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE); glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE); + return true; } @@ -203,14 +205,7 @@ enum EGL_TexStatus egl_textureProcess(EGL_Texture * this) enum EGL_TexStatus egl_textureBind(EGL_Texture * this) { - GLuint tex; - EGL_TexStatus status; - - if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK) - return status; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tex); glBindSampler(0, this->sampler); - return EGL_TEX_STATUS_OK; + return this->ops.bind(this); } diff --git a/client/renderers/EGL/texture.h b/client/renderers/EGL/texture.h index 43cb20f8..146123ee 100644 --- a/client/renderers/EGL/texture.h +++ b/client/renderers/EGL/texture.h @@ -93,6 +93,9 @@ typedef struct EGL_TextureOps /* get the texture for use */ enum EGL_TexStatus (*get)(EGL_Texture * texture, GLuint * tex); + + /* bind the texture for use */ + enum EGL_TexStatus (*bind)(EGL_Texture * texture); } EGL_TextureOps; diff --git a/client/renderers/EGL/texture_buffer.c b/client/renderers/EGL/texture_buffer.c index d42c601d..ed74c3f8 100644 --- a/client/renderers/EGL/texture_buffer.c +++ b/client/renderers/EGL/texture_buffer.c @@ -292,6 +292,19 @@ EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex) return EGL_TEX_STATUS_OK; } +EGL_TexStatus egl_texBufferBind(EGL_Texture * texture) +{ + GLuint tex; + EGL_TexStatus status; + + if ((status = texture->ops.get(texture, &tex)) != EGL_TEX_STATUS_OK) + return status; + + glBindTexture(GL_TEXTURE_2D, tex); + return EGL_TEX_STATUS_OK; +} + + const EGL_TextureOps EGL_TextureBuffer = { .init = egl_texBufferInit, @@ -299,7 +312,8 @@ const EGL_TextureOps EGL_TextureBuffer = .setup = egl_texBufferSetup, .update = egl_texBufferUpdate, .process = egl_texBufferProcess, - .get = egl_texBufferGet + .get = egl_texBufferGet, + .bind = egl_texBufferBind }; const EGL_TextureOps EGL_TextureBufferStream = @@ -309,5 +323,6 @@ const EGL_TextureOps EGL_TextureBufferStream = .setup = egl_texBufferStreamSetup, .update = egl_texBufferStreamUpdate, .process = egl_texBufferStreamProcess, - .get = egl_texBufferStreamGet + .get = egl_texBufferStreamGet, + .bind = egl_texBufferBind }; diff --git a/client/renderers/EGL/texture_buffer.h b/client/renderers/EGL/texture_buffer.h index 4b364126..0c8fc252 100644 --- a/client/renderers/EGL/texture_buffer.h +++ b/client/renderers/EGL/texture_buffer.h @@ -48,6 +48,7 @@ void egl_texBufferFree(EGL_Texture * texture_); bool egl_texBufferSetup(EGL_Texture * texture_, const EGL_TexSetup * setup); EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture_); EGL_TexStatus egl_texBufferGet(EGL_Texture * texture_, GLuint * tex); +EGL_TexStatus egl_texBufferBind(EGL_Texture * texture_); bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type, EGLDisplay * display); diff --git a/client/renderers/EGL/texture_dmabuf.c b/client/renderers/EGL/texture_dmabuf.c index 32d4b25c..52197125 100644 --- a/client/renderers/EGL/texture_dmabuf.c +++ b/client/renderers/EGL/texture_dmabuf.c @@ -46,12 +46,26 @@ EGL_TextureOps EGL_TextureDMABUF; // internal functions -static void egl_texDMABUFCleanup(TexDMABUF * this) +static void egl_texDMABUFCleanup(EGL_Texture * texture) { + TextureBuffer * parent = UPCAST(TextureBuffer, texture); + TexDMABUF * this = UPCAST(TexDMABUF , parent); + struct FdImage * image; vector_forEachRef(image, &this->images) g_egl_dynProcs.eglDestroyImage(this->display, image->image); vector_clear(&this->images); + + egl_texUtilFreeBuffers(parent->buf, parent->texCount); + + if (parent->tex[0]) + glDeleteTextures(parent->texCount, parent->tex); + + if (parent->sync) + { + glDeleteSync(parent->sync); + parent->sync = 0; + } } // dmabuf functions @@ -92,7 +106,7 @@ static void egl_texDMABUFFree(EGL_Texture * texture) TextureBuffer * parent = UPCAST(TextureBuffer, texture); TexDMABUF * this = UPCAST(TexDMABUF , parent); - egl_texDMABUFCleanup(this); + egl_texDMABUFCleanup(texture); vector_destroy(&this->images); egl_texBufferFree(&parent->base); @@ -102,11 +116,27 @@ static void egl_texDMABUFFree(EGL_Texture * texture) static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup) { TextureBuffer * parent = UPCAST(TextureBuffer, texture); - TexDMABUF * this = UPCAST(TexDMABUF , parent); - egl_texDMABUFCleanup(this); + egl_texDMABUFCleanup(texture); - return egl_texBufferSetup(&parent->base, setup); + glGenTextures(parent->texCount, parent->tex); + for(int i = 0; i < parent->texCount; ++i) + { + glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[i]); + glTexImage2D(GL_TEXTURE_EXTERNAL_OES, + 0, + texture->format.intFormat, + texture->format.width, + texture->format.height, + 0, + texture->format.format, + texture->format.dataType, + NULL); + } + + glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); + parent->rIndex = -1; + return true; } static bool egl_texDMABUFUpdate(EGL_Texture * texture, @@ -173,8 +203,8 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture, INTERLOCKED_SECTION(parent->copyLock, { - glBindTexture(GL_TEXTURE_2D, parent->tex[parent->bufIndex]); - g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[parent->bufIndex]); + g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image); if (parent->sync) glDeleteSync(parent->sync); @@ -238,6 +268,18 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex) return EGL_TEX_STATUS_OK; } +static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture) +{ + GLuint tex; + EGL_TexStatus status; + + if ((status = egl_texDMABUFGet(texture, &tex)) != EGL_TEX_STATUS_OK) + return status; + + glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); + return EGL_TEX_STATUS_OK; +} + EGL_TextureOps EGL_TextureDMABUF = { .init = egl_texDMABUFInit, @@ -245,5 +287,6 @@ EGL_TextureOps EGL_TextureDMABUF = .setup = egl_texDMABUFSetup, .update = egl_texDMABUFUpdate, .process = egl_texDMABUFProcess, - .get = egl_texDMABUFGet + .get = egl_texDMABUFGet, + .bind = egl_texDMABUFBind }; diff --git a/client/renderers/EGL/texture_framebuffer.c b/client/renderers/EGL/texture_framebuffer.c index 9d1d656f..922d6da7 100644 --- a/client/renderers/EGL/texture_framebuffer.c +++ b/client/renderers/EGL/texture_framebuffer.c @@ -147,5 +147,6 @@ EGL_TextureOps EGL_TextureFrameBuffer = .setup = egl_texFBSetup, .update = egl_texFBUpdate, .process = egl_texBufferStreamProcess, - .get = egl_texBufferStreamGet + .get = egl_texBufferStreamGet, + .bind = egl_texBufferBind };