From 43a3fb0db3f0b44156a676b0249d316ad51ff580 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Tue, 21 Nov 2023 11:57:25 +1100 Subject: [PATCH] [client] egl: RGB24 improvements This patch performs several changes. * Alters the fourcc codes to types that ignore the alpha channel where possible to allow the gpu to internally use 24-bit formats. * Attempts to use DRM_FORMAT_RGB888 first as some GPUs may support this * If DMABUF is not in use the data is now imported directly as RGB24 without the post-processing shader --- client/renderers/EGL/desktop.c | 5 -- client/renderers/EGL/egltypes.h | 3 +- client/renderers/EGL/filter_24bit.c | 2 +- client/renderers/EGL/framebuffer.c | 2 +- client/renderers/EGL/postprocess.c | 6 +- client/renderers/EGL/texture.h | 9 +- client/renderers/EGL/texture_buffer.c | 8 +- client/renderers/EGL/texture_buffer.h | 6 +- client/renderers/EGL/texture_dmabuf.c | 125 +++++++++++++++++++------- client/renderers/EGL/texture_util.c | 13 ++- client/renderers/EGL/texture_util.h | 8 +- 11 files changed, 129 insertions(+), 58 deletions(-) diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index edc494f3..1cac84de 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -346,11 +346,6 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format) case FRAME_TYPE_RGB_24: pixFmt = EGL_PF_RGB_24; - // the data width is correct per the format, but we are going to use a - // 32-bit texture to load the data, so we need to alter the width for the - // different bpp - desktop->format.dataWidth = - desktop->format.pitch / 4; break; default: diff --git a/client/renderers/EGL/egltypes.h b/client/renderers/EGL/egltypes.h index a0bbc52d..f8248123 100644 --- a/client/renderers/EGL/egltypes.h +++ b/client/renderers/EGL/egltypes.h @@ -39,7 +39,8 @@ typedef enum EGL_PixelFormat EGL_PF_RGBA10, EGL_PF_RGBA16F, EGL_PF_BGR_32, - EGL_PF_RGB_24 + EGL_PF_RGB_24, + EGL_PF_RGB_24_32 } EGL_PixelFormat; diff --git a/client/renderers/EGL/filter_24bit.c b/client/renderers/EGL/filter_24bit.c index 775be98c..4d14d46f 100644 --- a/client/renderers/EGL/filter_24bit.c +++ b/client/renderers/EGL/filter_24bit.c @@ -112,7 +112,7 @@ static bool egl_filter24bitSetup(EGL_Filter * filter, { EGL_Filter24bit * this = UPCAST(EGL_Filter24bit, filter); - if (pixFmt != EGL_PF_BGR_32 && pixFmt != EGL_PF_RGB_24) + if (pixFmt != EGL_PF_BGR_32 && pixFmt != EGL_PF_RGB_24_32) return false; if (this->useDMA != useDMA || this->format != pixFmt) diff --git a/client/renderers/EGL/framebuffer.c b/client/renderers/EGL/framebuffer.c index 667354c6..d18fc566 100644 --- a/client/renderers/EGL/framebuffer.c +++ b/client/renderers/EGL/framebuffer.c @@ -72,7 +72,7 @@ bool egl_framebufferSetup(EGL_Framebuffer * this, enum EGL_PixelFormat pixFmt, } GLuint tex; - egl_textureGet(this->tex, &tex, NULL, NULL); + egl_textureGet(this->tex, &tex, NULL, NULL, NULL); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/client/renderers/EGL/postprocess.c b/client/renderers/EGL/postprocess.c index 5485ab6c..29074b0a 100644 --- a/client/renderers/EGL/postprocess.c +++ b/client/renderers/EGL/postprocess.c @@ -642,7 +642,9 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, //TODO: clean this up GLuint _unused; - if (egl_textureGet(tex, &_unused, &sizeX, &sizeY) != EGL_TEX_STATUS_OK) + EGL_PixelFormat pixFmt; + if (egl_textureGet(tex, &_unused, + &sizeX, &sizeY, &pixFmt) != EGL_TEX_STATUS_OK) return false; if (atomic_exchange(&this->modified, false)) @@ -677,7 +679,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex, { egl_filterSetOutputResHint(filter, targetX, targetY); - if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY, + if (!egl_filterSetup(filter, pixFmt, sizeX, sizeY, desktopWidth, desktopHeight, useDMA) || !egl_filterPrepare(filter)) continue; diff --git a/client/renderers/EGL/texture.h b/client/renderers/EGL/texture.h index 37901642..f92e1052 100644 --- a/client/renderers/EGL/texture.h +++ b/client/renderers/EGL/texture.h @@ -92,7 +92,8 @@ typedef struct EGL_TextureOps enum EGL_TexStatus (*process)(EGL_Texture * texture); /* get the texture for use */ - enum EGL_TexStatus (*get)(EGL_Texture * texture, GLuint * tex); + enum EGL_TexStatus (*get)(EGL_Texture * texture, GLuint * tex, + EGL_PixelFormat * fmt); /* bind the texture for use */ enum EGL_TexStatus (*bind)(EGL_Texture * texture); @@ -132,13 +133,15 @@ bool egl_textureUpdateFromDMA(EGL_Texture * texture, enum EGL_TexStatus egl_textureProcess(EGL_Texture * texture); static inline EGL_TexStatus egl_textureGet(EGL_Texture * texture, GLuint * tex, - unsigned int * sizeX, unsigned int * sizeY) + unsigned int * sizeX, unsigned int * sizeY, EGL_PixelFormat * fmt) { if (sizeX) *sizeX = texture->format.width; if (sizeY) *sizeY = texture->format.height; - return texture->ops.get(texture, tex); + if (fmt) + *fmt = texture->format.pixFmt; + return texture->ops.get(texture, tex, fmt); } enum EGL_TexStatus egl_textureBind(EGL_Texture * texture); diff --git a/client/renderers/EGL/texture_buffer.c b/client/renderers/EGL/texture_buffer.c index b23106b7..a15609ed 100644 --- a/client/renderers/EGL/texture_buffer.c +++ b/client/renderers/EGL/texture_buffer.c @@ -132,7 +132,8 @@ EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture) return EGL_TEX_STATUS_OK; } -EGL_TexStatus egl_texBufferGet(EGL_Texture * texture, GLuint * tex) +EGL_TexStatus egl_texBufferGet(EGL_Texture * texture, GLuint * tex, + EGL_PixelFormat * fmt) { TextureBuffer * this = UPCAST(TextureBuffer, texture); *tex = this->tex[0]; @@ -260,7 +261,8 @@ EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture) return EGL_TEX_STATUS_OK; } -EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex) +EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex, + EGL_PixelFormat * fmt) { TextureBuffer * this = UPCAST(TextureBuffer, texture); @@ -298,7 +300,7 @@ EGL_TexStatus egl_texBufferBind(EGL_Texture * texture) GLuint tex; EGL_TexStatus status; - if ((status = texture->ops.get(texture, &tex)) != EGL_TEX_STATUS_OK) + if ((status = texture->ops.get(texture, &tex, NULL)) != EGL_TEX_STATUS_OK) return status; glBindTexture(GL_TEXTURE_2D, tex); diff --git a/client/renderers/EGL/texture_buffer.h b/client/renderers/EGL/texture_buffer.h index 90bd0a5a..e2f8740d 100644 --- a/client/renderers/EGL/texture_buffer.h +++ b/client/renderers/EGL/texture_buffer.h @@ -47,7 +47,8 @@ bool egl_texBufferInit(EGL_Texture ** texture_, EGL_TexType type, 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_texBufferGet(EGL_Texture * texture_, GLuint * tex, + EGL_PixelFormat * fmt); EGL_TexStatus egl_texBufferBind(EGL_Texture * texture_); bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type, @@ -55,4 +56,5 @@ bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type, bool egl_texBufferStreamSetup(EGL_Texture * texture_, const EGL_TexSetup * setup); EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture_); -EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture_, GLuint * tex); +EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture_, GLuint * tex, + EGL_PixelFormat * fmt); diff --git a/client/renderers/EGL/texture_dmabuf.c b/client/renderers/EGL/texture_dmabuf.c index e1e927e2..b755e960 100644 --- a/client/renderers/EGL/texture_dmabuf.c +++ b/client/renderers/EGL/texture_dmabuf.c @@ -37,13 +37,21 @@ typedef struct TexDMABUF TextureBuffer base; EGLDisplay display; - bool hasImportModifiers; Vector images; + + EGL_PixelFormat pixFmt; + unsigned fourcc; + unsigned width; + GLuint format; } TexDMABUF; EGL_TextureOps EGL_TextureDMABUF; +static bool initDone = false; +static bool has24BitSupport = true; +static bool hasImportModifiers = true; + // internal functions static void egl_texDMABUFCleanup(EGL_Texture * texture) @@ -94,9 +102,13 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGL_TexType type, this->display = display; - const char * client_exts = eglQueryString(this->display, EGL_EXTENSIONS); - this->hasImportModifiers = - util_hasGLExt(client_exts, "EGL_EXT_image_dma_buf_import_modifiers"); + if (!initDone) + { + const char * client_exts = eglQueryString(this->display, EGL_EXTENSIONS); + hasImportModifiers = + util_hasGLExt(client_exts, "EGL_EXT_image_dma_buf_import_modifiers"); + initDone = true; + } return true; } @@ -113,9 +125,18 @@ static void egl_texDMABUFFree(EGL_Texture * texture) free(this); } -static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup) +static bool texDMABUFSetup(EGL_Texture * texture) { TextureBuffer * parent = UPCAST(TextureBuffer, texture); + TexDMABUF * this = UPCAST(TexDMABUF , parent); + + if (texture->format.pixFmt == EGL_PF_RGB_24 && !has24BitSupport) + { + this->pixFmt = EGL_PF_RGB_24_32; + this->width = texture->format.pitch / 4; + this->fourcc = DRM_FORMAT_ARGB8888; + this->format = GL_BGRA_EXT; + } egl_texDMABUFCleanup(texture); @@ -126,10 +147,10 @@ static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup glTexImage2D(GL_TEXTURE_EXTERNAL_OES, 0, texture->format.intFormat, - texture->format.width, + this->width, texture->format.height, 0, - texture->format.format, + this->format, texture->format.dataType, NULL); } @@ -139,6 +160,50 @@ static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup return true; } +static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup) +{ + TextureBuffer * parent = UPCAST(TextureBuffer, texture); + TexDMABUF * this = UPCAST(TexDMABUF , parent); + + this->pixFmt = texture->format.pixFmt; + this->width = texture->format.width; + this->fourcc = texture->format.fourcc; + this->format = texture->format.format; + + return texDMABUFSetup(texture); +} + +static EGLImage createImage(EGL_Texture * texture, int fd) +{ + TextureBuffer * parent = UPCAST(TextureBuffer, texture); + TexDMABUF * this = UPCAST(TexDMABUF , parent); + + const uint64_t modifier = DRM_FORMAT_MOD_LINEAR; + EGLAttrib attribs[] = + { + EGL_WIDTH , this->width , + EGL_HEIGHT , texture->format.height, + EGL_LINUX_DRM_FOURCC_EXT , this->fourcc, + EGL_DMA_BUF_PLANE0_FD_EXT , fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT , 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT , texture->format.pitch, + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, (modifier & 0xffffffff), + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, (modifier >> 32), + EGL_NONE , EGL_NONE + }; + + if (!hasImportModifiers) + attribs[12] = attribs[13] = + attribs[14] = attribs[15] = EGL_NONE; + + return g_egl_dynProcs.eglCreateImage( + this->display, + EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + (EGLClientBuffer)NULL, + attribs); +} + static bool egl_texDMABUFUpdate(EGL_Texture * texture, const EGL_TexUpdate * update) { @@ -159,30 +224,23 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture, if (unlikely(image == EGL_NO_IMAGE)) { - const uint64_t modifier = DRM_FORMAT_MOD_LINEAR; - EGLAttrib attribs[] = + bool setup = false; + if (texture->format.pixFmt == EGL_PF_RGB_24 && has24BitSupport) { - EGL_WIDTH , texture->format.width , - EGL_HEIGHT , texture->format.height, - EGL_LINUX_DRM_FOURCC_EXT , texture->format.fourcc, - EGL_DMA_BUF_PLANE0_FD_EXT , update->dmaFD, - EGL_DMA_BUF_PLANE0_OFFSET_EXT , 0, - EGL_DMA_BUF_PLANE0_PITCH_EXT , texture->format.pitch, - EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, (modifier & 0xffffffff), - EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, (modifier >> 32), - EGL_NONE , EGL_NONE - }; + image = createImage(texture, update->dmaFD); + if (image == EGL_NO_IMAGE) + { + DEBUG_INFO("Using 24-bit in 32-bit for DMA"); + has24BitSupport = false; + setup = true; + } + } - if (!this->hasImportModifiers) - attribs[12] = attribs[13] = - attribs[14] = attribs[15] = EGL_NONE; + if (!has24BitSupport && setup) + texDMABUFSetup(texture); - image = g_egl_dynProcs.eglCreateImage( - this->display, - EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, - (EGLClientBuffer)NULL, - attribs); + if (image == EGL_NO_IMAGE) + image = createImage(texture, update->dmaFD); if (unlikely(image == EGL_NO_IMAGE)) { @@ -220,9 +278,12 @@ static EGL_TexStatus egl_texDMABUFProcess(EGL_Texture * texture) return EGL_TEX_STATUS_OK; } -static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex) +static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex, + EGL_PixelFormat * fmt) { TextureBuffer * parent = UPCAST(TextureBuffer, texture); + TexDMABUF * this = UPCAST(TexDMABUF , parent); + GLsync sync = 0; INTERLOCKED_SECTION(parent->copyLock, @@ -265,6 +326,10 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex) } *tex = parent->tex[parent->rIndex]; + + if (fmt) + *fmt = this->pixFmt; + return EGL_TEX_STATUS_OK; } @@ -273,7 +338,7 @@ static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture) GLuint tex; EGL_TexStatus status; - if ((status = egl_texDMABUFGet(texture, &tex)) != EGL_TEX_STATUS_OK) + if ((status = egl_texDMABUFGet(texture, &tex, NULL)) != EGL_TEX_STATUS_OK) return status; glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); diff --git a/client/renderers/EGL/texture_util.c b/client/renderers/EGL/texture_util.c index 0915340d..3cda65a9 100644 --- a/client/renderers/EGL/texture_util.c +++ b/client/renderers/EGL/texture_util.c @@ -48,7 +48,7 @@ bool egl_texUtilGetFormat(const EGL_TexSetup * setup, EGL_TexFormat * fmt) fmt->format = GL_BGRA_EXT; fmt->intFormat = GL_BGRA_EXT; fmt->dataType = GL_UNSIGNED_BYTE; - fmt->fourcc = DRM_FORMAT_ARGB8888; + fmt->fourcc = DRM_FORMAT_XRGB8888; break; case EGL_PF_RGBA: @@ -56,7 +56,7 @@ bool egl_texUtilGetFormat(const EGL_TexSetup * setup, EGL_TexFormat * fmt) fmt->format = GL_RGBA; fmt->intFormat = GL_RGBA; fmt->dataType = GL_UNSIGNED_BYTE; - fmt->fourcc = DRM_FORMAT_ABGR8888; + fmt->fourcc = DRM_FORMAT_XBGR8888; break; case EGL_PF_RGBA10: @@ -64,7 +64,7 @@ bool egl_texUtilGetFormat(const EGL_TexSetup * setup, EGL_TexFormat * fmt) fmt->format = GL_RGBA; fmt->intFormat = GL_RGB10_A2; fmt->dataType = GL_UNSIGNED_INT_2_10_10_10_REV; - fmt->fourcc = DRM_FORMAT_ABGR2101010; + fmt->fourcc = DRM_FORMAT_XBGR2101010; break; case EGL_PF_RGBA16F: @@ -72,16 +72,15 @@ bool egl_texUtilGetFormat(const EGL_TexSetup * setup, EGL_TexFormat * fmt) fmt->format = GL_RGBA; fmt->intFormat = GL_RGBA16F; fmt->dataType = GL_HALF_FLOAT; - fmt->fourcc = DRM_FORMAT_ABGR16161616F; + fmt->fourcc = DRM_FORMAT_XBGR16161616F; break; case EGL_PF_RGB_24: fmt->bpp = 3; - fmt->format = GL_BGRA_EXT; + fmt->format = GL_RGB; fmt->intFormat = GL_BGRA_EXT; fmt->dataType = GL_UNSIGNED_BYTE; - fmt->fourcc = DRM_FORMAT_ARGB8888; - fmt->stride = fmt->pitch / 4; + fmt->fourcc = DRM_FORMAT_RGB888; break; default: diff --git a/client/renderers/EGL/texture_util.h b/client/renderers/EGL/texture_util.h index ad346778..af1e3003 100644 --- a/client/renderers/EGL/texture_util.h +++ b/client/renderers/EGL/texture_util.h @@ -63,10 +63,12 @@ void egl_texUtilUnmapBuffer(EGL_TexBuffer * buffer); #define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) +#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') #define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') -#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4') -#define DRM_FORMAT_ABGR2101010 fourcc_code('A', 'B', '3', '0') -#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H') +#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') +#define DRM_FORMAT_XBGR8888 fourcc_code('X', 'B', '2', '4') +#define DRM_FORMAT_XBGR2101010 fourcc_code('X', 'B', '3', '0') +#define DRM_FORMAT_XBGR16161616F fourcc_code('X', 'B', '4', 'H') #define DRM_FORMAT_MOD_VENDOR_NONE 0 #define fourcc_mod_code(vendor, val) \