diff --git a/gsk/gpu/gskgldescriptors.c b/gsk/gpu/gskgldescriptors.c index e4b4bddade..f55e010dc9 100644 --- a/gsk/gpu/gskgldescriptors.c +++ b/gsk/gpu/gskgldescriptors.c @@ -9,6 +9,7 @@ struct _GskGLDescriptors GskGpuDescriptors parent_instance; GskGLDevice *device; + guint n_external; }; G_DEFINE_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK_TYPE_GPU_DESCRIPTORS) @@ -29,14 +30,28 @@ gsk_gl_descriptors_add_image (GskGpuDescriptors *desc, GskGpuSampler sampler, guint32 *out_descriptor) { + GskGLDescriptors *self = GSK_GL_DESCRIPTORS (desc); gsize used_texture_units; - used_texture_units = gsk_gpu_descriptors_get_size (desc); - if (used_texture_units >= 16) - return FALSE; + used_texture_units = gsk_gpu_descriptors_get_size (desc) + 2 * self->n_external; - *out_descriptor = used_texture_units; - return TRUE; + if (gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_EXTERNAL) + { + if (16 - used_texture_units < 3) + return FALSE; + + *out_descriptor = (self->n_external << 1) | 1; + self->n_external++; + return TRUE; + } + else + { + if (used_texture_units >= 16) + return FALSE; + + *out_descriptor = (gsk_gpu_descriptors_get_size (desc) - self->n_external) << 1; + return TRUE; + } } static void @@ -67,16 +82,36 @@ gsk_gl_descriptors_new (GskGLDevice *device) return GSK_GPU_DESCRIPTORS (self); } +guint +gsk_gl_descriptors_get_n_external (GskGLDescriptors *self) +{ + return self->n_external; +} + void gsk_gl_descriptors_use (GskGLDescriptors *self) { GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self); - gsize i; + gsize i, ext, n_textures; + + n_textures = 16 - 3 * self->n_external; + ext = 0; for (i = 0; i < gsk_gpu_descriptors_get_size (desc); i++) { - glActiveTexture (GL_TEXTURE0 + i); - gsk_gl_image_bind_texture (GSK_GL_IMAGE (gsk_gpu_descriptors_get_image (desc, i))); - glBindSampler (i, gsk_gl_device_get_sampler_id (self->device, gsk_gpu_descriptors_get_sampler (desc, i))); + GskGLImage *image = GSK_GL_IMAGE (gsk_gpu_descriptors_get_image (desc, i)); + + if (gsk_gpu_image_get_flags (GSK_GPU_IMAGE (image)) & GSK_GPU_IMAGE_EXTERNAL) + { + glActiveTexture (GL_TEXTURE0 + n_textures + 3 * ext); + gsk_gl_image_bind_texture (image); + ext++; + } + else + { + glActiveTexture (GL_TEXTURE0 + i - ext); + gsk_gl_image_bind_texture (image); + glBindSampler (i - ext, gsk_gl_device_get_sampler_id (self->device, gsk_gpu_descriptors_get_sampler (desc, i))); + } } } diff --git a/gsk/gpu/gskgldescriptorsprivate.h b/gsk/gpu/gskgldescriptorsprivate.h index ac8cf6262a..1e618efccf 100644 --- a/gsk/gpu/gskgldescriptorsprivate.h +++ b/gsk/gpu/gskgldescriptorsprivate.h @@ -10,9 +10,10 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK, GL_DESCRIPTORS, GskGpuDescriptors) -GskGpuDescriptors * gsk_gl_descriptors_new (GskGLDevice *device); +GskGpuDescriptors * gsk_gl_descriptors_new (GskGLDevice *device); -void gsk_gl_descriptors_use (GskGLDescriptors *self); +guint gsk_gl_descriptors_get_n_external (GskGLDescriptors *self); +void gsk_gl_descriptors_use (GskGLDescriptors *self); G_END_DECLS diff --git a/gsk/gpu/gskgldevice.c b/gsk/gpu/gskgldevice.c index cea723b0cf..705afec2db 100644 --- a/gsk/gpu/gskgldevice.c +++ b/gsk/gpu/gskgldevice.c @@ -34,6 +34,7 @@ struct _GLProgramKey { const GskGpuShaderOpClass *op_class; GskGpuShaderClip clip; + guint n_external_textures; }; G_DEFINE_TYPE (GskGLDevice, gsk_gl_device, GSK_TYPE_GPU_DEVICE) @@ -44,7 +45,8 @@ gl_program_key_hash (gconstpointer data) const GLProgramKey *key = data; return GPOINTER_TO_UINT (key->op_class) ^ - key->clip; + key->clip ^ + (key->n_external_textures << 24); } static gboolean @@ -55,7 +57,8 @@ gl_program_key_equal (gconstpointer a, const GLProgramKey *keyb = b; return keya->op_class == keyb->op_class && - keya->clip == keyb->clip; + keya->clip == keyb->clip && + keya->n_external_textures == keyb->n_external_textures; } static GskGpuImage * @@ -337,6 +340,7 @@ gsk_gl_device_load_shader (GskGLDevice *self, const char *program_name, GLenum shader_type, GskGpuShaderClip clip, + guint n_external_textures, GError **error) { GString *preamble; @@ -349,7 +353,22 @@ gsk_gl_device_load_shader (GskGLDevice *self, g_string_append (preamble, self->version_string); g_string_append (preamble, "\n"); if (self->api == GDK_GL_API_GLES) - g_string_append (preamble, "#define GSK_GLES 1\n"); + { + if (n_external_textures > 0) + { + g_string_append (preamble, "#extension GL_OES_EGL_image_external_essl3 : require\n"); + g_string_append (preamble, "#extension GL_OES_EGL_image_external : require\n"); + } + g_string_append (preamble, "#define GSK_GLES 1\n"); + g_assert (3 * n_external_textures <= 16); + } + else + { + g_assert (n_external_textures == 0); + } + + g_string_append_printf (preamble, "#define N_TEXTURES %u\n", 16 - 3 * n_external_textures); + g_string_append_printf (preamble, "#define N_EXTERNAL_TEXTURES %u\n", n_external_textures); switch (shader_type) { @@ -418,16 +437,17 @@ static GLuint gsk_gl_device_load_program (GskGLDevice *self, const char *program_name, GskGpuShaderClip clip, + guint n_external_textures, GError **error) { GLuint vertex_shader_id, fragment_shader_id, program_id; GLint link_status; - vertex_shader_id = gsk_gl_device_load_shader (self, program_name, GL_VERTEX_SHADER, clip, error); + vertex_shader_id = gsk_gl_device_load_shader (self, program_name, GL_VERTEX_SHADER, clip, n_external_textures, error); if (vertex_shader_id == 0) return 0; - fragment_shader_id = gsk_gl_device_load_shader (self, program_name, GL_FRAGMENT_SHADER, clip, error); + fragment_shader_id = gsk_gl_device_load_shader (self, program_name, GL_FRAGMENT_SHADER, clip, n_external_textures, error); if (fragment_shader_id == 0) return 0; @@ -478,15 +498,17 @@ gsk_gl_device_load_program (GskGLDevice *self, void gsk_gl_device_use_program (GskGLDevice *self, const GskGpuShaderOpClass *op_class, - GskGpuShaderClip clip) + GskGpuShaderClip clip, + guint n_external_textures) { GError *error = NULL; GLuint program_id; GLProgramKey key = { .op_class = op_class, .clip = clip, + .n_external_textures = n_external_textures }; - guint i; + guint i, n_textures; program_id = GPOINTER_TO_UINT (g_hash_table_lookup (self->gl_programs, &key)); if (program_id) @@ -495,7 +517,7 @@ gsk_gl_device_use_program (GskGLDevice *self, return; } - program_id = gsk_gl_device_load_program (self, op_class->shader_name, clip, &error); + program_id = gsk_gl_device_load_program (self, op_class->shader_name, clip, n_external_textures, &error); if (program_id == 0) { g_critical ("Failed to load shader program: %s", error->message); @@ -507,7 +529,16 @@ gsk_gl_device_use_program (GskGLDevice *self, glUseProgram (program_id); - for (i = 0; i < 16; i++) + n_textures = 16 - 3 * n_external_textures; + + for (i = 0; i < n_external_textures; i++) + { + char *name = g_strdup_printf ("external_textures[%u]", i); + glUniform1i (glGetUniformLocation (program_id, name), n_textures + 3 * i); + g_free (name); + } + + for (i = 0; i < n_textures; i++) { char *name = g_strdup_printf ("textures[%u]", i); glUniform1i (glGetUniformLocation (program_id, name), i); diff --git a/gsk/gpu/gskgldeviceprivate.h b/gsk/gpu/gskgldeviceprivate.h index 3b68167051..b237b6bc4d 100644 --- a/gsk/gpu/gskgldeviceprivate.h +++ b/gsk/gpu/gskgldeviceprivate.h @@ -13,7 +13,8 @@ GskGpuDevice * gsk_gl_device_get_for_display (GdkDisp void gsk_gl_device_use_program (GskGLDevice *self, const GskGpuShaderOpClass *op_class, - GskGpuShaderClip clip); + GskGpuShaderClip clip, + guint n_external_textures); GLuint gsk_gl_device_get_sampler_id (GskGLDevice *self, GskGpuSampler sampler); diff --git a/gsk/gpu/gskglframe.c b/gsk/gpu/gskglframe.c index 2f69b00172..bf130d84d1 100644 --- a/gsk/gpu/gskglframe.c +++ b/gsk/gpu/gskglframe.c @@ -193,13 +193,15 @@ gsk_gl_frame_init (GskGLFrame *self) void gsk_gl_frame_use_program (GskGLFrame *self, const GskGpuShaderOpClass *op_class, - GskGpuShaderClip clip) + GskGpuShaderClip clip, + guint n_external_textures) { GLuint vao; gsk_gl_device_use_program (GSK_GL_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self))), op_class, - clip); + clip, + n_external_textures); vao = GPOINTER_TO_UINT (g_hash_table_lookup (self->vaos, op_class)); if (vao) diff --git a/gsk/gpu/gskglframeprivate.h b/gsk/gpu/gskglframeprivate.h index 367187327c..77427d9229 100644 --- a/gsk/gpu/gskglframeprivate.h +++ b/gsk/gpu/gskglframeprivate.h @@ -10,6 +10,7 @@ G_DECLARE_FINAL_TYPE (GskGLFrame, gsk_gl_frame, GSK, GL_FRAME, GskGpuFrame) void gsk_gl_frame_use_program (GskGLFrame *self, const GskGpuShaderOpClass *op_class, - GskGpuShaderClip clip); + GskGpuShaderClip clip, + guint n_external_textures); G_END_DECLS diff --git a/gsk/gpu/gskglimage.c b/gsk/gpu/gskglimage.c index cc16119e1e..a0ef6d1811 100644 --- a/gsk/gpu/gskglimage.c +++ b/gsk/gpu/gskglimage.c @@ -194,7 +194,10 @@ gsk_gl_image_new_for_texture (GskGLDevice *device, void gsk_gl_image_bind_texture (GskGLImage *self) { - glBindTexture (GL_TEXTURE_2D, self->texture_id); + if (gsk_gpu_image_get_flags (GSK_GPU_IMAGE (self)) & GSK_GPU_IMAGE_EXTERNAL) + glBindTexture (GL_TEXTURE_EXTERNAL_OES, self->texture_id); + else + glBindTexture (GL_TEXTURE_2D, self->texture_id); } void diff --git a/gsk/gpu/gskgpushaderop.c b/gsk/gpu/gskgpushaderop.c index e03369f541..000e69354f 100644 --- a/gsk/gpu/gskgpushaderop.c +++ b/gsk/gpu/gskgpushaderop.c @@ -91,15 +91,18 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op, { GskGpuShaderOp *self = (GskGpuShaderOp *) op; GskGpuShaderOpClass *shader_op_class = (GskGpuShaderOpClass *) op->op_class; + GskGLDescriptors *desc; GskGpuOp *next; gsize i, n; + desc = GSK_GL_DESCRIPTORS (self->desc); gsk_gl_frame_use_program (GSK_GL_FRAME (frame), shader_op_class, - self->clip); + self->clip, + desc ? gsk_gl_descriptors_get_n_external (desc) : 0); - if (self->desc) - gsk_gl_descriptors_use (GSK_GL_DESCRIPTORS (self->desc)); + if (desc) + gsk_gl_descriptors_use (GSK_GL_DESCRIPTORS (desc)); if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_MERGE)) n = MAX_MERGE_OPS; diff --git a/gsk/gpu/shaders/common-gl.glsl b/gsk/gpu/shaders/common-gl.glsl index 37f26566ba..ee4757ffc4 100644 --- a/gsk/gpu/shaders/common-gl.glsl +++ b/gsk/gpu/shaders/common-gl.glsl @@ -27,7 +27,12 @@ uniform Floats vec4 really_just_floats[1024]; } floats; -uniform sampler2D textures[16]; +#if N_EXTERNAL_TEXTURES > 0 +uniform samplerExternalOES external_textures[N_EXTERNAL_TEXTURES]; +#endif +#if N_TEXTURES > 0 +uniform sampler2D textures[N_TEXTURES]; +#endif #define GSK_VERTEX_INDEX gl_VertexID @@ -59,90 +64,227 @@ gsk_get_float (uint id) #define gsk_get_uint(id) (floatBitsToUint(gsk_get_float(id))) #ifdef GSK_GLES + vec4 gsk_texture (uint id, vec2 pos) { - switch(id) - { - case 0u: - return texture (textures[0], pos); - case 1u: - return texture (textures[1], pos); - case 2u: - return texture (textures[2], pos); - case 3u: - return texture (textures[3], pos); - case 4u: - return texture (textures[4], pos); - case 5u: - return texture (textures[5], pos); - case 6u: - return texture (textures[6], pos); - case 7u: - return texture (textures[7], pos); - case 8u: - return texture (textures[8], pos); - case 9u: - return texture (textures[9], pos); - case 10u: - return texture (textures[10], pos); - case 11u: - return texture (textures[11], pos); - case 12u: - return texture (textures[12], pos); - case 13u: - return texture (textures[13], pos); - case 14u: - return texture (textures[14], pos); - case 15u: - return texture (textures[15], pos); - default: - return vec4 (1.0, 0.0, 0.8, 1.0); - } + if ((id & 1u) != 0u) + { + switch (id >> 1u) + { + case 0u: +#if N_EXTERNAL_TEXTURES > 0 + return texture (external_textures[0], pos); +#endif +#if N_EXTERNAL_TEXTURES > 1 + case 1u: + return texture (external_textures[1], pos); +#endif + case 2u: +#if N_EXTERNAL_TEXTURES > 2 + return texture (external_textures[2], pos); +#endif + case 3u: +#if N_EXTERNAL_TEXTURES > 3 + return texture (external_textures[3], pos); +#endif + case 4u: +#if N_EXTERNAL_TEXTURES > 4 + return texture (external_textures[4], pos); +#endif + case 5u: +#if N_EXTERNAL_TEXTURES > 5 + return texture (external_textures[5], pos); +#endif + default: + break; + } + } + else + { + switch (id >> 1u) + { + case 0u: +#if N_TEXTURES > 0 + return texture (textures[0], pos); +#endif + case 1u: +#if N_TEXTURES > 1 + return texture (textures[1], pos); +#endif + case 2u: +#if N_TEXTURES > 2 + return texture (textures[2], pos); +#endif + case 3u: +#if N_TEXTURES > 3 + return texture (textures[3], pos); +#endif + case 4u: +#if N_TEXTURES > 4 + return texture (textures[4], pos); +#endif + case 5u: +#if N_TEXTURES > 5 + return texture (textures[5], pos); +#endif + case 6u: +#if N_TEXTURES > 6 + return texture (textures[6], pos); +#endif + case 7u: +#if N_TEXTURES > 7 + return texture (textures[7], pos); +#endif + case 8u: +#if N_TEXTURES > 8 + return texture (textures[8], pos); +#endif + case 9u: +#if N_TEXTURES > 9 + return texture (textures[9], pos); +#endif + case 10u: +#if N_TEXTURES > 10 + return texture (textures[10], pos); +#endif + case 11u: +#if N_TEXTURES > 11 + return texture (textures[11], pos); +#endif + case 12u: +#if N_TEXTURES > 12 + return texture (textures[12], pos); +#endif + case 13u: +#if N_TEXTURES > 13 + return texture (textures[13], pos); +#endif + case 14u: +#if N_TEXTURES > 14 + return texture (textures[14], pos); +#endif + case 15u: +#if N_TEXTURES > 15 + return texture (textures[15], pos); +#endif + default: + break; + } + } + return vec4 (1.0, 0.0, 0.8, 1.0); } ivec2 gsk_texture_size (uint id, int lod) { - switch(id) - { - case 0u: - return textureSize (textures[0], lod); - case 1u: - return textureSize (textures[1], lod); - case 2u: - return textureSize (textures[2], lod); - case 3u: - return textureSize (textures[3], lod); - case 4u: - return textureSize (textures[4], lod); - case 5u: - return textureSize (textures[5], lod); - case 6u: - return textureSize (textures[6], lod); - case 7u: - return textureSize (textures[7], lod); - case 8u: - return textureSize (textures[8], lod); - case 9u: - return textureSize (textures[9], lod); - case 10u: - return textureSize (textures[10], lod); - case 11u: - return textureSize (textures[11], lod); - case 12u: - return textureSize (textures[12], lod); - case 13u: - return textureSize (textures[13], lod); - case 14u: - return textureSize (textures[14], lod); - case 15u: - return textureSize (textures[15], lod); - default: - return ivec2 (1, 1); - } + if ((id & 1u) != 0u) + { + switch (id >> 1u) + { + case 0u: +#if N_EXTERNAL_TEXTURES > 0 + return textureSize (external_textures[0], lod); +#endif +#if N_EXTERNAL_TEXTURES > 1 + case 1u: + return textureSize (external_textures[1], lod); +#endif + case 2u: +#if N_EXTERNAL_TEXTURES > 2 + return textureSize (external_textures[2], lod); +#endif + case 3u: +#if N_EXTERNAL_TEXTURES > 3 + return textureSize (external_textures[3], lod); +#endif + case 4u: +#if N_EXTERNAL_TEXTURES > 4 + return textureSize (external_textures[4], lod); +#endif + case 5u: +#if N_EXTERNAL_TEXTURES > 5 + return textureSize (external_textures[5], lod); +#endif + default: + break; + } + } + else + { + switch (id >> 1u) + { + case 0u: +#if N_TEXTURES > 0 + return textureSize (textures[0], lod); +#endif + case 1u: +#if N_TEXTURES > 1 + return textureSize (textures[1], lod); +#endif + case 2u: +#if N_TEXTURES > 2 + return textureSize (textures[2], lod); +#endif + case 3u: +#if N_TEXTURES > 3 + return textureSize (textures[3], lod); +#endif + case 4u: +#if N_TEXTURES > 4 + return textureSize (textures[4], lod); +#endif + case 5u: +#if N_TEXTURES > 5 + return textureSize (textures[5], lod); +#endif + case 6u: +#if N_TEXTURES > 6 + return textureSize (textures[6], lod); +#endif + case 7u: +#if N_TEXTURES > 7 + return textureSize (textures[7], lod); +#endif + case 8u: +#if N_TEXTURES > 8 + return textureSize (textures[8], lod); +#endif + case 9u: +#if N_TEXTURES > 9 + return textureSize (textures[9], lod); +#endif + case 10u: +#if N_TEXTURES > 10 + return textureSize (textures[10], lod); +#endif + case 11u: +#if N_TEXTURES > 11 + return textureSize (textures[11], lod); +#endif + case 12u: +#if N_TEXTURES > 12 + return textureSize (textures[12], lod); +#endif + case 13u: +#if N_TEXTURES > 13 + return textureSize (textures[13], lod); +#endif + case 14u: +#if N_TEXTURES > 14 + return textureSize (textures[14], lod); +#endif + case 15u: +#if N_TEXTURES > 15 + return textureSize (textures[15], lod); +#endif + default: + break; + } + } + return ivec2 (1, 1); } vec4 @@ -150,50 +292,118 @@ gsk_texel_fetch (uint id, ivec2 pos, int lod) { - switch(id) - { - case 0u: - return texelFetch (textures[0], pos, lod); - case 1u: - return texelFetch (textures[1], pos, lod); - case 2u: - return texelFetch (textures[2], pos, lod); - case 3u: - return texelFetch (textures[3], pos, lod); - case 4u: - return texelFetch (textures[4], pos, lod); - case 5u: - return texelFetch (textures[5], pos, lod); - case 6u: - return texelFetch (textures[6], pos, lod); - case 7u: - return texelFetch (textures[7], pos, lod); - case 8u: - return texelFetch (textures[8], pos, lod); - case 9u: - return texelFetch (textures[9], pos, lod); - case 10u: - return texelFetch (textures[10], pos, lod); - case 11u: - return texelFetch (textures[11], pos, lod); - case 12u: - return texelFetch (textures[12], pos, lod); - case 13u: - return texelFetch (textures[13], pos, lod); - case 14u: - return texelFetch (textures[14], pos, lod); - case 15u: - return texelFetch (textures[15], pos, lod); - default: - return vec4 (1.0, 0.0, 0.8, 1.0); - } + if ((id & 1u) != 0u) + { + switch (id >> 1u) + { + case 0u: +#if N_EXTERNAL_TEXTURES > 0 + return texelFetch (external_textures[0], pos, lod); +#endif +#if N_EXTERNAL_TEXTURES > 1 + case 1u: + return texelFetch (external_textures[1], pos, lod); +#endif + case 2u: +#if N_EXTERNAL_TEXTURES > 2 + return texelFetch (external_textures[2], pos, lod); +#endif + case 3u: +#if N_EXTERNAL_TEXTURES > 3 + return texelFetch (external_textures[3], pos, lod); +#endif + case 4u: +#if N_EXTERNAL_TEXTURES > 4 + return texelFetch (external_textures[4], pos, lod); +#endif + case 5u: +#if N_EXTERNAL_TEXTURES > 5 + return texelFetch (external_textures[5], pos, lod); +#endif + default: + break; + } + } + else + { + switch (id >> 1u) + { + case 0u: +#if N_TEXTURES > 0 + return texelFetch (textures[0], pos, lod); +#endif + case 1u: +#if N_TEXTURES > 1 + return texelFetch (textures[1], pos, lod); +#endif + case 2u: +#if N_TEXTURES > 2 + return texelFetch (textures[2], pos, lod); +#endif + case 3u: +#if N_TEXTURES > 3 + return texelFetch (textures[3], pos, lod); +#endif + case 4u: +#if N_TEXTURES > 4 + return texelFetch (textures[4], pos, lod); +#endif + case 5u: +#if N_TEXTURES > 5 + return texelFetch (textures[5], pos, lod); +#endif + case 6u: +#if N_TEXTURES > 6 + return texelFetch (textures[6], pos, lod); +#endif + case 7u: +#if N_TEXTURES > 7 + return texelFetch (textures[7], pos, lod); +#endif + case 8u: +#if N_TEXTURES > 8 + return texelFetch (textures[8], pos, lod); +#endif + case 9u: +#if N_TEXTURES > 9 + return texelFetch (textures[9], pos, lod); +#endif + case 10u: +#if N_TEXTURES > 10 + return texelFetch (textures[10], pos, lod); +#endif + case 11u: +#if N_TEXTURES > 11 + return texelFetch (textures[11], pos, lod); +#endif + case 12u: +#if N_TEXTURES > 12 + return texelFetch (textures[12], pos, lod); +#endif + case 13u: +#if N_TEXTURES > 13 + return texelFetch (textures[13], pos, lod); +#endif + case 14u: +#if N_TEXTURES > 14 + return texelFetch (textures[14], pos, lod); +#endif + case 15u: +#if N_TEXTURES > 15 + return texelFetch (textures[15], pos, lod); +#endif + default: + break; + } + } + return vec4 (1.0, 0.0, 0.8, 1.0); } #else /* !GSK_GLES */ -#define gsk_texture(id, pos) texture (textures[id], pos) -#define gsk_texture_size(id, lod) textureSize (textures[id], lod) -#define gsk_texel_fetch(id, pos, lod) texelFetch (textures[id], pos, lod) +#define gsk_texture(id, pos) texture (textures[id >> 1], pos) +#define gsk_texture_size(id, lod) textureSize (textures[id >> 1], lod) +#define gsk_texel_fetch(id, pos, lod) texelFetch (textures[id >> 1], pos, lod) #endif