From ea98ea121751067d2009640f9422c3d665e7f126 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 12 Oct 2023 00:08:09 -0400 Subject: [PATCH] wip: Try to make GL_TEXTURE_EXTERNAL_OES work --- gdk/gdkdisplay.c | 4 +- gdk/gdkdmabuftexture.c | 19 ++- gsk/gl/gskglattachmentstate.c | 3 +- gsk/gl/gskglcommandqueue.c | 44 +++++-- gsk/gl/gskglcommandqueueprivate.h | 1 + gsk/gl/gskglcompiler.c | 121 ++++++++++++------- gsk/gl/gskglcompilerprivate.h | 2 + gsk/gl/gskgldriver.c | 185 ++++++++++++++---------------- gsk/gl/gskglprograms.defs | 15 +-- gsk/gl/resources/external.glsl | 35 ++++++ gsk/gl/resources/nv12.glsl | 49 -------- gsk/gl/resources/preamble.glsl | 4 + gsk/gl/resources/yuv420.glsl | 51 -------- gsk/gl/resources/yuyv.glsl | 49 -------- gsk/meson.build | 4 +- 15 files changed, 263 insertions(+), 323 deletions(-) create mode 100644 gsk/gl/resources/external.glsl delete mode 100644 gsk/gl/resources/nv12.glsl delete mode 100644 gsk/gl/resources/yuv420.glsl delete mode 100644 gsk/gl/resources/yuyv.glsl diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index bbc5258aa2..439bf1dfec 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -1892,8 +1892,8 @@ init_dmabuf_formats (GdkDisplay *display) uint64_t *modifiers; unsigned int *external_only; - if (!gdk_dmabuf_texture_may_support ((unsigned int)formats[i])) - continue; +// if (!gdk_dmabuf_texture_may_support ((unsigned int)formats[i])) +// continue; eglQueryDmaBufModifiersEXT (priv->egl_display, formats[i], 0, NULL, NULL, &num_modifiers); modifiers = g_new (uint64_t, num_modifiers); diff --git a/gdk/gdkdmabuftexture.c b/gdk/gdkdmabuftexture.c index 996f790701..02e619b978 100644 --- a/gdk/gdkdmabuftexture.c +++ b/gdk/gdkdmabuftexture.c @@ -35,6 +35,15 @@ #include #endif +/* We don't include gsk/gsk.h here to avoid a build order problem + * with the generated header gskenumtypes.h + */ +#include +#include +#include +#include +#include + /** * GdkDmabufTexture: * @@ -377,8 +386,7 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder, info = get_drm_format_info (fourcc); - if (!info || - ((info->requires_gl || n_planes > 1 || modifier != DRM_FORMAT_MOD_LINEAR) && !display_supports_format (display, fourcc, modifier))) + if ((!info || info->requires_gl || n_planes > 1 || modifier != DRM_FORMAT_MOD_LINEAR) && !display_supports_format (display, fourcc, modifier)) { g_warning ("Unsupported dmabuf format %c%c%c%c:%#lx", fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, modifier); @@ -396,8 +404,11 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder, self->destroy = destroy; self->data = data; - GDK_TEXTURE (self)->format = premultiplied ? info->premultiplied_memory_format - : info->unpremultiplied_memory_format; + if (info) + GDK_TEXTURE (self)->format = premultiplied ? info->premultiplied_memory_format + : info->unpremultiplied_memory_format; + else + GDK_TEXTURE (self)->format = premultiplied ? GDK_MEMORY_A8R8G8B8_PREMULTIPLIED : GDK_MEMORY_A8R8G8B8; g_set_object (&self->display, display); diff --git a/gsk/gl/gskglattachmentstate.c b/gsk/gl/gskglattachmentstate.c index 92fe871a3a..3765e95f79 100644 --- a/gsk/gl/gskglattachmentstate.c +++ b/gsk/gl/gskglattachmentstate.c @@ -76,7 +76,8 @@ gsk_gl_attachment_state_bind_texture (GskGLAttachmentState *self, g_assert (self != NULL); g_assert (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || - target == GL_TEXTURE_3D); + target == GL_TEXTURE_3D || + target == GL_TEXTURE_EXTERNAL_OES); g_assert (texture >= GL_TEXTURE0 && texture <= GL_TEXTURE16); g_assert (texture - GL_TEXTURE0 < G_N_ELEMENTS (self->textures)); diff --git a/gsk/gl/gskglcommandqueue.c b/gsk/gl/gskglcommandqueue.c index 0924b73993..a6b4b9a924 100644 --- a/gsk/gl/gskglcommandqueue.c +++ b/gsk/gl/gskglcommandqueue.c @@ -282,7 +282,10 @@ snapshot_attachments (const GskGLAttachmentState *state, { bind[count].id = state->textures[i].id; bind[count].texture = state->textures[i].texture; - bind[count].sampler = state->textures[i].sampler; + if (state->textures[i].target == GL_TEXTURE_EXTERNAL_OES) + bind[count].sampler = 15; + else + bind[count].sampler = state->textures[i].sampler; count++; } } @@ -1190,12 +1193,23 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self, s->sync = NULL; } - glBindTexture (GL_TEXTURE_2D, bind->id); + if (bind->sampler == 15) + glBindTexture (GL_TEXTURE_EXTERNAL_OES, bind->id); + else + glBindTexture (GL_TEXTURE_2D, bind->id); textures[bind->texture] = bind->id; if (!self->has_samplers) { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS)); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS)); + if (bind->sampler == 15) + { + glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS)); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS)); + } } } @@ -1205,8 +1219,16 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self, glBindSampler (bind->texture, self->samplers[bind->sampler]); else { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS)); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS)); + if (bind->sampler == 15) + { + glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_from_index (bind->sampler / GSK_GL_N_FILTERS)); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_from_index (bind->sampler % GSK_GL_N_FILTERS)); + } } samplers[bind->texture] = bind->sampler; } @@ -1324,7 +1346,7 @@ gsk_gl_command_queue_end_frame (GskGLCommandQueue *self) if (self->attachments->textures[i].id != 0) { glActiveTexture (GL_TEXTURE0 + i); - glBindTexture (GL_TEXTURE_2D, 0); + glBindTexture (self->attachments->textures[i].target, 0); self->attachments->textures[i].id = 0; self->attachments->textures[i].changed = FALSE; @@ -1401,7 +1423,7 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self, glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, texture_id); - + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -1429,8 +1451,10 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self, } /* Restore the previous texture if it was set */ - if (self->attachments->textures[0].id != 0) - glBindTexture (GL_TEXTURE_2D, self->attachments->textures[0].id); + if (self->attachments->textures[0].id != 0 && + self->attachments->textures[0].target == GL_TEXTURE_2D) + glBindTexture (self->attachments->textures[0].target, + self->attachments->textures[0].id); return (int)texture_id; } diff --git a/gsk/gl/gskglcommandqueueprivate.h b/gsk/gl/gskglcommandqueueprivate.h index e9bb2f4003..575de3b093 100644 --- a/gsk/gl/gskglcommandqueueprivate.h +++ b/gsk/gl/gskglcommandqueueprivate.h @@ -54,6 +54,7 @@ typedef struct _GskGLCommandBind */ guint texture : 4; + /* the sampler to use. We set sampler to 15 to indicate external textures */ guint sampler : 4; /* The identifier for the texture created with glGenTextures(). */ diff --git a/gsk/gl/gskglcompiler.c b/gsk/gl/gskglcompiler.c index d825eb5844..8484aeac93 100644 --- a/gsk/gl/gskglcompiler.c +++ b/gsk/gl/gskglcompiler.c @@ -56,6 +56,7 @@ struct _GskGLCompiler guint gles : 1; guint legacy : 1; guint debug_shaders : 1; + guint use_preamble : 1; }; typedef struct _GskGLProgramAttrib @@ -108,6 +109,7 @@ gsk_gl_compiler_init (GskGLCompiler *self) self->vertex_suffix = g_bytes_ref (empty_bytes); self->fragment_source = g_bytes_ref (empty_bytes); self->fragment_suffix = g_bytes_ref (empty_bytes); + self->use_preamble = 1; } GskGLCompiler * @@ -422,6 +424,13 @@ gsk_gl_compiler_set_suffix_from_resource (GskGLCompiler *self, g_clear_error (&error); } +void +gsk_gl_compiler_set_use_preamble (GskGLCompiler *self, + gboolean use_preamble) +{ + self->use_preamble = use_preamble ? 1 : 0; +} + static void prepend_line_numbers (char *code, GString *s) @@ -573,28 +582,40 @@ gsk_gl_compiler_compile (GskGLCompiler *self, gl3 = "#define GSK_GL3 1\n"; vertex_id = glCreateShader (GL_VERTEX_SHADER); - glShaderSource (vertex_id, - 10, - (const char *[]) { - version, debug, legacy, gl3, gles, - clip, - get_shader_string (self->all_preamble), - get_shader_string (self->vertex_preamble), - get_shader_string (self->vertex_source), - get_shader_string (self->vertex_suffix), - }, - (int[]) { - strlen (version), - strlen (debug), - strlen (legacy), - strlen (gl3), - strlen (gles), - strlen (clip), - g_bytes_get_size (self->all_preamble), - g_bytes_get_size (self->vertex_preamble), - g_bytes_get_size (self->vertex_source), - g_bytes_get_size (self->vertex_suffix), - }); + if (self->use_preamble) + glShaderSource (vertex_id, + 10, + (const char *[]) { + version, debug, legacy, gl3, gles, + clip, + get_shader_string (self->all_preamble), + get_shader_string (self->vertex_preamble), + get_shader_string (self->vertex_source), + get_shader_string (self->vertex_suffix), + }, + (int[]) { + strlen (version), + strlen (debug), + strlen (legacy), + strlen (gl3), + strlen (gles), + strlen (clip), + g_bytes_get_size (self->all_preamble), + g_bytes_get_size (self->vertex_preamble), + g_bytes_get_size (self->vertex_source), + g_bytes_get_size (self->vertex_suffix), + }); + else + glShaderSource (vertex_id, + 2, + (const char *[]) { + get_shader_string (self->vertex_source), + get_shader_string (self->vertex_suffix), + }, + (int[]) { + g_bytes_get_size (self->vertex_source), + g_bytes_get_size (self->vertex_suffix), + }); glCompileShader (vertex_id); if (!check_shader_error (vertex_id, error)) @@ -606,28 +627,40 @@ gsk_gl_compiler_compile (GskGLCompiler *self, print_shader_info ("Vertex shader", vertex_id, name); fragment_id = glCreateShader (GL_FRAGMENT_SHADER); - glShaderSource (fragment_id, - 10, - (const char *[]) { - version, debug, legacy, gl3, gles, - clip, - get_shader_string (self->all_preamble), - get_shader_string (self->fragment_preamble), - get_shader_string (self->fragment_source), - get_shader_string (self->fragment_suffix), - }, - (int[]) { - strlen (version), - strlen (debug), - strlen (legacy), - strlen (gl3), - strlen (gles), - strlen (clip), - g_bytes_get_size (self->all_preamble), - g_bytes_get_size (self->fragment_preamble), - g_bytes_get_size (self->fragment_source), - g_bytes_get_size (self->fragment_suffix), - }); + if (self->use_preamble) + glShaderSource (fragment_id, + 10, + (const char *[]) { + version, debug, legacy, gl3, gles, + clip, + get_shader_string (self->all_preamble), + get_shader_string (self->fragment_preamble), + get_shader_string (self->fragment_source), + get_shader_string (self->fragment_suffix), + }, + (int[]) { + strlen (version), + strlen (debug), + strlen (legacy), + strlen (gl3), + strlen (gles), + strlen (clip), + g_bytes_get_size (self->all_preamble), + g_bytes_get_size (self->fragment_preamble), + g_bytes_get_size (self->fragment_source), + g_bytes_get_size (self->fragment_suffix), + }); + else + glShaderSource (fragment_id, + 2, + (const char *[]) { + get_shader_string (self->fragment_source), + get_shader_string (self->fragment_suffix), + }, + (int[]) { + g_bytes_get_size (self->fragment_source), + g_bytes_get_size (self->fragment_suffix), + }); glCompileShader (fragment_id); if (!check_shader_error (fragment_id, error)) diff --git a/gsk/gl/gskglcompilerprivate.h b/gsk/gl/gskglcompilerprivate.h index 82a2dda81a..a56f740f7e 100644 --- a/gsk/gl/gskglcompilerprivate.h +++ b/gsk/gl/gskglcompilerprivate.h @@ -43,6 +43,8 @@ void gsk_gl_compiler_set_preamble (GskGLCompiler * void gsk_gl_compiler_set_preamble_from_resource (GskGLCompiler *self, GskGLCompilerKind kind, const char *resource_path); +void gsk_gl_compiler_set_use_preamble (GskGLCompiler *self, + gboolean use_preamble); void gsk_gl_compiler_set_source (GskGLCompiler *self, GskGLCompilerKind kind, GBytes *source_bytes); diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c index 198dc4b2dd..acde42a938 100644 --- a/gsk/gl/gskgldriver.c +++ b/gsk/gl/gskgldriver.c @@ -377,6 +377,7 @@ gsk_gl_driver_load_programs (GskGLDriver *self, #define GSK_GL_ADD_UNIFORM(pos, KEY, name) \ gsk_gl_program_add_uniform (program, #name, UNIFORM_##KEY); #define GSK_GL_DEFINE_PROGRAM(name, sources, uniforms) \ + gsk_gl_compiler_set_use_preamble (compiler, TRUE); \ gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_VERTEX, NULL); \ gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_FRAGMENT, NULL); \ sources \ @@ -384,6 +385,7 @@ gsk_gl_driver_load_programs (GskGLDriver *self, GSK_GL_COMPILE_PROGRAM(name ## _rect_clip, uniforms, "#define RECT_CLIP 1\n"); \ GSK_GL_COMPILE_PROGRAM(name, uniforms, ""); #define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, sources, uniforms) \ + gsk_gl_compiler_set_use_preamble (compiler, FALSE); \ gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_VERTEX, NULL); \ gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_FRAGMENT, NULL); \ sources \ @@ -719,20 +721,18 @@ gsk_gl_driver_cache_texture (GskGLDriver *self, } #if defined(HAVE_EGL) && defined(HAVE_LINUX_DMA_BUF_H) -static int -import_dmabuf_planes (EGLDisplay egl_display, - int width, - int height, - unsigned int fourcc, - guint64 modifier, - unsigned int n_planes, - int *fds, - unsigned int *strides, - unsigned int *offsets) +static EGLImage +egl_create_dmabuf_image (EGLDisplay display, + int width, + int height, + unsigned int fourcc, + guint64 modifier, + unsigned int n_planes, + int *fds, + unsigned int *strides, + unsigned int *offsets) { EGLint attribs[64]; - EGLImage image; - guint texture_id; int i; g_assert (1 <= n_planes && n_planes <= 4); @@ -742,6 +742,8 @@ import_dmabuf_planes (EGLDisplay egl_display, fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, modifier); i = 0; + attribs[i++] = EGL_IMAGE_PRESERVED_KHR; + attribs[i++] = EGL_TRUE; attribs[i++] = EGL_WIDTH; attribs[i++] = width; attribs[i++] = EGL_HEIGHT; @@ -774,11 +776,55 @@ import_dmabuf_planes (EGLDisplay egl_display, attribs[i++] = EGL_NONE; - image = eglCreateImageKHR (egl_display, - EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, - (EGLClientBuffer)NULL, - attribs); + return eglCreateImageKHR (display, + EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + (EGLClientBuffer)NULL, + attribs); +} + +static guint +egl_import_image (EGLImage image, + int target) +{ + guint texture_id; + + glGenTextures (1, &texture_id); + glBindTexture (target, texture_id); + g_assert (glGetError() == GL_NO_ERROR); + glEGLImageTargetTexture2DOES (target, image); + g_assert (glGetError() == GL_NO_ERROR); + glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + g_assert (glGetError() == GL_NO_ERROR); + glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + g_assert (glGetError() == GL_NO_ERROR); + + return texture_id; +} + +static void +egl_destroy_image (EGLDisplay display, + EGLImage image) +{ + eglDestroyImageKHR (display, image); +} + +static int +import_dmabuf_planes (EGLDisplay display, + int width, + int height, + unsigned int fourcc, + guint64 modifier, + unsigned int n_planes, + int *fds, + unsigned int *strides, + unsigned int *offsets, + int target) +{ + EGLImage image; + int texture_id; + + image = egl_create_dmabuf_image (display, width, height, fourcc, modifier, n_planes,fds, strides, offsets); if (image == EGL_NO_IMAGE) { @@ -786,13 +832,9 @@ import_dmabuf_planes (EGLDisplay egl_display, return 0; } - glGenTextures (1, &texture_id); - glBindTexture (GL_TEXTURE_2D, texture_id); - glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, image); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + texture_id = egl_import_image (image, target); - eglDestroyImageKHR (egl_display, image); + egl_destroy_image (display, image); return texture_id; } @@ -871,49 +913,6 @@ draw_rect (GskGLCommandQueue *command_queue, vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } }; } -typedef struct _TextureFormatInfo TextureFormatInfo; -struct _TextureFormatInfo -{ - int n_planes; - unsigned int subformats[3]; - int plane_indices[3]; - int hsub[3]; - int vsub[3]; - int uniforms[3]; -}; - -static TextureFormatInfo texture_format_info[] = { - { .n_planes = 2, - .subformats = { DRM_FORMAT_GR88, DRM_FORMAT_ARGB8888 }, - .plane_indices = { 0, 0 }, - .hsub = { 1, 2 }, - .vsub = { 1, 1 }, - .uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_YUYV_SOURCE2 }, - }, - { .n_planes = 2, - .subformats = { DRM_FORMAT_R8, DRM_FORMAT_GR88 }, - .plane_indices = { 0, 1 }, - .hsub = { 1, 2 }, - .vsub = { 1, 2 }, - .uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_NV12_SOURCE2 }, - }, - { .n_planes = 2, - .subformats = { DRM_FORMAT_R16, DRM_FORMAT_GR1616 }, - .plane_indices = { 0, 1 }, - .hsub = { 1, 2 }, - .vsub = { 1, 2 }, - .uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_NV12_SOURCE2 }, - }, - { .n_planes = 3, - .subformats = { DRM_FORMAT_R8, DRM_FORMAT_R8, DRM_FORMAT_R8 }, - .plane_indices = { 0, 1, 2 }, - .hsub = { 1, 2, 2 }, - .vsub = { 1, 2, 2 }, - .uniforms = { UNIFORM_SHARED_SOURCE, UNIFORM_YUV420_SOURCE2, UNIFORM_YUV420_SOURCE3 }, - }, - -}; - static unsigned int release_render_target (GskGLDriver *self, GskGLRenderTarget *render_target, gboolean release_texture, @@ -927,8 +926,8 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self, GdkDisplay *display = gdk_gl_context_get_display (context); EGLDisplay egl_display; int width, height; + guint32 fourcc; guint64 modifier; - TextureFormatInfo *info; GskGLProgram *program; GskGLRenderTarget *render_target; guint prev_fbo; @@ -950,27 +949,16 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self, width = gdk_texture_get_width (GDK_TEXTURE (texture)); height = gdk_texture_get_height (GDK_TEXTURE (texture)); + fourcc = gdk_dmabuf_texture_get_fourcc (texture); modifier = gdk_dmabuf_texture_get_modifier (texture); - if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_YUYV) + GSK_DEBUG (OPENGL, + "DMA-buf Format %c%c%c%c:%#lx", + fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, modifier); + + if (gdk_gl_context_get_api (context) == GDK_GL_API_GLES) { - info = &texture_format_info[0]; - program = self->yuyv; - } - else if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_NV12) - { - info = &texture_format_info[1]; - program = self->nv12; - } - else if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_P010) - { - info = &texture_format_info[2]; - program = self->nv12; - } - else if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_YUV420) - { - info = &texture_format_info[3]; - program = self->yuv420; + program = self->external; } else { @@ -982,7 +970,8 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self, gdk_dmabuf_texture_get_n_planes (texture), gdk_dmabuf_texture_get_fds (texture), gdk_dmabuf_texture_get_strides (texture), - gdk_dmabuf_texture_get_offsets (texture)); + gdk_dmabuf_texture_get_offsets (texture), + GL_TEXTURE_2D); } gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target); @@ -996,22 +985,22 @@ gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self, set_viewport_for_size (self, program, width, height); reset_modelview (self, program); - for (int i = 0; i < info->n_planes; i++) + if (gdk_gl_context_get_api (context) == GDK_GL_API_GLES) { - int plane = info->plane_indices[i]; int texture_id = import_dmabuf_planes (egl_display, - width / info->hsub[i], - height / info->vsub[i], - info->subformats[i], - modifier, - 1, - gdk_dmabuf_texture_get_fds (texture) + plane, - gdk_dmabuf_texture_get_strides (texture) + plane, - gdk_dmabuf_texture_get_offsets (texture) + plane); + gdk_texture_get_width (GDK_TEXTURE (texture)), + gdk_texture_get_height (GDK_TEXTURE (texture)), + gdk_dmabuf_texture_get_fourcc (texture), + gdk_dmabuf_texture_get_modifier (texture), + gdk_dmabuf_texture_get_n_planes (texture), + gdk_dmabuf_texture_get_fds (texture), + gdk_dmabuf_texture_get_strides (texture), + gdk_dmabuf_texture_get_offsets (texture), + GL_TEXTURE_EXTERNAL_OES); gsk_gl_program_set_uniform_texture (program, - info->uniforms[i], 0, - GL_TEXTURE_2D, GL_TEXTURE0 + i, texture_id); + UNIFORM_EXTERNAL_SOURCE, 0, + GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE0, texture_id); gsk_gl_driver_autorelease_texture (self, texture_id); } diff --git a/gsk/gl/gskglprograms.defs b/gsk/gl/gskglprograms.defs index 9d5e9c9d27..2ed531d90b 100644 --- a/gsk/gl/gskglprograms.defs +++ b/gsk/gl/gskglprograms.defs @@ -94,15 +94,6 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow, * to the list of supported formats in gdk/gdkdmabuftexture.c. */ -GSK_GL_DEFINE_PROGRAM_NO_CLIP (yuyv, - GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("yuyv.glsl")), - GSK_GL_ADD_UNIFORM (1, YUYV_SOURCE2, u_source2)) - -GSK_GL_DEFINE_PROGRAM_NO_CLIP (nv12, - GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("nv12.glsl")), - GSK_GL_ADD_UNIFORM (1, NV12_SOURCE2, u_source2)) - -GSK_GL_DEFINE_PROGRAM_NO_CLIP (yuv420, - GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("yuv420.glsl")), - GSK_GL_ADD_UNIFORM (1, YUV420_SOURCE2, u_source2) - GSK_GL_ADD_UNIFORM (2, YUV420_SOURCE3, u_source2)) +GSK_GL_DEFINE_PROGRAM_NO_CLIP (external, + GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("external.glsl")), + GSK_GL_ADD_UNIFORM (1, EXTERNAL_SOURCE, u_external_source)) diff --git a/gsk/gl/resources/external.glsl b/gsk/gl/resources/external.glsl new file mode 100644 index 0000000000..7bba3c6cc7 --- /dev/null +++ b/gsk/gl/resources/external.glsl @@ -0,0 +1,35 @@ +// VERTEX_SHADER: +// external.glsl + +#version 100 + +precision highp float; + +attribute vec2 aPosition; +attribute vec2 aUv; +varying vec2 vUv; +uniform mat4 u_projection; +uniform mat4 u_modelview; + +void main() { + gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); + + vUv = vec2(aUv.x, aUv.y); +} + +// FRAGMENT_SHADER: +// external.glsl + +#version 100 +#extension GL_OES_EGL_image_external : require + +precision highp float; + +uniform samplerExternalOES u_external_source; + +varying vec2 vUv; + +void main() { + vec4 color = texture2D(u_external_source, vUv); + gl_FragColor = color; +} diff --git a/gsk/gl/resources/nv12.glsl b/gsk/gl/resources/nv12.glsl deleted file mode 100644 index 7d4cce22c9..0000000000 --- a/gsk/gl/resources/nv12.glsl +++ /dev/null @@ -1,49 +0,0 @@ -// VERTEX_SHADER: -// nv12.glsl - -void main() { - gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - - vUv = vec2(aUv.x, aUv.y); -} - -// FRAGMENT_SHADER: -// nv12.glsl - -uniform sampler2D u_source2; - -vec4 yuv_to_rgb(vec4 yuv) -{ - vec4 res; - - float Y = 1.16438356 * (yuv.x - 0.0625); - float su = yuv.y - 0.5; - float sv = yuv.z - 0.5; - - res.r = Y + 1.59602678 * sv; - res.g = Y - 0.39176229 * su - 0.81296764 * sv; - res.b = Y + 2.01723214 * su; - - res.rgb *= yuv.w; - res.a = yuv.w; - - return res; -} - -/* This shader converts 2-plane yuv (DRM_FORMAT_NV12 or DRM_FORMAT_P010) - * into rgb. It assumes that the two planes have been imported separately, - * the first one as R texture, the second one as RG. - */ - -void main() { - vec4 y = GskTexture(u_source, vUv); - vec4 uv = GskTexture(u_source2, vUv); - - vec4 yuv; - - yuv.x = y.x; - yuv.yz = uv.xy; - yuv.w = 1.0; - - gskSetOutputColor(yuv_to_rgb(yuv)); -} diff --git a/gsk/gl/resources/preamble.glsl b/gsk/gl/resources/preamble.glsl index 46bebc14e0..1ba41b9889 100644 --- a/gsk/gl/resources/preamble.glsl +++ b/gsk/gl/resources/preamble.glsl @@ -1,3 +1,7 @@ +#ifdef GSK_GLES +#extension GL_OES_EGL_image_external : require +#endif + #ifndef GSK_LEGACY precision highp float; #endif diff --git a/gsk/gl/resources/yuv420.glsl b/gsk/gl/resources/yuv420.glsl deleted file mode 100644 index 377cd2727b..0000000000 --- a/gsk/gl/resources/yuv420.glsl +++ /dev/null @@ -1,51 +0,0 @@ -// VERTEX_SHADER: -// y_uv_to_rgba.glsl - -void main() { - gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - - vUv = vec2(aUv.x, aUv.y); -} - -// FRAGMENT_SHADER: -// y_uv_to_rgba.glsl - -uniform sampler2D u_source2; -uniform sampler2D u_source3; - -vec4 yuv_to_rgb(vec4 yuv) -{ - vec4 res; - - float Y = 1.16438356 * (yuv.x - 0.0625); - float su = yuv.y - 0.5; - float sv = yuv.z - 0.5; - - res.r = Y + 1.59602678 * sv; - res.g = Y - 0.39176229 * su - 0.81296764 * sv; - res.b = Y + 2.01723214 * su; - - res.rgb *= yuv.w; - res.a = yuv.w; - - return res; -} - -/* This shader converts 3-plane yuv (DRM_FORMAT_YUY420) into rgb. - */ - - -void main() { - vec4 y = GskTexture(u_source, vUv); - vec4 u = GskTexture(u_source2, vUv); - vec4 v = GskTexture(u_source3, vUv); - - vec4 yuv; - - yuv.x = y.x; - yuv.y = u.x; - yuv.z = v.x; - yuv.w = 1.0; - - gskSetOutputColor(yuv_to_rgb(yuv)); -} diff --git a/gsk/gl/resources/yuyv.glsl b/gsk/gl/resources/yuyv.glsl deleted file mode 100644 index e527a5eda5..0000000000 --- a/gsk/gl/resources/yuyv.glsl +++ /dev/null @@ -1,49 +0,0 @@ -// VERTEX_SHADER: -// y_xuxv_to_rgba.glsl - -void main() { - gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0); - - vUv = vec2(aUv.x, aUv.y); -} - -// FRAGMENT_SHADER: -// y_xuxv_to_rgba.glsl - -uniform sampler2D u_source2; - -vec4 yuv_to_rgb(vec4 yuv) -{ - vec4 res; - - float Y = 1.16438356 * (yuv.x - 0.0625); - float su = yuv.y - 0.5; - float sv = yuv.z - 0.5; - - res.r = Y + 1.59602678 * sv; - res.g = Y - 0.39176229 * su - 0.81296764 * sv; - res.b = Y + 2.01723214 * su; - - res.rgb *= yuv.w; - res.a = yuv.w; - - return res; -} - -/* This shader converts single-plane yuv (DRM_FORMAT_YUYV) into rgb. - * It assumes that the buffer has been imported twice - once as RG - * texture with full size, and once as RGBA textures with half the - * width (to account for the subsampling). - */ -void main() { - vec4 y = GskTexture(u_source, vUv); - vec4 uv = GskTexture(u_source2, vUv); - - vec4 yuv; - - yuv.x = y.x; - yuv.yz = uv.yw; - yuv.w = 1.0; - - gskSetOutputColor(yuv_to_rgb(yuv)); -} diff --git a/gsk/meson.build b/gsk/meson.build index 1cef4f55cb..23ebe82ce0 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -20,9 +20,7 @@ gsk_private_gl_shaders = [ 'gl/resources/custom.glsl', 'gl/resources/filled_border.glsl', 'gl/resources/mask.glsl', - 'gl/resources/yuyv.glsl', - 'gl/resources/nv12.glsl', - 'gl/resources/yuv420.glsl', + 'gl/resources/external.glsl', ] gsk_public_sources = files([