[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
This commit is contained in:
Geoffrey McRae 2023-11-21 11:57:25 +11:00
parent 8d27d9e2e2
commit 43a3fb0db3
11 changed files with 129 additions and 58 deletions

View File

@ -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:

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
if (!initDone)
{
const char * client_exts = eglQueryString(this->display, EGL_EXTENSIONS);
this->hasImportModifiers =
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);

View File

@ -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:

View File

@ -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) \