gsk: Support dmabuf textures
Support dmabuf textures in the GL renderer. This copies the approach taken by mutter for yuv dmabuf conversion.
This commit is contained in:
@@ -42,9 +42,16 @@
|
||||
#include <gdk/gdkmemorytextureprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
|
||||
#include <gdk/gdkdmabuftextureprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include <epoxy/egl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_DMA_BUF_H
|
||||
#include <drm/drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
|
||||
|
||||
static guint
|
||||
@@ -224,6 +231,8 @@ gsk_gl_driver_dispose (GObject *object)
|
||||
GSK_GL_DELETE_PROGRAM(name); \
|
||||
GSK_GL_DELETE_PROGRAM(name ## _no_clip); \
|
||||
GSK_GL_DELETE_PROGRAM(name ## _rect_clip);
|
||||
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) \
|
||||
GSK_GL_DELETE_PROGRAM(name);
|
||||
#define GSK_GL_DELETE_PROGRAM(name) \
|
||||
G_STMT_START { \
|
||||
if (self->name) \
|
||||
@@ -238,6 +247,7 @@ gsk_gl_driver_dispose (GObject *object)
|
||||
#undef GSK_GL_SHADER_JOINED
|
||||
#undef GSK_GL_ADD_UNIFORM
|
||||
#undef GSK_GL_DEFINE_PROGRAM
|
||||
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
|
||||
|
||||
if (self->shader_cache != NULL)
|
||||
{
|
||||
@@ -373,6 +383,11 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
|
||||
GSK_GL_COMPILE_PROGRAM(name ## _no_clip, uniforms, "#define NO_CLIP 1\n"); \
|
||||
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_source (compiler, GSK_GL_COMPILER_VERTEX, NULL); \
|
||||
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_FRAGMENT, NULL); \
|
||||
sources \
|
||||
GSK_GL_COMPILE_PROGRAM(name, uniforms, "#define NO_CLIP 1\n");
|
||||
#define GSK_GL_COMPILE_PROGRAM(name, uniforms, clip) \
|
||||
G_STMT_START { \
|
||||
GskGLProgram *program; \
|
||||
@@ -399,8 +414,8 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
|
||||
g_steal_pointer (&program); \
|
||||
} G_STMT_END;
|
||||
# include "gskglprograms.defs"
|
||||
#undef GSK_GL_DEFINE_PROGRAM_CLIP
|
||||
#undef GSK_GL_DEFINE_PROGRAM
|
||||
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
|
||||
#undef GSK_GL_ADD_UNIFORM
|
||||
#undef GSK_GL_SHADER_SINGLE
|
||||
#undef GSK_GL_SHADER_JOINED
|
||||
@@ -703,6 +718,321 @@ 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)
|
||||
{
|
||||
EGLint attribs[64];
|
||||
EGLImage image;
|
||||
guint texture_id;
|
||||
int i;
|
||||
|
||||
g_assert (1 <= n_planes && n_planes <= 4);
|
||||
|
||||
GSK_DEBUG (OPENGL,
|
||||
"Importing dma-buf into GL via EGLImage. Format %c%c%c%c:%#lx",
|
||||
fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, modifier);
|
||||
|
||||
i = 0;
|
||||
attribs[i++] = EGL_WIDTH;
|
||||
attribs[i++] = width;
|
||||
attribs[i++] = EGL_HEIGHT;
|
||||
attribs[i++] = height;
|
||||
attribs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attribs[i++] = fourcc;
|
||||
|
||||
#define ADD_PLANE(plane) \
|
||||
{ \
|
||||
if (modifier != DRM_FORMAT_MOD_INVALID) \
|
||||
{ \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_MODIFIER_LO_EXT; \
|
||||
attribs[i++] = modifier & 0xFFFFFFFF; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ## _MODIFIER_HI_EXT; \
|
||||
attribs[i++] = modifier >> 32; \
|
||||
} \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_FD_EXT; \
|
||||
attribs[i++] = fds[plane]; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_PITCH_EXT; \
|
||||
attribs[i++] = strides[plane]; \
|
||||
attribs[i++] = EGL_DMA_BUF_PLANE## plane ##_OFFSET_EXT; \
|
||||
attribs[i++] = offsets[plane]; \
|
||||
}
|
||||
|
||||
ADD_PLANE (0);
|
||||
|
||||
if (n_planes > 1) ADD_PLANE (1);
|
||||
if (n_planes > 2) ADD_PLANE (2);
|
||||
if (n_planes > 3) ADD_PLANE (3);
|
||||
|
||||
attribs[i++] = EGL_NONE;
|
||||
|
||||
image = eglCreateImageKHR (egl_display,
|
||||
EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
(EGLClientBuffer)NULL,
|
||||
attribs);
|
||||
|
||||
if (image == EGL_NO_IMAGE)
|
||||
{
|
||||
g_warning ("Failed to create EGL image: %#x\n", eglGetError ());
|
||||
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);
|
||||
|
||||
eglDestroyImageKHR (egl_display, image);
|
||||
|
||||
return texture_id;
|
||||
}
|
||||
|
||||
static void
|
||||
set_viewport_for_size (GskGLDriver *self,
|
||||
GskGLProgram *program,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
float viewport[4] = { 0, 0, width, height };
|
||||
|
||||
gsk_gl_uniform_state_set4fv (program->uniforms,
|
||||
program->program_info,
|
||||
UNIFORM_SHARED_VIEWPORT, 0,
|
||||
1,
|
||||
(const float *)&viewport);
|
||||
self->stamps[UNIFORM_SHARED_VIEWPORT]++;
|
||||
}
|
||||
|
||||
#define ORTHO_NEAR_PLANE -10000
|
||||
#define ORTHO_FAR_PLANE 10000
|
||||
|
||||
static void
|
||||
set_projection_for_size (GskGLDriver *self,
|
||||
GskGLProgram *program,
|
||||
float width,
|
||||
float height)
|
||||
{
|
||||
graphene_matrix_t projection;
|
||||
|
||||
graphene_matrix_init_ortho (&projection, 0, width, 0, height, ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
|
||||
graphene_matrix_scale (&projection, 1, -1, 1);
|
||||
|
||||
gsk_gl_uniform_state_set_matrix (program->uniforms,
|
||||
program->program_info,
|
||||
UNIFORM_SHARED_PROJECTION, 0,
|
||||
&projection);
|
||||
self->stamps[UNIFORM_SHARED_PROJECTION]++;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_modelview (GskGLDriver *self,
|
||||
GskGLProgram *program)
|
||||
{
|
||||
graphene_matrix_t modelview;
|
||||
|
||||
graphene_matrix_init_identity (&modelview);
|
||||
|
||||
gsk_gl_uniform_state_set_matrix (program->uniforms,
|
||||
program->program_info,
|
||||
UNIFORM_SHARED_MODELVIEW, 0,
|
||||
&modelview);
|
||||
self->stamps[UNIFORM_SHARED_MODELVIEW]++;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_rect (GskGLCommandQueue *command_queue,
|
||||
float min_x,
|
||||
float min_y,
|
||||
float max_x,
|
||||
float max_y)
|
||||
{
|
||||
GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (command_queue);
|
||||
float min_u = 0;
|
||||
float max_u = 1;
|
||||
float min_v = 1;
|
||||
float max_v = 0;
|
||||
guint16 c = FP16_ZERO;
|
||||
|
||||
vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { min_u, min_v }, .color = { c, c, c, c } };
|
||||
vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
|
||||
vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { max_u, min_v }, .color = { c, c, c, c } };
|
||||
vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { max_u, max_v }, .color = { c, c, c, c } };
|
||||
vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { min_u, max_v }, .color = { c, c, c, c } };
|
||||
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,
|
||||
gboolean cache_texture);
|
||||
|
||||
static unsigned int
|
||||
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
|
||||
GdkDmabufTexture *texture)
|
||||
{
|
||||
GdkGLContext *context = self->command_queue->context;
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
EGLDisplay egl_display;
|
||||
int width, height;
|
||||
guint64 modifier;
|
||||
TextureFormatInfo *info;
|
||||
GskGLProgram *program;
|
||||
GskGLRenderTarget *render_target;
|
||||
guint prev_fbo;
|
||||
|
||||
egl_display = gdk_display_get_egl_display (display);
|
||||
if (egl_display == NULL)
|
||||
{
|
||||
g_warning ("Can't import dmabufs when not using EGL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!display->have_egl_dma_buf_import)
|
||||
{
|
||||
g_warning ("EGL does ont support importing dmabufs");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
width = gdk_texture_get_width (GDK_TEXTURE (texture));
|
||||
height = gdk_texture_get_height (GDK_TEXTURE (texture));
|
||||
modifier = gdk_dmabuf_texture_get_modifier (texture);
|
||||
|
||||
if (gdk_dmabuf_texture_get_fourcc (texture) == DRM_FORMAT_YUYV)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
return import_dmabuf_planes (egl_display,
|
||||
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));
|
||||
}
|
||||
|
||||
gsk_gl_driver_create_render_target (self, width, height, GL_RGBA8, &render_target);
|
||||
|
||||
prev_fbo = gsk_gl_command_queue_bind_framebuffer (self->command_queue, render_target->framebuffer_id);
|
||||
gsk_gl_command_queue_clear (self->command_queue, 0, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
gsk_gl_command_queue_begin_draw (self->command_queue, program->program_info, width, height);
|
||||
|
||||
set_projection_for_size (self, program, width, height);
|
||||
set_viewport_for_size (self, program, width, height);
|
||||
reset_modelview (self, program);
|
||||
|
||||
for (int i = 0; i < info->n_planes; i++)
|
||||
{
|
||||
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);
|
||||
|
||||
gsk_gl_program_set_uniform_texture (program,
|
||||
info->uniforms[i], 0,
|
||||
GL_TEXTURE_2D, GL_TEXTURE0 + i, texture_id);
|
||||
|
||||
gsk_gl_driver_autorelease_texture (self, texture_id);
|
||||
}
|
||||
|
||||
draw_rect (self->command_queue, 0, 0, width, height);
|
||||
|
||||
gsk_gl_command_queue_end_draw (self->command_queue);
|
||||
|
||||
gsk_gl_command_queue_bind_framebuffer (self->command_queue, prev_fbo);
|
||||
|
||||
return release_render_target (self, render_target, FALSE, FALSE);
|
||||
}
|
||||
#else
|
||||
static unsigned int
|
||||
gsk_gl_driver_import_dmabuf_texture (GskGLDriver *self,
|
||||
GdkDmabufTexture *texture)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_EGL && HAVE_LINUX_DMA_BUF_H */
|
||||
|
||||
/**
|
||||
* gsk_gl_driver_load_texture:
|
||||
* @self: a `GdkTexture`
|
||||
@@ -759,7 +1089,11 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
if (GDK_IS_DMABUF_TEXTURE (texture))
|
||||
{
|
||||
texture_id = gsk_gl_driver_import_dmabuf_texture (self, GDK_DMABUF_TEXTURE (texture));
|
||||
}
|
||||
else if (GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
|
||||
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
|
||||
@@ -788,9 +1122,8 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
t = gsk_gl_texture_new (texture_id,
|
||||
width, height,
|
||||
self->current_frame_id);
|
||||
t = gsk_gl_texture_new (texture_id, width, height, self->current_frame_id);
|
||||
|
||||
if (ensure_mipmap)
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, t->texture_id);
|
||||
@@ -962,6 +1295,47 @@ gsk_gl_driver_create_render_target (GskGLDriver *self,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
release_render_target (GskGLDriver *self,
|
||||
GskGLRenderTarget *render_target,
|
||||
gboolean release_texture,
|
||||
gboolean cache_texture)
|
||||
{
|
||||
guint texture_id;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
|
||||
g_return_val_if_fail (render_target != NULL, 0);
|
||||
|
||||
if (release_texture)
|
||||
{
|
||||
texture_id = 0;
|
||||
g_ptr_array_add (self->render_targets, render_target);
|
||||
}
|
||||
else
|
||||
{
|
||||
texture_id = render_target->texture_id;
|
||||
|
||||
if (cache_texture)
|
||||
{
|
||||
GskGLTexture *texture;
|
||||
|
||||
texture = gsk_gl_texture_new (render_target->texture_id,
|
||||
render_target->width,
|
||||
render_target->height,
|
||||
self->current_frame_id);
|
||||
g_hash_table_insert (self->textures,
|
||||
GUINT_TO_POINTER (texture_id),
|
||||
g_steal_pointer (&texture));
|
||||
}
|
||||
|
||||
gsk_gl_driver_autorelease_framebuffer (self, render_target->framebuffer_id);
|
||||
g_free (render_target);
|
||||
|
||||
}
|
||||
|
||||
return texture_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_gl_driver_release_render_target:
|
||||
* @self: a `GskGLDriver`
|
||||
@@ -987,36 +1361,7 @@ gsk_gl_driver_release_render_target (GskGLDriver *self,
|
||||
GskGLRenderTarget *render_target,
|
||||
gboolean release_texture)
|
||||
{
|
||||
guint texture_id;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
|
||||
g_return_val_if_fail (render_target != NULL, 0);
|
||||
|
||||
if (release_texture)
|
||||
{
|
||||
texture_id = 0;
|
||||
g_ptr_array_add (self->render_targets, render_target);
|
||||
}
|
||||
else
|
||||
{
|
||||
GskGLTexture *texture;
|
||||
|
||||
texture_id = render_target->texture_id;
|
||||
|
||||
texture = gsk_gl_texture_new (render_target->texture_id,
|
||||
render_target->width,
|
||||
render_target->height,
|
||||
self->current_frame_id);
|
||||
g_hash_table_insert (self->textures,
|
||||
GUINT_TO_POINTER (texture_id),
|
||||
g_steal_pointer (&texture));
|
||||
|
||||
gsk_gl_driver_autorelease_framebuffer (self, render_target->framebuffer_id);
|
||||
g_free (render_target);
|
||||
|
||||
}
|
||||
|
||||
return texture_id;
|
||||
return release_render_target (self, render_target, release_texture, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -69,7 +69,9 @@ typedef struct {
|
||||
#define CONCAT_EXPANDED2(a,b) a##b
|
||||
#define GSK_GL_ADD_UNIFORM(pos, KEY, name) UNIFORM_##KEY = UNIFORM_SHARED_LAST + pos,
|
||||
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) enum { uniforms };
|
||||
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) enum { uniforms };
|
||||
# include "gskglprograms.defs"
|
||||
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
|
||||
#undef GSK_GL_DEFINE_PROGRAM
|
||||
#undef GSK_GL_ADD_UNIFORM
|
||||
#undef GSK_GL_NO_UNIFORMS
|
||||
@@ -116,10 +118,13 @@ struct _GskGLDriver
|
||||
GskGLProgram *name ## _no_clip; \
|
||||
GskGLProgram *name ## _rect_clip; \
|
||||
GskGLProgram *name;
|
||||
#define GSK_GL_DEFINE_PROGRAM_NO_CLIP(name, resource, uniforms) \
|
||||
GskGLProgram *name;
|
||||
# include "gskglprograms.defs"
|
||||
#undef GSK_GL_NO_UNIFORMS
|
||||
#undef GSK_GL_ADD_UNIFORM
|
||||
#undef GSK_GL_DEFINE_PROGRAM
|
||||
#undef GSK_GL_DEFINE_PROGRAM_NO_CLIP
|
||||
|
||||
gint64 current_frame_id;
|
||||
|
||||
|
||||
@@ -87,3 +87,22 @@ GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
|
||||
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
|
||||
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
|
||||
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
||||
|
||||
/* Texture conversion shaders.
|
||||
*
|
||||
* Note: If you add new formats here, they need to be added
|
||||
* 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))
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <gsk/gskglshaderprivate.h>
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
#include <gdk/gdkmemorytextureprivate.h>
|
||||
#include <gdk/gdkdmabuftextureprivate.h>
|
||||
#include <gdk/gdkdisplayprivate.h>
|
||||
#include <gsk/gsktransformprivate.h>
|
||||
#include <gsk/gskroundedrectprivate.h>
|
||||
#include <gsk/gskrectprivate.h>
|
||||
@@ -43,10 +45,15 @@
|
||||
#include "gskglprogramprivate.h"
|
||||
#include "gskglrenderjobprivate.h"
|
||||
#include "gskglshadowlibraryprivate.h"
|
||||
#include "gskdebugprivate.h"
|
||||
|
||||
#include "ninesliceprivate.h"
|
||||
#include "fp16private.h"
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
#define ORTHO_NEAR_PLANE -10000
|
||||
#define ORTHO_FAR_PLANE 10000
|
||||
#define MAX_GRADIENT_STOPS 6
|
||||
@@ -3630,16 +3637,11 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
|
||||
gboolean ensure_mipmap,
|
||||
GskGLRenderOffscreen *offscreen)
|
||||
{
|
||||
GdkGLTexture *gl_texture = NULL;
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
gl_texture = GDK_GL_TEXTURE (texture);
|
||||
|
||||
if (!ensure_mipmap &&
|
||||
gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
|
||||
texture->width,
|
||||
texture->height) &&
|
||||
!gl_texture)
|
||||
!(GDK_IS_GL_TEXTURE (texture) || GDK_IS_DMABUF_TEXTURE (texture)))
|
||||
{
|
||||
const GskGLIconData *icon_data;
|
||||
|
||||
@@ -3653,16 +3655,18 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
|
||||
/* Only generate a mipmap if it does not make use reupload
|
||||
* a GL texture which we could otherwise use directly.
|
||||
*/
|
||||
if (gl_texture &&
|
||||
gdk_gl_context_is_shared (gdk_gl_texture_get_context (gl_texture), job->command_queue->context))
|
||||
ensure_mipmap = gdk_gl_texture_has_mipmap (gl_texture);
|
||||
if (GDK_IS_GL_TEXTURE (texture) &&
|
||||
gdk_gl_context_is_shared (gdk_gl_texture_get_context (GDK_GL_TEXTURE (texture)),
|
||||
job->command_queue->context))
|
||||
ensure_mipmap = gdk_gl_texture_has_mipmap (GDK_GL_TEXTURE (texture));
|
||||
|
||||
offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, ensure_mipmap);
|
||||
init_full_texture_region (offscreen);
|
||||
offscreen->has_mipmap = ensure_mipmap;
|
||||
|
||||
if (gl_texture && offscreen->texture_id == gdk_gl_texture_get_id (gl_texture))
|
||||
offscreen->sync = gdk_gl_texture_get_sync (gl_texture);
|
||||
if (GDK_IS_GL_TEXTURE (texture) &&
|
||||
offscreen->texture_id == gdk_gl_texture_get_id (GDK_GL_TEXTURE (texture)))
|
||||
offscreen->sync = gdk_gl_texture_get_sync (GDK_GL_TEXTURE (texture));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
49
gsk/gl/resources/nv12.glsl
Normal file
49
gsk/gl/resources/nv12.glsl
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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));
|
||||
}
|
||||
51
gsk/gl/resources/yuv420.glsl
Normal file
51
gsk/gl/resources/yuv420.glsl
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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));
|
||||
}
|
||||
49
gsk/gl/resources/yuyv.glsl
Normal file
49
gsk/gl/resources/yuyv.glsl
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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));
|
||||
}
|
||||
@@ -20,6 +20,9 @@ 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',
|
||||
]
|
||||
|
||||
gsk_public_sources = files([
|
||||
|
||||
Reference in New Issue
Block a user