gl: Move texture uploading to the renderer

It does not belong in GdkGLContext, it's a renderer thing.
It's also the only user of that API.

Introduce gdk_gl_context_check_version() private API to make version
checks simpler.
This commit is contained in:
Benjamin Otte 2021-10-12 15:04:43 +02:00
parent 31e9072906
commit 5199bebdb5
3 changed files with 101 additions and 91 deletions

View File

@ -249,86 +249,6 @@ gdk_gl_context_get_property (GObject *object,
}
}
void
gdk_gl_context_upload_texture (GdkGLContext *context,
const guchar *data,
int width,
int height,
int stride,
GdkMemoryFormat data_format,
guint texture_target)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
guchar *copy = NULL;
GLenum gl_internalformat;
GLenum gl_format;
GLenum gl_type;
gsize bpp;
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
if (!gdk_memory_format_gl_format (data_format,
gdk_gl_context_get_use_es (context),
&gl_internalformat,
&gl_format,
&gl_type))
{
copy = g_malloc_n (width * 4, height);
gdk_memory_convert (copy, width * 4,
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
data, stride,
data_format,
width, height);
data = copy;
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
stride = width * 4;
if (!gdk_memory_format_gl_format (data_format,
gdk_gl_context_get_use_es (context),
&gl_internalformat,
&gl_format,
&gl_type))
{
g_assert_not_reached ();
}
}
else
{
copy = NULL;
}
bpp = gdk_memory_format_bytes_per_pixel (data_format);
glPixelStorei (GL_UNPACK_ALIGNMENT, gdk_memory_format_alignment (data_format));
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
* the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
*/
if (stride == width * bpp)
{
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
}
else if (stride % bpp == 0 &&
(!gdk_gl_context_get_use_es (context) ||
(priv->gl_version >= 30 || priv->has_unpack_subimage)))
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
}
else
{
int i;
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, NULL);
for (i = 0; i < height; i++)
glTexSubImage2D (texture_target, 0, 0, i, width, 1, gl_format, gl_type, data + (i * stride));
}
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
g_free (copy);
}
#define N_EGL_ATTRS 16
static GdkGLAPI
@ -1067,6 +987,19 @@ gdk_gl_context_set_required_version (GdkGLContext *context,
priv->minor = version % 100;
}
gboolean
gdk_gl_context_check_version (GdkGLContext *context,
int required_major,
int required_minor)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), FALSE);
g_return_val_if_fail (required_minor < 10, FALSE);
return priv->gl_version >= required_major * 10 + required_minor;
}
/**
* gdk_gl_context_get_required_version:
* @context: a `GdkGLContext`

View File

@ -108,13 +108,10 @@ gboolean gdk_gl_context_is_api_allowed (GdkGLContext
void gdk_gl_context_set_is_legacy (GdkGLContext *context,
gboolean is_legacy);
void gdk_gl_context_upload_texture (GdkGLContext *context,
const guchar *data,
int width,
int height,
int stride,
GdkMemoryFormat data_format,
guint texture_target);
gboolean gdk_gl_context_check_version (GdkGLContext *context,
int required_major,
int required_minor);
gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context);
void gdk_gl_context_push_debug_group (GdkGLContext *context,
const char *message);

View File

@ -1339,6 +1339,86 @@ gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self)
return fbo_id;
}
static void
gsk_gl_command_queue_do_upload_texture (GskGLCommandQueue *self,
const guchar *data,
int width,
int height,
int stride,
GdkMemoryFormat data_format)
{
GdkGLContext *context;
guchar *copy = NULL;
GLenum gl_internalformat;
GLenum gl_format;
GLenum gl_type;
gsize bpp;
gboolean use_es;
context = gdk_gl_context_get_current ();
use_es = gdk_gl_context_get_use_es (context);
if (!gdk_memory_format_gl_format (data_format,
use_es,
&gl_internalformat,
&gl_format,
&gl_type))
{
copy = g_malloc_n (width * 4, height);
gdk_memory_convert (copy, width * 4,
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
data, stride,
data_format,
width, height);
data = copy;
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
stride = width * 4;
if (!gdk_memory_format_gl_format (data_format,
use_es,
&gl_internalformat,
&gl_format,
&gl_type))
{
g_assert_not_reached ();
}
}
else
{
copy = NULL;
}
bpp = gdk_memory_format_bytes_per_pixel (data_format);
glPixelStorei (GL_UNPACK_ALIGNMENT, gdk_memory_format_alignment (data_format));
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
* the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
*/
if (stride == width * bpp)
{
glTexImage2D (GL_TEXTURE_2D, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
}
else if (stride % bpp == 0 &&
(!use_es || gdk_gl_context_check_version (context, 3, 0) || gdk_gl_context_has_unpack_subimage (context)))
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
glTexImage2D (GL_TEXTURE_2D, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
}
else
{
int i;
glTexImage2D (GL_TEXTURE_2D, 0, gl_internalformat, width, height, 0, gl_format, gl_type, NULL);
for (i = 0; i < height; i++)
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, i, width, 1, gl_format, gl_type, data + (i * stride));
}
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
g_free (copy);
}
int
gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
GdkTexture *texture,
@ -1402,10 +1482,10 @@ gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture_id);
gdk_gl_context_upload_texture (gdk_gl_context_get_current (),
data + x_offset * bpp + y_offset * data_stride,
width, height, data_stride,
data_format, GL_TEXTURE_2D);
gsk_gl_command_queue_do_upload_texture (self,
data + x_offset * bpp + y_offset * data_stride,
width, height, data_stride,
data_format);
/* Restore previous texture state if any */
if (self->attachments->textures[0].id > 0)