egl: Use correct yuv details for importing

Make the dmabuf import api take color space and range hints as
ints, and update all callers to pass them.

The callers use the new dmabuf egl yuv hints helper api to get
this information from the dmabuf + colorstate. Note that the old
gl renderer is not handling color states carefully and may not
get dmabuf import right wrt to color states.
This commit is contained in:
Matthias Clasen
2024-07-27 08:59:33 -04:00
parent 83ba577fa8
commit 50e7f02fc4
7 changed files with 73 additions and 5 deletions

View File

@@ -209,12 +209,15 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
int width,
int height,
const GdkDmabuf *dmabuf,
int color_space_hint,
int range_hint,
int target)
{
EGLDisplay egl_display = gdk_display_get_egl_display (display);
EGLint attribs[64];
int i;
EGLImage image;
gboolean is_yuv;
g_return_val_if_fail (width > 0, 0);
g_return_val_if_fail (height > 0, 0);
@@ -228,6 +231,25 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
return EGL_NO_IMAGE;
}
if (gdk_dmabuf_fourcc_is_yuv (dmabuf->fourcc, &is_yuv) && is_yuv)
{
if (color_space_hint == 0 || range_hint == 0)
{
GDK_DISPLAY_DEBUG (display, DMABUF,
"Can't import yuv dmabuf into GL without color space hints");
return EGL_NO_IMAGE;
}
}
else
{
if (color_space_hint != 0 || range_hint != 0)
{
GDK_DISPLAY_DEBUG (display, DMABUF,
"Can't import non-yuv dmabuf into GL with color space hints");
return EGL_NO_IMAGE;
}
}
GDK_DISPLAY_DEBUG (display, DMABUF,
"Importing dmabuf (format: %.4s:%#" G_GINT64_MODIFIER "x, planes: %u) into GL",
(char *) &dmabuf->fourcc, dmabuf->modifier, dmabuf->n_planes);
@@ -241,10 +263,16 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
attribs[i++] = height;
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[i++] = dmabuf->fourcc;
attribs[i++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
attribs[i++] = EGL_ITU_REC601_EXT;
attribs[i++] = EGL_SAMPLE_RANGE_HINT_EXT;
attribs[i++] = EGL_YUV_NARROW_RANGE_EXT;
if (color_space_hint != 0)
{
attribs[i++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
attribs[i++] = color_space_hint;
}
if (range_hint != 0)
{
attribs[i++] = EGL_SAMPLE_RANGE_HINT_EXT;
attribs[i++] = range_hint;
}
#define ADD_PLANE(plane) \
{ \

View File

@@ -13,6 +13,8 @@ EGLImage gdk_dmabuf_egl_create_image (GdkDisplay
int width,
int height,
const GdkDmabuf *dmabuf,
int color_state_hint,
int range_hint,
int target);
void gdk_dmabuf_get_egl_yuv_hints (const GdkDmabuf *dmabuf,

View File

@@ -2198,6 +2198,8 @@ gdk_gl_context_import_dmabuf_for_target (GdkGLContext *self,
int width,
int height,
const GdkDmabuf *dmabuf,
int color_space_hint,
int range_hint,
int target)
{
#if defined(HAVE_EGL) && defined(HAVE_DMABUF)
@@ -2209,6 +2211,8 @@ gdk_gl_context_import_dmabuf_for_target (GdkGLContext *self,
width,
height,
dmabuf,
color_space_hint,
range_hint,
target);
if (image == EGL_NO_IMAGE)
return 0;
@@ -2232,6 +2236,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
int width,
int height,
const GdkDmabuf *dmabuf,
int color_space_hint,
int range_hint,
gboolean *external)
{
GdkDisplay *display = gdk_gl_context_get_display (self);
@@ -2248,6 +2254,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
width, height,
dmabuf,
color_space_hint,
range_hint,
GL_TEXTURE_2D);
if (texture_id == 0)
{
@@ -2277,6 +2285,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
width, height,
dmabuf,
color_space_hint,
range_hint,
GL_TEXTURE_EXTERNAL_OES);
if (texture_id == 0)
{
@@ -2309,6 +2319,8 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
width, height,
dmabuf,
color_space_hint,
range_hint,
target);
if (texture_id == 0)

View File

@@ -185,6 +185,8 @@ guint gdk_gl_context_import_dmabuf (GdkGLContext
int width,
int height,
const GdkDmabuf *dmabuf,
int color_space_hint,
int range_hint,
gboolean *external);
gboolean gdk_gl_context_export_dmabuf (GdkGLContext *self,

View File

@@ -43,6 +43,7 @@
#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkprofilerprivate.h>
#include <gdk/gdktextureprivate.h>
#include <gdk/gdkdmabufeglprivate.h>
#include <gdk/gdkmemoryformatprivate.h>
#include <gdk/gdkdmabuftextureprivate.h>
@@ -814,6 +815,8 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
gboolean external;
GdkMemoryFormat format;
gboolean premultiply;
GdkColorState *color_state;
int color_space, range;
gdk_gl_context_make_current (context);
@@ -831,10 +834,16 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
dmabuf = gdk_dmabuf_texture_get_dmabuf (texture);
format = gdk_texture_get_format (GDK_TEXTURE (texture));
premultiply = gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT;
color_state = gdk_texture_get_color_state (GDK_TEXTURE (texture));
gdk_dmabuf_get_egl_yuv_hints (dmabuf, color_state, &color_space, &range);
texture_id = gdk_gl_context_import_dmabuf (context,
width, height,
dmabuf,
color_space,
range,
&external);
if (texture_id == 0)
return 0;

View File

@@ -10,6 +10,7 @@
#include "gskglimageprivate.h"
#include "gdkdmabuftextureprivate.h"
#include "gdkdmabufeglprivate.h"
#include "gdkglcontextprivate.h"
#include "gdkgltextureprivate.h"
@@ -105,11 +106,20 @@ gsk_gl_frame_upload_texture (GskGpuFrame *frame,
{
gboolean external;
GLuint tex_id;
int color_space_hint;
int range_hint;
gdk_dmabuf_get_egl_yuv_hints (gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture)),
gdk_texture_get_color_state (texture),
&color_space_hint,
&range_hint);
tex_id = gdk_gl_context_import_dmabuf (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture)),
color_space_hint,
range_hint,
&external);
if (tex_id)
{

View File

@@ -5,6 +5,7 @@
#include <gdk/gdkglcontextprivate.h>
#include <gdk/gdkdmabuffourccprivate.h>
#include <gdk/gdkdmabuftextureprivate.h>
#include <gdk/gdkdmabufeglprivate.h>
static cairo_surface_t *
make_surface (int width,
@@ -191,6 +192,8 @@ test_dmabuf_import (void)
GdkGLTextureBuilder *builder;
guchar *data;
gboolean external;
GdkColorState *color_state;
int color_space, range;
display = gdk_display_get_default ();
if (!gdk_display_prepare_gl (display, &error))
@@ -229,7 +232,9 @@ test_dmabuf_import (void)
g_assert_no_error (error);
dmabuf2 = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
texture_id2 = gdk_gl_context_import_dmabuf (context2, 64, 64, dmabuf2, &external);
color_state = gdk_texture_get_color_state (texture);
gdk_dmabuf_get_egl_yuv_hints (dmabuf2, color_state, &color_space, &range);
texture_id2 = gdk_gl_context_import_dmabuf (context2, 64, 64, dmabuf2, color_space, range, &external);
g_assert_cmpint (texture_id2, !=, 0);
g_assert_false (external);