gsk: Prepare for external textures

Prepare the plumbing in the GL renderer for textures that use
target GL_TEXTURE_EXTERNAL_OES. These need to use a special sampler,
so make sure our sampler machinery does not run over it.
This commit is contained in:
Matthias Clasen 2023-10-21 14:25:29 -04:00
parent 52254f755f
commit 13d0e311b7
4 changed files with 44 additions and 11 deletions

View File

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

View File

@ -29,6 +29,9 @@ typedef struct _GskGLBindFramebuffer GskGLBindFramebuffer;
typedef struct _GskGLBindTexture GskGLBindTexture;
#define GSK_GL_N_FILTERS 3
#define SAMPLER_EXTERNAL 9
G_STATIC_ASSERT (SAMPLER_EXTERNAL >= GSK_GL_N_FILTERS * GSK_GL_N_FILTERS);
static inline guint
filter_index (GLint filter)

View File

@ -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 = SAMPLER_EXTERNAL;
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 == SAMPLER_EXTERNAL)
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 == SAMPLER_EXTERNAL)
{
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 == SAMPLER_EXTERNAL)
{
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,9 @@ 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;
}

View File

@ -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(). */
@ -234,8 +235,13 @@ struct _GskGLCommandQueue
/* Array of samplers that we use for mag/min filter handling. It is indexed
* by the sampler_index() function.
*
* Note that when samplers are not supported (hello GLES), we fall back to
* setting the texture filter, but that needs to be done for every texture.
*
* Also note that we don't use all of these samplers since some combinations
* are invalid. An index of SAMPLER_EXTERNAL is used to indicate an external
* texture, which needs special sampler treatment.
*/
GLuint samplers[GSK_GL_N_FILTERS * GSK_GL_N_FILTERS];