self->textures[i].id = 0;
self->textures[i].changed = FALSE;
self->textures[i].initial = TRUE;
+ self->textures[i].sampler = sampler_index (GL_LINEAR, GL_LINEAR);
}
return self;
gsk_gl_attachment_state_bind_texture (GskGLAttachmentState *self,
GLenum target,
GLenum texture,
- guint id)
+ guint id,
+ GLint min_filter,
+ GLint mag_filter)
{
GskGLBindTexture *attach;
+ unsigned int sampler;
g_assert (self != NULL);
g_assert (target == GL_TEXTURE_1D ||
attach = &self->textures[texture - GL_TEXTURE0];
- if (attach->target != target || attach->texture != texture || attach->id != id)
+ sampler = sampler_index (min_filter, mag_filter);
+
+ if (attach->target != target || attach->texture != texture || attach->id != id ||
+ attach->sampler != sampler)
{
attach->target = target;
attach->texture = texture;
attach->id = id;
attach->initial = FALSE;
+ attach->sampler = sampler;
if (attach->changed == FALSE)
{
typedef struct _GskGLBindFramebuffer GskGLBindFramebuffer;
typedef struct _GskGLBindTexture GskGLBindTexture;
+#define GSK_GL_N_FILTERS 3
+
+static inline guint
+filter_index (GLint filter)
+{
+ switch (filter)
+ {
+ case GL_LINEAR:
+ return 0;
+ case GL_NEAREST:
+ return 1;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return 2;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static inline guint
+sampler_index (GLint min_filter,
+ GLint mag_filter)
+{
+ return filter_index (min_filter) * GSK_GL_N_FILTERS + filter_index (mag_filter);
+}
+
struct _GskGLBindTexture
{
guint changed : 1;
guint initial : 1;
- GLenum target : 30;
+ GLenum target : 26;
+ guint sampler : 4;
GLenum texture;
guint id;
};
void gsk_gl_attachment_state_bind_texture (GskGLAttachmentState *self,
GLenum target,
GLenum texture,
- guint id);
+ guint id,
+ GLint min_filter,
+ GLint mag_filter);
void gsk_gl_attachment_state_bind_framebuffer (GskGLAttachmentState *self,
guint id);
return TRUE;
}
+static inline GLint
+filter_from_index (guint index)
+{
+ GLint filters[3] = { GL_LINEAR, GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR };
+
+ g_assert (index < GSK_GL_N_FILTERS);
+
+ return filters[index];
+}
+
static inline guint
snapshot_attachments (const GskGLAttachmentState *state,
GskGLCommandBinds *array)
{
bind[count].id = state->textures[i].id;
bind[count].texture = state->textures[i].texture;
+ bind[count].sampler = state->textures[i].sampler;
count++;
}
}
g_clear_pointer (&self->attachments, gsk_gl_attachment_state_unref);
g_clear_pointer (&self->uniforms, gsk_gl_uniform_state_unref);
+ glDeleteSamplers (G_N_ELEMENTS (self->samplers), self->samplers);
+
gsk_gl_command_batches_clear (&self->batches);
gsk_gl_command_binds_clear (&self->batch_binds);
gsk_gl_command_uniforms_clear (&self->batch_uniforms);
GskGLUniformState *uniforms)
{
GskGLCommandQueue *self;
+ guint i;
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
}
}
+ /* create the samplers */
+ glGenSamplers (G_N_ELEMENTS (self->samplers), self->samplers);
+ for (i = 0; i < G_N_ELEMENTS (self->samplers); i++)
+ {
+ glSamplerParameteri (self->samplers[i], GL_TEXTURE_MIN_FILTER, filter_from_index(i / GSK_GL_N_FILTERS));
+ glSamplerParameteri (self->samplers[i], GL_TEXTURE_MAG_FILTER, filter_from_index(i % GSK_GL_N_FILTERS));
+ glSamplerParameteri (self->samplers[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glSamplerParameteri (self->samplers[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+
return g_steal_pointer (&self);
}
guint vao_id;
guint vbo_id;
int textures[4];
+ int samplers[4];
int framebuffer = -1;
int next_batch_index;
int active = -1;
for (guint i = 0; i < G_N_ELEMENTS (textures); i++)
textures[i] = -1;
+ for (guint i = 0; i < G_N_ELEMENTS (samplers); i++)
+ samplers[i] = -1;
gsk_gl_command_queue_sort_batches (self);
textures[bind->texture] = bind->id;
}
+ if (samplers[bind->texture] != bind->sampler)
+ {
+ glBindSampler (bind->texture, self->samplers[bind->sampler]);
+ samplers[bind->texture] = bind->sampler;
+ }
+
bind++;
}
int width,
int height,
int format,
- int min_filter,
- int mag_filter,
guint *out_fbo_id,
guint *out_texture_id)
{
g_assert (out_texture_id != NULL);
texture_id = gsk_gl_command_queue_create_texture (self,
- width, height,
- format,
- min_filter, mag_filter);
+ width, height,
+ format);
if (texture_id == -1)
{
gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
int width,
int height,
- int format,
- int min_filter,
- int mag_filter)
+ int format)
{
GLuint texture_id = 0;
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture_id);
-
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
+
+ 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);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int
gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
- GdkTexture *texture,
- int min_filter,
- int mag_filter)
+ GdkTexture *texture)
{
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
cairo_surface_t *surface = NULL;
g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
g_assert (!GDK_IS_GL_TEXTURE (texture));
- g_assert (mag_filter == GL_LINEAR || mag_filter == GL_NEAREST);
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
width = MIN (width, self->max_texture_size);
height = MIN (height, self->max_texture_size);
}
- texture_id = gsk_gl_command_queue_create_texture (self, width, height, GL_RGBA8, min_filter, mag_filter);
+ texture_id = gsk_gl_command_queue_create_texture (self, width, height, GL_RGBA8);
if (texture_id == -1)
return texture_id;
gsk_gl_command_queue_do_upload_texture (self, texture);
- if (min_filter == GL_LINEAR_MIPMAP_LINEAR)
- glGenerateMipmap (GL_TEXTURE_2D);
-
/* Restore previous texture state if any */
if (self->attachments->textures[0].id > 0)
glBindTexture (self->attachments->textures[0].target,
* texture will be placed into. We always use GL_TEXTURE_2D so we don't
* waste any bits here to indicate that.
*/
- guint texture : 5;
+ guint texture : 4;
+
+ guint sampler : 4;
/* The identifier for the texture created with glGenTextures(). */
- guint id : 27;
+ guint id: 24;
} GskGLCommandBind;
G_STATIC_ASSERT (sizeof (GskGLCommandBind) == 4);
*/
GskGLCommandUniforms batch_uniforms;
+ /* 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.
+ */
+ GLuint samplers[GSK_GL_N_FILTERS * GSK_GL_N_FILTERS];
+
/* Discovered max texture size when loading the command queue so that we
* can either scale down or slice textures to fit within this size. Assumed
* to be both height and width.
const cairo_region_t *scissor,
guint default_framebuffer);
int gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
- GdkTexture *texture,
- int min_filter,
- int mag_filter);
+ GdkTexture *texture);
int gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
int width,
int height,
- int format,
- int min_filter,
- int mag_filter);
+ int format);
guint gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self);
gboolean gsk_gl_command_queue_create_render_target (GskGLCommandQueue *self,
int width,
int height,
int format,
- int min_filter,
- int mag_filter,
guint *out_fbo_id,
guint *out_texture_id);
void gsk_gl_command_queue_delete_program (GskGLCommandQueue *self,
return GPOINTER_TO_SIZE (k->pointer) ^
((scale_x << 8) |
- (scale_y << 6) |
- (k->filter << 1) |
+ (scale_y << 4) |
k->pointer_is_child);
}
return k1->pointer == k2->pointer &&
k1->scale_x == k2->scale_x &&
k1->scale_y == k2->scale_y &&
- k1->filter == k2->filter &&
k1->pointer_is_child == k2->pointer_is_child &&
(!k1->pointer_is_child || memcmp (&k1->parent_rect, &k2->parent_rect, sizeof k1->parent_rect) == 0);
}
* gsk_gl_driver_load_texture:
* @self: a `GdkTexture`
* @texture: a `GdkTexture`
- * @min_filter: GL_NEAREST or GL_LINEAR
- * @mag_filter: GL_NEAREST or GL_LINEAR
+ * @ensure_mipmap: Mipmaps for this texture must exist for downscaling
*
* Loads a `GdkTexture` by uploading the contents to the GPU when
* necessary. If @texture is a `GdkGLTexture`, it can be used without
guint
gsk_gl_driver_load_texture (GskGLDriver *self,
GdkTexture *texture,
- int min_filter,
- int mag_filter)
+ gboolean ensure_mipmap)
{
GdkGLContext *context;
GdkMemoryTexture *downloaded_texture;
guint texture_id;
int height;
int width;
- int format;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
context = self->command_queue->context;
- format = GL_RGBA8;
+ texture_id = 0;
+ downloaded_texture = NULL;
- if (GDK_IS_GL_TEXTURE (texture) && min_filter == GL_LINEAR && mag_filter == GL_LINEAR)
+ t = gdk_texture_get_render_data (texture, self);
+ if (t && t->texture_id)
+ {
+ if (ensure_mipmap & !t->has_mipmap)
+ {
+ glBindTexture (GL_TEXTURE_2D, t->texture_id);
+ glGenerateMipmap (GL_TEXTURE_2D);
+ t->has_mipmap = TRUE;
+ }
+
+ return t->texture_id;
+ }
+
+ if (GDK_IS_GL_TEXTURE (texture) && !ensure_mipmap)
{
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
/* A GL texture from the same GL context is a simple task... */
return gdk_gl_texture_get_id (gl_texture);
}
- else
- {
- downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture));
- }
}
- else
- {
- if ((t = gdk_texture_get_render_data (texture, self)))
- {
- if (t->min_filter == min_filter && t->mag_filter == mag_filter && t->texture_id)
- return t->texture_id;
- }
+ if (texture_id == 0)
+ {
downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture));
- }
- /* The download_texture() call may have switched the GL context. Make sure
- * the right context is at work again.
- */
- gdk_gl_context_make_current (context);
+ /* The download_texture() call may have switched the GL context. Make sure
+ * the right context is at work again.
+ */
+ gdk_gl_context_make_current (context);
+
+ texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, GDK_TEXTURE (downloaded_texture));
+ }
width = gdk_texture_get_width (texture);
height = gdk_texture_get_height (texture);
- texture_id = gsk_gl_command_queue_upload_texture (self->command_queue,
- GDK_TEXTURE (downloaded_texture),
- min_filter,
- mag_filter);
t = gsk_gl_texture_new (texture_id,
- width, height, format, min_filter, mag_filter,
- self->current_frame_id);
+ width, height,
+ self->current_frame_id);
+ if (ensure_mipmap)
+ {
+ glBindTexture (GL_TEXTURE_2D, t->texture_id);
+ glGenerateMipmap (GL_TEXTURE_2D);
+ t->has_mipmap = TRUE;
+ }
g_hash_table_insert (self->textures, GUINT_TO_POINTER (texture_id), t);
- gdk_texture_clear_render_data (texture);
-
if (gdk_texture_set_render_data (texture, self, t, gsk_gl_texture_destroyed))
t->user = texture;
g_clear_object (&downloaded_texture);
- return texture_id;
+ return t->texture_id;
}
/**
* @width: the width of the texture
* @height: the height of the texture
* @format: format for the texture
- * @min_filter: GL_NEAREST or GL_LINEAR
- * @mag_filter: GL_NEAREST or GL_FILTER
*
* Creates a new texture immediately that can be used by the caller
* to upload data, map to a framebuffer, or other uses which may
gsk_gl_driver_create_texture (GskGLDriver *self,
float width,
float height,
- int format,
- int min_filter,
- int mag_filter)
+ int format)
{
GskGLTexture *texture;
guint texture_id;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), NULL);
texture_id = gsk_gl_command_queue_create_texture (self->command_queue,
- width, height,
- format,
- min_filter, mag_filter);
+ width, height,
+ format);
texture = gsk_gl_texture_new (texture_id,
- width, height,
- format,
- min_filter, mag_filter,
- self->current_frame_id);
+ width, height,
+ self->current_frame_id);
g_hash_table_insert (self->textures,
GUINT_TO_POINTER (texture->texture_id),
texture);
* @width: the width for the render target
* @height: the height for the render target
* @format: the format to use
- * @min_filter: the min filter to use for the texture
- * @mag_filter: the mag filter to use for the texture
* @out_render_target: (out): a location for the render target
*
* Creates a new render target which contains a framebuffer and a texture
int width,
int height,
int format,
- int min_filter,
- int mag_filter,
GskGLRenderTarget **out_render_target)
{
guint framebuffer_id;
GskGLRenderTarget *render_target = g_ptr_array_index (self->render_targets, i-1);
if (render_target->width == width &&
- render_target->height == height &&
- render_target->min_filter == min_filter &&
- render_target->mag_filter == mag_filter)
+ render_target->height == height)
{
*out_render_target = g_ptr_array_steal_index_fast (self->render_targets, i-1);
return TRUE;
if (gsk_gl_command_queue_create_render_target (self->command_queue,
width, height,
format,
- min_filter, mag_filter,
&framebuffer_id, &texture_id))
{
GskGLRenderTarget *render_target;
render_target = g_new0 (GskGLRenderTarget, 1);
- render_target->min_filter = min_filter;
- render_target->mag_filter = mag_filter;
render_target->format = format;
render_target->width = width;
render_target->height = height;
texture = gsk_gl_texture_new (render_target->texture_id,
render_target->width,
render_target->height,
- render_target->format,
- render_target->min_filter,
- render_target->mag_filter,
self->current_frame_id);
g_hash_table_insert (self->textures,
GUINT_TO_POINTER (texture_id),
void
gsk_gl_driver_add_texture_slices (GskGLDriver *self,
GdkTexture *texture,
- int min_filter,
- int mag_filter,
+ gboolean ensure_mipmap,
guint min_cols,
guint min_rows,
GskGLTextureSlice **out_slices,
if (t)
{
if (t->n_slices == n_slices &&
- t->min_filter == min_filter &&
- t->mag_filter == mag_filter)
+ (t->has_mipmap || !ensure_mipmap))
{
*out_slices = t->slices;
*out_n_slices = t->n_slices;
subtex = gdk_memory_texture_new_subtexture (memtex,
x, y,
slice_width, slice_height);
- texture_id = gsk_gl_command_queue_upload_texture (self->command_queue,
- subtex,
- min_filter, mag_filter);
+ texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, subtex);
g_object_unref (subtex);
+ if (ensure_mipmap)
+ {
+ glBindTexture (GL_TEXTURE_2D, texture_id);
+ glGenerateMipmap (GL_TEXTURE_2D);
+ }
slices[slice_index].rect.x = x;
slices[slice_index].rect.y = y;
/* Allocate one Texture for the entire thing. */
t = gsk_gl_texture_new (0,
tex_width, tex_height,
- GL_RGBA8,
- min_filter, mag_filter,
self->current_frame_id);
+ t->has_mipmap = ensure_mipmap;
/* Use gsk_gl_texture_free() as destroy notify here since we are
* not inserting this GskGLTexture into self->textures!
gconstpointer pointer;
float scale_x;
float scale_y;
- int filter;
int pointer_is_child;
graphene_rect_t parent_rect; /* Valid when pointer_is_child */
} GskTextureKey;
{
guint framebuffer_id;
guint texture_id;
- int min_filter;
- int mag_filter;
int format;
int width;
int height;
int width,
int height,
int format,
- int min_filter,
- int mag_filter,
GskGLRenderTarget **render_target);
guint gsk_gl_driver_release_render_target (GskGLDriver *self,
GskGLRenderTarget *render_target,
guint texture_id);
guint gsk_gl_driver_load_texture (GskGLDriver *self,
GdkTexture *texture,
- int min_filter,
- int mag_filter);
+ gboolean ensure_mipmap);
GskGLTexture * gsk_gl_driver_create_texture (GskGLDriver *self,
float width,
float height,
- int format,
- int min_filter,
- int mag_filter);
+ int format);
void gsk_gl_driver_release_texture (GskGLDriver *self,
GskGLTexture *texture);
void gsk_gl_driver_release_texture_by_id (GskGLDriver *self,
guint texture_id);
void gsk_gl_driver_add_texture_slices (GskGLDriver *self,
GdkTexture *texture,
- int min_filter,
- int mag_filter,
+ gboolean ensure_mipmap,
guint min_cols,
guint min_rows,
GskGLTextureSlice **out_slices,
static inline void
gsk_gl_driver_slice_texture (GskGLDriver *self,
GdkTexture *texture,
- int min_filter,
- int mag_filter,
+ gboolean ensure_mipmap,
guint min_cols,
guint min_rows,
GskGLTextureSlice **out_slices,
t = gdk_texture_get_render_data (texture, self);
if (t && t->slices &&
- t->min_filter == min_filter &&
- t->mag_filter == mag_filter &&
+ (t->has_mipmap || !ensure_mipmap) &&
min_cols == 0 && min_rows == 0)
{
*out_slices = t->slices;
return;
}
- gsk_gl_driver_add_texture_slices (self, texture, min_filter, mag_filter, min_cols, min_rows, out_slices, out_n_slices);
+ gsk_gl_driver_add_texture_slices (self, texture, ensure_mipmap, min_cols, min_rows, out_slices, out_n_slices);
}
G_END_DECLS
}
static inline void
-gsk_gl_program_set_uniform_texture (GskGLProgram *self,
- guint key,
- guint stamp,
- GLenum texture_target,
- GLenum texture_slot,
- guint texture_id)
+gsk_gl_program_set_uniform_texture_with_filter (GskGLProgram *self,
+ guint key,
+ guint stamp,
+ GLenum texture_target,
+ GLenum texture_slot,
+ guint texture_id,
+ GLint min_filter,
+ GLint mag_filter)
{
gsk_gl_attachment_state_bind_texture (self->driver->command_queue->attachments,
texture_target,
texture_slot,
- texture_id);
+ texture_id,
+ min_filter,
+ mag_filter);
gsk_gl_uniform_state_set_texture (self->uniforms,
self->program_info,
key,
texture_slot);
}
+static inline void
+gsk_gl_program_set_uniform_texture (GskGLProgram *self,
+ guint key,
+ guint stamp,
+ GLenum texture_target,
+ GLenum texture_slot,
+ guint texture_id)
+{
+ gsk_gl_program_set_uniform_texture_with_filter (self,
+ key,
+ stamp,
+ texture_target,
+ texture_slot,
+ texture_id,
+ GL_LINEAR,
+ GL_LINEAR);
+}
+
static inline void
gsk_gl_program_set_uniform_matrix (GskGLProgram *self,
guint key,
if (gsk_gl_driver_create_render_target (self->driver,
width, height,
format,
- GL_NEAREST, GL_NEAREST,
&render_target))
{
gsk_gl_driver_begin_frame (self->driver, self->command_queue);
guint force_offscreen : 1;
guint reset_clip : 1;
guint do_not_cache : 1;
- guint linear_filter : 1;
/* Return location for whether we created a texture */
guint was_offscreen : 1;
key.pointer_is_child = FALSE;
key.scale_x = scale_x;
key.scale_y = scale_y;
- key.filter = GL_NEAREST;
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key);
/* Create texture to upload */
texture = gdk_texture_new_for_surface (surface);
- texture_id = gsk_gl_driver_load_texture (job->driver, texture,
- GL_NEAREST, GL_NEAREST);
+ texture_id = gsk_gl_driver_load_texture (job->driver, texture, FALSE);
if (gdk_gl_context_has_debug (job->command_queue->context))
gdk_gl_context_label_object_printf (job->command_queue->context, GL_TEXTURE, texture_id,
MAX (texture_to_blur_width, 1),
MAX (texture_to_blur_height, 1),
job->target_format,
- GL_NEAREST, GL_NEAREST,
&pass1))
return 0;
texture_to_blur_width,
texture_to_blur_height,
job->target_format,
- GL_NEAREST, GL_NEAREST,
&pass2))
return gsk_gl_driver_release_render_target (job->driver, pass1, FALSE);
{
GskGLRenderOffscreen offscreen = {0};
float sx = 1, sy = 1;
+ gboolean linear_filter = FALSE;
offscreen.bounds = &child->bounds;
offscreen.force_offscreen = FALSE;
offscreen.reset_clip = TRUE;
if (!result_is_axis_aligned (transform, &child->bounds))
- offscreen.linear_filter = TRUE;
+ linear_filter = TRUE;
if (category == GSK_TRANSFORM_CATEGORY_2D)
{
if (gsk_gl_render_job_visit_node_with_offscreen (job, child, &offscreen))
{
/* For non-trivial transforms, we draw everything on a texture and then
- * draw the texture transformed. */
+ * draw the texture transformed.
+ */
if (transform)
gsk_gl_render_job_push_modelview (job, transform);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
- gsk_gl_program_set_uniform_texture (job->current_program,
- UNIFORM_SHARED_SOURCE, 0,
- GL_TEXTURE_2D,
- GL_TEXTURE0,
- offscreen.texture_id);
+ gsk_gl_program_set_uniform_texture_with_filter (job->current_program,
+ UNIFORM_SHARED_SOURCE, 0,
+ GL_TEXTURE_2D,
+ GL_TEXTURE0,
+ offscreen.texture_id,
+ linear_filter ? GL_LINEAR : GL_NEAREST,
+ linear_filter ? GL_LINEAR : GL_NEAREST);
gsk_gl_render_job_draw_offscreen (job, &child->bounds, &offscreen);
gsk_gl_render_job_end_draw (job);
key.pointer_is_child = FALSE;
key.scale_x = scale_x;
key.scale_y = scale_y;
- key.filter = GL_NEAREST;
blurred_texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
if (!gsk_gl_driver_create_render_target (job->driver,
texture_width, texture_height,
get_target_format (job, node),
- GL_NEAREST, GL_NEAREST,
&render_target))
g_assert_not_reached ();
gsk_gl_driver_create_render_target (job->driver,
texture_width, texture_height,
get_target_format (job, node),
- GL_NEAREST, GL_NEAREST,
&render_target);
if (gdk_gl_context_has_debug (context))
key.pointer_is_child = FALSE;
key.scale_x = job->scale_x;
key.scale_y = job->scale_y;
- key.filter = GL_NEAREST;
offscreen.texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
cache_texture = offscreen.texture_id == 0;
static void
gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
GdkTexture *texture,
- int min_filter,
- int mag_filter,
+ gboolean ensure_mipmap,
GskGLRenderOffscreen *offscreen)
{
- if (min_filter == GL_LINEAR &&
- mag_filter == GL_LINEAR &&
+ if (!ensure_mipmap &&
gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
texture->width,
texture->height) &&
}
else
{
- offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, min_filter, mag_filter);
+ offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, ensure_mipmap);
init_full_texture_region (offscreen);
}
}
{
GskGLRenderOffscreen offscreen = {0};
- gsk_gl_render_job_upload_texture (job, texture, GL_LINEAR, GL_LINEAR, &offscreen);
+ gsk_gl_render_job_upload_texture (job, texture, FALSE, &offscreen);
g_assert (offscreen.texture_id);
g_assert (offscreen.was_offscreen == FALSE);
GskGLTextureSlice *slices = NULL;
guint n_slices = 0;
- gsk_gl_driver_slice_texture (job->driver, texture, GL_LINEAR, GL_LINEAR, 0, 0, &slices, &n_slices);
+ gsk_gl_driver_slice_texture (job->driver, texture, FALSE, 0, 0, &slices, &n_slices);
g_assert (slices != NULL);
g_assert (n_slices > 0);
int max_texture_size = job->command_queue->max_texture_size;
graphene_rect_t clip_rect;
GskGLRenderTarget *render_target;
- GskGLRenderOffscreen offscreen = {0};
graphene_rect_t viewport;
graphene_rect_t prev_viewport;
graphene_matrix_t prev_projection;
key.parent_rect = clip_rect;
key.scale_x = 1.;
key.scale_y = 1.;
- key.filter = min_filter;
texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
(int) ceilf (clip_rect.size.width),
(int) ceilf (clip_rect.size.height),
get_target_format (job, node),
- GL_LINEAR, GL_LINEAR,
&render_target))
{
gsk_gl_render_job_visit_texture (job, texture, bounds);
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size)
{
- gsk_gl_render_job_upload_texture (job, texture, min_filter, mag_filter, &offscreen);
-
- g_assert (offscreen.texture_id);
- g_assert (offscreen.was_offscreen == FALSE);
+ texture_id = gsk_gl_driver_load_texture (job->driver, texture, filter == GSK_SCALING_FILTER_TRILINEAR);
u0 = (clip_rect.origin.x - bounds->origin.x) / bounds->size.width;
v0 = (clip_rect.origin.y - bounds->origin.y) / bounds->size.height;
v1 = (clip_rect.origin.y + clip_rect.size.height - bounds->origin.y) / bounds->size.height;
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
- gsk_gl_program_set_uniform_texture (job->current_program,
- UNIFORM_SHARED_SOURCE, 0,
- GL_TEXTURE_2D,
- GL_TEXTURE0,
- offscreen.texture_id);
+ gsk_gl_program_set_uniform_texture_with_filter (job->current_program,
+ UNIFORM_SHARED_SOURCE, 0,
+ GL_TEXTURE_2D,
+ GL_TEXTURE0,
+ texture_id,
+ min_filter,
+ mag_filter);
gsk_gl_render_job_draw_coords (job,
0, 0, clip_rect.size.width, clip_rect.size.height,
u0, v0, u1, v1,
GskGLTextureSlice *slices = NULL;
guint n_slices = 0;
- gsk_gl_driver_slice_texture (job->driver, texture, min_filter, mag_filter, 0, 0, &slices, &n_slices);
+ gsk_gl_driver_slice_texture (job->driver, texture, filter == GSK_SCALING_FILTER_TRILINEAR, 0, 0, &slices, &n_slices);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
if (i > 0)
gsk_gl_render_job_split_draw (job);
- gsk_gl_program_set_uniform_texture (job->current_program,
- UNIFORM_SHARED_SOURCE, 0,
- GL_TEXTURE_2D,
- GL_TEXTURE0,
- slice->texture_id);
+ gsk_gl_program_set_uniform_texture_with_filter (job->current_program,
+ UNIFORM_SHARED_SOURCE, 0,
+ GL_TEXTURE_2D,
+ GL_TEXTURE0,
+ slice->texture_id,
+ min_filter,
+ mag_filter);
gsk_gl_render_job_draw_coords (job,
slice_bounds.origin.x,
slice_bounds.origin.y,
{
GskTextureKey key;
guint cached_id;
- int filter;
g_assert (job != NULL);
g_assert (node != NULL);
offscreen->force_offscreen == FALSE)
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
- gsk_gl_render_job_upload_texture (job, texture, GL_LINEAR, GL_LINEAR, offscreen);
- g_assert (offscreen->was_offscreen == FALSE);
+ gsk_gl_render_job_upload_texture (job, texture, FALSE, offscreen);
return TRUE;
}
- filter = offscreen->linear_filter ? GL_LINEAR : GL_NEAREST;
-
key.pointer = node;
key.pointer_is_child = TRUE; /* Don't conflict with the child using the cache too */
key.parent_rect = *offscreen->bounds;
key.scale_x = job->scale_x;
key.scale_y = job->scale_y;
- key.filter = filter;
float offset_x = job->offset_x;
float offset_y = job->offset_y;
if (!gsk_gl_driver_create_render_target (job->driver,
texture_width, texture_height,
get_target_format (job, node),
- filter, filter,
&render_target))
g_assert_not_reached ();
MAX (1, job->viewport.size.width),
MAX (1, job->viewport.size.height),
job->target_format,
- GL_NEAREST, GL_NEAREST,
&framebuffer_id, &texture_id))
return;
gsk_gl_texture_new (guint texture_id,
int width,
int height,
- int format,
- int min_filter,
- int mag_filter,
gint64 frame_id)
{
GskGLTexture *texture;
texture = g_new0 (GskGLTexture, 1);
texture->texture_id = texture_id;
texture->link.data = texture;
- texture->min_filter = min_filter;
- texture->mag_filter = mag_filter;
- texture->format = format;
texture->width = width;
texture->height = height;
texture->last_used_in_frame = frame_id;
height = MIN (height, self->driver->command_queue->max_texture_size);
}
- texture = gsk_gl_driver_create_texture (self->driver, width, height, GL_RGBA8, GL_LINEAR, GL_LINEAR);
+ texture = gsk_gl_driver_create_texture (self->driver, width, height, GL_RGBA8);
texture->permanent = TRUE;
return texture;
atlas->texture_id = gsk_gl_command_queue_create_texture (self->driver->command_queue,
atlas->width,
atlas->height,
- GL_RGBA8,
- GL_LINEAR,
- GL_LINEAR);
+ GL_RGBA8);
gdk_gl_context_label_object_printf (gdk_gl_context_get_current (),
GL_TEXTURE, atlas->texture_id,
int width;
int height;
- int min_filter;
- int mag_filter;
- int format;
/* Set when used by an atlas so we don't drop the texture */
guint permanent : 1;
+ /* we called glGenerateMipmap() for this texture */
+ guint has_mipmap : 1;
};
GskGLTexture * gsk_gl_texture_new (guint texture_id,
int width,
int height,
- int format,
- int min_filter,
- int mag_filter,
gint64 frame_id);
const GskGLTextureNineSlice * gsk_gl_texture_get_nine_slice (GskGLTexture *texture,
const GskRoundedRect *outline,