forked from AuroraMiddleware/gtk
Merge branch 'wip/chergert/opbuffer' into 'master'
Add OpBuffer helper for building op buffer See merge request GNOME/gtk!1131
This commit is contained in:
commit
6c92b824f3
@ -269,13 +269,7 @@ gsk_gl_glyph_cache_lookup_or_add (GskGLGlyphCache *cache,
|
||||
|
||||
if (value)
|
||||
{
|
||||
if (value->atlas && !value->used)
|
||||
{
|
||||
gsk_gl_texture_atlas_mark_used (value->atlas, value->draw_width, value->draw_height);
|
||||
value->used = TRUE;
|
||||
}
|
||||
value->accessed = TRUE;
|
||||
|
||||
gsk_gl_glyph_cache_entry_validate (cache, value);
|
||||
*cached_glyph_out = value;
|
||||
return;
|
||||
}
|
||||
@ -334,6 +328,8 @@ gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
|
||||
{
|
||||
guint dropped = 0;
|
||||
|
||||
self->atlas_timestamp++;
|
||||
|
||||
g_hash_table_iter_init (&iter, self->hash_table);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
|
||||
{
|
||||
@ -366,6 +362,12 @@ gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
|
||||
{
|
||||
gsk_gl_driver_destroy_texture (driver, value->texture_id);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
|
||||
/* Sadly, if we drop an atlas-less cached glyph, we
|
||||
* have to treat it like a dropped atlas and purge
|
||||
* text node render data.
|
||||
*/
|
||||
self->atlas_timestamp++;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -375,3 +377,15 @@ gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
|
||||
GSK_NOTE(GLYPH_CACHE, g_message ("%d glyphs cached", g_hash_table_size (self->hash_table)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_glyph_cache_entry_validate (GskGLGlyphCache *cache,
|
||||
GskGLCachedGlyph *value)
|
||||
{
|
||||
value->accessed = TRUE;
|
||||
if (value->atlas && !value->used)
|
||||
{
|
||||
gsk_gl_texture_atlas_mark_used (value->atlas, value->draw_width, value->draw_height);
|
||||
value->used = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ typedef struct
|
||||
GskGLTextureAtlases *atlases;
|
||||
|
||||
int timestamp;
|
||||
int atlas_timestamp; /* incremented whenever an atlas is dropped */
|
||||
} GskGLGlyphCache;
|
||||
|
||||
typedef struct
|
||||
@ -79,5 +80,7 @@ void gsk_gl_glyph_cache_lookup_or_add (GskGLGlyphCache
|
||||
GlyphCacheKey *lookup,
|
||||
GskGLDriver *driver,
|
||||
const GskGLCachedGlyph **cached_glyph_out);
|
||||
void gsk_gl_glyph_cache_entry_validate (GskGLGlyphCache *cache,
|
||||
GskGLCachedGlyph *entry);
|
||||
|
||||
#endif
|
||||
|
@ -7,19 +7,13 @@
|
||||
|
||||
#define MAX_FRAME_AGE 60
|
||||
|
||||
typedef struct
|
||||
{
|
||||
graphene_rect_t texture_rect;
|
||||
GskGLTextureAtlas *atlas;
|
||||
GdkTexture *source_texture;
|
||||
guint accessed : 1;
|
||||
guint used : 1;
|
||||
} IconData;
|
||||
|
||||
static void
|
||||
icon_data_free (gpointer p)
|
||||
{
|
||||
g_object_unref (((IconData *)p)->source_texture);
|
||||
IconData *icon_data = p;
|
||||
|
||||
gdk_texture_clear_render_data (icon_data->source_texture);
|
||||
g_object_unref (icon_data->source_texture);
|
||||
g_free (p);
|
||||
}
|
||||
|
||||
@ -100,12 +94,12 @@ gsk_gl_icon_cache_begin_frame (GskGLIconCache *self,
|
||||
{
|
||||
if (icon_data->used)
|
||||
{
|
||||
const int w = icon_data->texture_rect.size.width * icon_data->atlas->width;
|
||||
const int h = icon_data->texture_rect.size.height * icon_data->atlas->height;
|
||||
gsk_gl_texture_atlas_mark_unused (icon_data->atlas, w + 2, h + 2);
|
||||
const int width = icon_data->source_texture->width;
|
||||
const int height = icon_data->source_texture->height;
|
||||
gsk_gl_texture_atlas_mark_unused (icon_data->atlas, width + 2, height + 2);
|
||||
icon_data->used = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
icon_data->accessed = FALSE;
|
||||
}
|
||||
@ -117,32 +111,32 @@ gsk_gl_icon_cache_begin_frame (GskGLIconCache *self,
|
||||
void
|
||||
gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
GdkTexture *texture,
|
||||
int *out_texture_id,
|
||||
graphene_rect_t *out_texture_rect)
|
||||
const IconData **out_icon_data)
|
||||
{
|
||||
IconData *icon_data = g_hash_table_lookup (self->icons, texture);
|
||||
IconData *icon_data;
|
||||
|
||||
icon_data = gdk_texture_get_render_data (texture, self);
|
||||
|
||||
if (!icon_data)
|
||||
icon_data = g_hash_table_lookup (self->icons, texture);
|
||||
|
||||
if (icon_data)
|
||||
{
|
||||
if (!icon_data->used)
|
||||
{
|
||||
const int w = icon_data->texture_rect.size.width * icon_data->atlas->width;
|
||||
const int h = icon_data->texture_rect.size.height * icon_data->atlas->height;
|
||||
|
||||
gsk_gl_texture_atlas_mark_used (icon_data->atlas, w + 2, h + 2);
|
||||
gsk_gl_texture_atlas_mark_used (icon_data->atlas, texture->width + 2, texture->height + 2);
|
||||
icon_data->used = TRUE;
|
||||
}
|
||||
icon_data->accessed = TRUE;
|
||||
|
||||
*out_texture_id = icon_data->atlas->texture_id;
|
||||
*out_texture_rect = icon_data->texture_rect;
|
||||
*out_icon_data = icon_data;
|
||||
return;
|
||||
}
|
||||
|
||||
/* texture not on any atlas yet. Find a suitable one. */
|
||||
{
|
||||
const int width = gdk_texture_get_width (texture);
|
||||
const int height = gdk_texture_get_height (texture);
|
||||
const int width = texture->width;
|
||||
const int height = texture->height;
|
||||
GskGLTextureAtlas *atlas = NULL;
|
||||
int packed_x = 0;
|
||||
int packed_y = 0;
|
||||
@ -155,12 +149,12 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
icon_data->atlas = atlas;
|
||||
icon_data->accessed = TRUE;
|
||||
icon_data->used = TRUE;
|
||||
icon_data->texture_id = atlas->texture_id;
|
||||
icon_data->source_texture = g_object_ref (texture);
|
||||
graphene_rect_init (&icon_data->texture_rect,
|
||||
(float)(packed_x + 1) / atlas->width,
|
||||
(float)(packed_y + 1) / atlas->height,
|
||||
(float)width / atlas->width,
|
||||
(float)height / atlas->height);
|
||||
icon_data->x = (float)(packed_x + 1) / atlas->width;
|
||||
icon_data->y = (float)(packed_y + 1) / atlas->width;
|
||||
icon_data->x2 = icon_data->x + (float)width / atlas->width;
|
||||
icon_data->y2 = icon_data->y + (float)height / atlas->height;
|
||||
|
||||
g_hash_table_insert (self->icons, texture, icon_data);
|
||||
|
||||
@ -240,8 +234,9 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
|
||||
gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
|
||||
|
||||
*out_texture_id = atlas->texture_id;
|
||||
*out_texture_rect = icon_data->texture_rect;
|
||||
gdk_texture_set_render_data (texture, self, icon_data, NULL);
|
||||
|
||||
*out_icon_data = icon_data;
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
|
@ -21,6 +21,16 @@ typedef struct
|
||||
int timestamp;
|
||||
} GskGLIconCache;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y, x2, y2;
|
||||
GskGLTextureAtlas *atlas;
|
||||
guint used : 1;
|
||||
guint accessed : 1;
|
||||
int texture_id;
|
||||
GdkTexture *source_texture;
|
||||
} IconData;
|
||||
|
||||
GskGLIconCache * gsk_gl_icon_cache_new (GdkDisplay *display,
|
||||
GskGLTextureAtlases *atlases);
|
||||
GskGLIconCache * gsk_gl_icon_cache_ref (GskGLIconCache *self);
|
||||
@ -29,7 +39,6 @@ void gsk_gl_icon_cache_begin_frame (GskGLIconCache *self,
|
||||
GPtrArray *removed_atlases);
|
||||
void gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
|
||||
GdkTexture *texture,
|
||||
int *out_texture_id,
|
||||
graphene_rect_t *out_texture_rect);
|
||||
const IconData **out_icon_data);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,6 @@ ops_finish (RenderOpBuilder *builder)
|
||||
g_array_free (builder->clip_stack, TRUE);
|
||||
builder->clip_stack = NULL;
|
||||
|
||||
builder->buffer_size = 0;
|
||||
builder->dx = 0;
|
||||
builder->dy = 0;
|
||||
builder->current_modelview = NULL;
|
||||
@ -57,23 +56,23 @@ ops_dump_framebuffer (RenderOpBuilder *builder,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
RenderOp *op;
|
||||
OpDumpFrameBuffer *op;
|
||||
|
||||
op = ops_begin (builder, OP_DUMP_FRAMEBUFFER);
|
||||
op->dump.filename = g_strdup (filename);
|
||||
op->dump.width = width;
|
||||
op->dump.height = height;
|
||||
op->filename = g_strdup (filename);
|
||||
op->width = width;
|
||||
op->height = height;
|
||||
}
|
||||
|
||||
void
|
||||
ops_push_debug_group (RenderOpBuilder *builder,
|
||||
const char *text)
|
||||
{
|
||||
RenderOp *op;
|
||||
OpDebugGroup *op;
|
||||
|
||||
op = ops_begin (builder, OP_PUSH_DEBUG_GROUP);
|
||||
strncpy (op->debug_group.text, text, sizeof(op->debug_group.text) - 1);
|
||||
op->debug_group.text[sizeof(op->debug_group.text) - 1] = 0; /* Ensure zero terminated */
|
||||
strncpy (op->text, text, sizeof(op->text) - 1);
|
||||
op->text[sizeof(op->text) - 1] = 0; /* Ensure zero terminated */
|
||||
}
|
||||
|
||||
void
|
||||
@ -182,6 +181,9 @@ ops_init (RenderOpBuilder *builder)
|
||||
|
||||
builder->current_opacity = 1.0f;
|
||||
|
||||
op_buffer_init (&builder->render_ops);
|
||||
builder->vertices = g_array_new (FALSE, TRUE, sizeof (GskQuadVertex));
|
||||
|
||||
for (i = 0; i < GL_N_PROGRAMS; i ++)
|
||||
{
|
||||
builder->program_state[i].opacity = 1.0f;
|
||||
@ -197,6 +199,9 @@ ops_free (RenderOpBuilder *builder)
|
||||
{
|
||||
gsk_transform_unref (builder->program_state[i].modelview);
|
||||
}
|
||||
|
||||
g_array_unref (builder->vertices);
|
||||
op_buffer_destroy (&builder->render_ops);
|
||||
}
|
||||
|
||||
void
|
||||
@ -208,7 +213,7 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
static const GskRoundedRect empty_clip;
|
||||
static const graphene_matrix_t empty_matrix;
|
||||
static const graphene_rect_t empty_rect;
|
||||
RenderOp *op;
|
||||
OpProgram *op;
|
||||
ProgramState *program_state;
|
||||
|
||||
if (builder->current_program == program)
|
||||
@ -225,16 +230,20 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
if (memcmp (&empty_matrix, &program_state->projection, sizeof (graphene_matrix_t)) == 0 ||
|
||||
memcmp (&builder->current_projection, &program_state->projection, sizeof (graphene_matrix_t)) != 0)
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_PROJECTION);
|
||||
op->projection = builder->current_projection;
|
||||
OpMatrix *opm;
|
||||
|
||||
opm = ops_begin (builder, OP_CHANGE_PROJECTION);
|
||||
opm->matrix = builder->current_projection;
|
||||
program_state->projection = builder->current_projection;
|
||||
}
|
||||
|
||||
if (program_state->modelview == NULL ||
|
||||
!gsk_transform_equal (builder->current_modelview, program_state->modelview))
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_MODELVIEW);
|
||||
gsk_transform_to_matrix (builder->current_modelview, &op->modelview);
|
||||
OpMatrix *opm;
|
||||
|
||||
opm = ops_begin (builder, OP_CHANGE_MODELVIEW);
|
||||
gsk_transform_to_matrix (builder->current_modelview, &opm->matrix);
|
||||
gsk_transform_unref (program_state->modelview);
|
||||
program_state->modelview = gsk_transform_ref (builder->current_modelview);
|
||||
}
|
||||
@ -242,23 +251,29 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
if (rect_equal (&empty_rect, &program_state->viewport) ||
|
||||
!rect_equal (&builder->current_viewport, &program_state->viewport))
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_VIEWPORT);
|
||||
op->viewport = builder->current_viewport;
|
||||
OpViewport *opv;
|
||||
|
||||
opv = ops_begin (builder, OP_CHANGE_VIEWPORT);
|
||||
opv->viewport = builder->current_viewport;
|
||||
program_state->viewport = builder->current_viewport;
|
||||
}
|
||||
|
||||
if (memcmp (&empty_clip, &program_state->clip, sizeof (GskRoundedRect)) == 0 ||
|
||||
memcmp (&builder->current_clip, &program_state->clip, sizeof (GskRoundedRect)) != 0)
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_CLIP);
|
||||
op->clip = *builder->current_clip;
|
||||
OpClip *opc;
|
||||
|
||||
opc = ops_begin (builder, OP_CHANGE_CLIP);
|
||||
opc->clip = *builder->current_clip;
|
||||
program_state->clip = *builder->current_clip;
|
||||
}
|
||||
|
||||
if (program_state->opacity != builder->current_opacity)
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_OPACITY);
|
||||
op->opacity = builder->current_opacity;
|
||||
OpOpacity *opo;
|
||||
|
||||
opo = ops_begin (builder, OP_CHANGE_OPACITY);
|
||||
opo->opacity = builder->current_opacity;
|
||||
program_state->opacity = builder->current_opacity;
|
||||
}
|
||||
}
|
||||
@ -267,29 +282,17 @@ static void
|
||||
ops_set_clip (RenderOpBuilder *builder,
|
||||
const GskRoundedRect *clip)
|
||||
{
|
||||
RenderOp *last_op;
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
OpClip *op;
|
||||
|
||||
if (current_program_state &&
|
||||
memcmp (¤t_program_state->clip, clip,sizeof (GskRoundedRect)) == 0)
|
||||
return;
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_CLIP)))
|
||||
op = op_buffer_add (&builder->render_ops, OP_CHANGE_CLIP);
|
||||
|
||||
if (last_op->op == OP_CHANGE_CLIP)
|
||||
{
|
||||
last_op->clip = *clip;
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderOp *op;
|
||||
|
||||
op = ops_begin (builder, OP_CHANGE_CLIP);
|
||||
op->clip = *clip;
|
||||
}
|
||||
}
|
||||
op->clip = *clip;
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
current_program_state->clip = *clip;
|
||||
@ -343,8 +346,8 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
|
||||
GskTransform *transform)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
graphene_matrix_t matrix;
|
||||
OpMatrix *op;
|
||||
|
||||
#if 0
|
||||
XXX This is not possible if we want pop() to work.
|
||||
@ -355,24 +358,10 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
|
||||
|
||||
gsk_transform_to_matrix (transform, &matrix);
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
if (last_op->op == OP_CHANGE_MODELVIEW)
|
||||
{
|
||||
last_op->modelview = matrix;
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_MODELVIEW);
|
||||
op->modelview = matrix;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_MODELVIEW);
|
||||
op->modelview = matrix;
|
||||
}
|
||||
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_MODELVIEW)))
|
||||
op = op_buffer_add (&builder->render_ops, OP_CHANGE_MODELVIEW);
|
||||
|
||||
op->matrix = matrix;
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
{
|
||||
@ -490,27 +479,13 @@ ops_set_projection (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *projection)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
graphene_matrix_t prev_mv;
|
||||
OpMatrix *op;
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
if (last_op->op == OP_CHANGE_PROJECTION)
|
||||
{
|
||||
last_op->projection = *projection;
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_PROJECTION);
|
||||
op->projection = *projection;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_PROJECTION);
|
||||
op->projection = *projection;
|
||||
}
|
||||
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_PROJECTION)))
|
||||
op = op_buffer_add (&builder->render_ops, OP_CHANGE_PROJECTION);
|
||||
|
||||
op->matrix = *projection;
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
current_program_state->projection = *projection;
|
||||
@ -526,7 +501,7 @@ ops_set_viewport (RenderOpBuilder *builder,
|
||||
const graphene_rect_t *viewport)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
OpViewport *op;
|
||||
graphene_rect_t prev_viewport;
|
||||
|
||||
if (current_program_state != NULL &&
|
||||
@ -549,7 +524,7 @@ void
|
||||
ops_set_texture (RenderOpBuilder *builder,
|
||||
int texture_id)
|
||||
{
|
||||
RenderOp *op;
|
||||
OpTexture *op;
|
||||
|
||||
if (builder->current_texture == texture_id)
|
||||
return;
|
||||
@ -563,7 +538,7 @@ int
|
||||
ops_set_render_target (RenderOpBuilder *builder,
|
||||
int render_target_id)
|
||||
{
|
||||
RenderOp *op;
|
||||
OpRenderTarget *op;
|
||||
int prev_render_target;
|
||||
|
||||
if (builder->current_render_target == render_target_id)
|
||||
@ -571,24 +546,10 @@ ops_set_render_target (RenderOpBuilder *builder,
|
||||
|
||||
prev_render_target = builder->current_render_target;
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
if (last_op->op == OP_CHANGE_RENDER_TARGET)
|
||||
{
|
||||
last_op->render_target_id = render_target_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_RENDER_TARGET);
|
||||
op->render_target_id = render_target_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_RENDER_TARGET);
|
||||
op->render_target_id = render_target_id;
|
||||
}
|
||||
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_RENDER_TARGET)))
|
||||
op = op_buffer_add (&builder->render_ops, OP_CHANGE_RENDER_TARGET);
|
||||
|
||||
op->render_target_id = render_target_id;
|
||||
|
||||
builder->current_render_target = render_target_id;
|
||||
|
||||
@ -600,32 +561,16 @@ ops_set_opacity (RenderOpBuilder *builder,
|
||||
float opacity)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
OpOpacity *op;
|
||||
float prev_opacity;
|
||||
RenderOp *last_op;
|
||||
|
||||
if (builder->current_opacity == opacity)
|
||||
return opacity;
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_OPACITY)))
|
||||
op = op_buffer_add (&builder->render_ops, OP_CHANGE_OPACITY);
|
||||
|
||||
if (last_op->op == OP_CHANGE_OPACITY)
|
||||
{
|
||||
last_op->opacity = opacity;
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_OPACITY);
|
||||
op->opacity = opacity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op = ops_begin (builder, OP_CHANGE_OPACITY);
|
||||
op->opacity = opacity;
|
||||
}
|
||||
op->opacity = opacity;
|
||||
|
||||
prev_opacity = builder->current_opacity;
|
||||
builder->current_opacity = opacity;
|
||||
@ -641,7 +586,7 @@ ops_set_color (RenderOpBuilder *builder,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
OpColor *op;
|
||||
|
||||
if (gdk_rgba_equal (color, ¤t_program_state->color))
|
||||
return;
|
||||
@ -649,7 +594,7 @@ ops_set_color (RenderOpBuilder *builder,
|
||||
current_program_state->color = *color;
|
||||
|
||||
op = ops_begin (builder, OP_CHANGE_COLOR);
|
||||
op->color = color;
|
||||
op->rgba = *color;
|
||||
}
|
||||
|
||||
void
|
||||
@ -658,7 +603,7 @@ ops_set_color_matrix (RenderOpBuilder *builder,
|
||||
const graphene_vec4_t *offset)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
OpColorMatrix *op;
|
||||
|
||||
if (memcmp (matrix,
|
||||
¤t_program_state->color_matrix.matrix,
|
||||
@ -672,8 +617,8 @@ ops_set_color_matrix (RenderOpBuilder *builder,
|
||||
current_program_state->color_matrix.offset = *offset;
|
||||
|
||||
op = ops_begin (builder, OP_CHANGE_COLOR_MATRIX);
|
||||
op->color_matrix.matrix = *matrix;
|
||||
op->color_matrix.offset = *offset;
|
||||
op->matrix = *matrix;
|
||||
op->offset = *offset;
|
||||
}
|
||||
|
||||
void
|
||||
@ -681,7 +626,7 @@ ops_set_border (RenderOpBuilder *builder,
|
||||
const GskRoundedRect *outline)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
OpBorder *op;
|
||||
|
||||
if (memcmp (¤t_program_state->border.outline,
|
||||
outline, sizeof (GskRoundedRect)) == 0)
|
||||
@ -690,7 +635,7 @@ ops_set_border (RenderOpBuilder *builder,
|
||||
current_program_state->border.outline = *outline;
|
||||
|
||||
op = ops_begin (builder, OP_CHANGE_BORDER);
|
||||
op->border.outline = *outline;
|
||||
op->outline = *outline;
|
||||
}
|
||||
|
||||
void
|
||||
@ -698,7 +643,7 @@ ops_set_border_width (RenderOpBuilder *builder,
|
||||
const float *widths)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp *op;
|
||||
OpBorder *op;
|
||||
|
||||
if (memcmp (current_program_state->border.widths,
|
||||
widths, sizeof (float) * 4) == 0)
|
||||
@ -708,10 +653,10 @@ ops_set_border_width (RenderOpBuilder *builder,
|
||||
widths, sizeof (float) * 4);
|
||||
|
||||
op = ops_begin (builder, OP_CHANGE_BORDER_WIDTH);
|
||||
op->border.widths[0] = widths[0];
|
||||
op->border.widths[1] = widths[1];
|
||||
op->border.widths[2] = widths[2];
|
||||
op->border.widths[3] = widths[3];
|
||||
op->widths[0] = widths[0];
|
||||
op->widths[1] = widths[1];
|
||||
op->widths[2] = widths[2];
|
||||
op->widths[3] = widths[3];
|
||||
}
|
||||
|
||||
void
|
||||
@ -719,68 +664,37 @@ ops_set_border_color (RenderOpBuilder *builder,
|
||||
const GdkRGBA *color)
|
||||
{
|
||||
ProgramState *current_program_state = get_current_program_state (builder);
|
||||
RenderOp op;
|
||||
op.op = OP_CHANGE_BORDER_COLOR;
|
||||
rgba_to_float (color, op.border.color);
|
||||
OpBorder *op;
|
||||
float fcolor[4];
|
||||
|
||||
if (memcmp (&op.border.color, ¤t_program_state->border.color,
|
||||
sizeof (float) * 4) == 0)
|
||||
rgba_to_float (color, fcolor);
|
||||
|
||||
if (memcmp (fcolor, ¤t_program_state->border.color, sizeof fcolor) == 0)
|
||||
return;
|
||||
|
||||
rgba_to_float (color, current_program_state->border.color);
|
||||
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
op = op_buffer_add (&builder->render_ops, OP_CHANGE_BORDER_COLOR);
|
||||
memcpy (op->color, fcolor, sizeof (float[4]));
|
||||
memcpy (current_program_state->border.color, fcolor, sizeof (float[4]));
|
||||
}
|
||||
|
||||
void
|
||||
ops_draw (RenderOpBuilder *builder,
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES])
|
||||
{
|
||||
RenderOp *last_op;
|
||||
OpDraw *op;
|
||||
|
||||
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
/* If the previous op was a DRAW as well, we didn't change anything between the two calls,
|
||||
* so these are just 2 subsequent draw calls. Same VAO, same program etc.
|
||||
* And the offsets into the vao are in order as well, so make it one draw call. */
|
||||
if (last_op->op == OP_DRAW)
|
||||
if ((op = op_buffer_peek_tail_checked (&builder->render_ops, OP_DRAW)))
|
||||
{
|
||||
/* We allow ourselves a little trick here. We still have to add a CHANGE_VAO op for
|
||||
* this draw call so we can add our vertex data there, but we want it to be placed before
|
||||
* the last draw call, so we reorder those. */
|
||||
RenderOp *new_draw;
|
||||
|
||||
new_draw = ops_begin (builder, OP_DRAW);
|
||||
|
||||
/* last_op may have moved in memory */
|
||||
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 2);
|
||||
|
||||
new_draw->draw.vao_offset = last_op->draw.vao_offset;
|
||||
new_draw->draw.vao_size = last_op->draw.vao_size + GL_N_VERTICES;
|
||||
|
||||
last_op->op = OP_CHANGE_VAO;
|
||||
memcpy (&last_op->vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
|
||||
op->vao_size += GL_N_VERTICES;
|
||||
}
|
||||
else
|
||||
{
|
||||
const gsize n_ops = builder->render_ops->len;
|
||||
RenderOp *op;
|
||||
gsize offset = builder->buffer_size / sizeof (GskQuadVertex);
|
||||
|
||||
/* We will add two render ops here. */
|
||||
g_array_set_size (builder->render_ops, n_ops + 2);
|
||||
|
||||
op = &g_array_index (builder->render_ops, RenderOp, n_ops);
|
||||
op->op = OP_CHANGE_VAO;
|
||||
memcpy (&op->vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
|
||||
|
||||
op = &g_array_index (builder->render_ops, RenderOp, n_ops + 1);
|
||||
op->op = OP_DRAW;
|
||||
op->draw.vao_offset = offset;
|
||||
op->draw.vao_size = GL_N_VERTICES;
|
||||
op = op_buffer_add (&builder->render_ops, OP_DRAW);
|
||||
op->vao_offset = builder->vertices->len;
|
||||
op->vao_size = GL_N_VERTICES;
|
||||
}
|
||||
|
||||
/* We added new vertex data in both cases so increase the buffer size */
|
||||
builder->buffer_size += sizeof (GskQuadVertex) * GL_N_VERTICES;
|
||||
g_array_append_vals (builder->vertices, vertex_data, GL_N_VERTICES);
|
||||
}
|
||||
|
||||
/* The offset is only valid for the current modelview.
|
||||
@ -795,15 +709,22 @@ ops_offset (RenderOpBuilder *builder,
|
||||
builder->dy += y;
|
||||
}
|
||||
|
||||
RenderOp *
|
||||
gpointer
|
||||
ops_begin (RenderOpBuilder *builder,
|
||||
guint kind)
|
||||
OpKind kind)
|
||||
{
|
||||
RenderOp *op;
|
||||
|
||||
g_array_set_size (builder->render_ops, builder->render_ops->len + 1);
|
||||
op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
op->op = kind;
|
||||
|
||||
return op;
|
||||
return op_buffer_add (&builder->render_ops, kind);
|
||||
}
|
||||
|
||||
void
|
||||
ops_reset (RenderOpBuilder *builder)
|
||||
{
|
||||
op_buffer_clear (&builder->render_ops);
|
||||
g_array_set_size (builder->vertices, 0);
|
||||
}
|
||||
|
||||
OpBuffer *
|
||||
ops_get_buffer (RenderOpBuilder *builder)
|
||||
{
|
||||
return &builder->render_ops;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "gskglrenderer.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
|
||||
#include "opbuffer.h"
|
||||
|
||||
#define GL_N_VERTICES 6
|
||||
#define GL_N_PROGRAMS 13
|
||||
|
||||
@ -32,38 +34,7 @@ typedef struct
|
||||
OpsMatrixMetadata metadata;
|
||||
} MatrixStackEntry;
|
||||
|
||||
enum {
|
||||
OP_NONE,
|
||||
OP_CHANGE_OPACITY = 1,
|
||||
OP_CHANGE_COLOR = 2,
|
||||
OP_CHANGE_PROJECTION = 3,
|
||||
OP_CHANGE_MODELVIEW = 4,
|
||||
OP_CHANGE_PROGRAM = 5,
|
||||
OP_CHANGE_RENDER_TARGET = 6,
|
||||
OP_CHANGE_CLIP = 7,
|
||||
OP_CHANGE_VIEWPORT = 8,
|
||||
OP_CHANGE_SOURCE_TEXTURE = 9,
|
||||
OP_CHANGE_VAO = 10,
|
||||
OP_CHANGE_LINEAR_GRADIENT = 11,
|
||||
OP_CHANGE_COLOR_MATRIX = 12,
|
||||
OP_CHANGE_BLUR = 13,
|
||||
OP_CHANGE_INSET_SHADOW = 14,
|
||||
OP_CHANGE_OUTSET_SHADOW = 15,
|
||||
OP_CHANGE_BORDER = 16,
|
||||
OP_CHANGE_BORDER_COLOR = 17,
|
||||
OP_CHANGE_BORDER_WIDTH = 18,
|
||||
OP_CHANGE_CROSS_FADE = 19,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
|
||||
OP_CLEAR = 21,
|
||||
OP_DRAW = 22,
|
||||
OP_DUMP_FRAMEBUFFER = 23,
|
||||
OP_PUSH_DEBUG_GROUP = 24,
|
||||
OP_POP_DEBUG_GROUP = 25,
|
||||
OP_CHANGE_BLEND = 26,
|
||||
OP_CHANGE_REPEAT = 27,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
struct _Program
|
||||
{
|
||||
int index; /* Into the renderer's program array */
|
||||
|
||||
@ -145,101 +116,7 @@ typedef struct
|
||||
int texture_rect_location;
|
||||
} repeat;
|
||||
};
|
||||
|
||||
} Program;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint op;
|
||||
|
||||
union {
|
||||
float opacity;
|
||||
graphene_matrix_t modelview;
|
||||
graphene_matrix_t projection;
|
||||
const Program *program;
|
||||
int texture_id;
|
||||
int render_target_id;
|
||||
const GdkRGBA *color;
|
||||
GskQuadVertex vertex_data[6];
|
||||
GskRoundedRect clip;
|
||||
graphene_rect_t viewport;
|
||||
struct {
|
||||
int n_color_stops;
|
||||
float color_offsets[8];
|
||||
float color_stops[4 * 8];
|
||||
graphene_point_t start_point;
|
||||
graphene_point_t end_point;
|
||||
} linear_gradient;
|
||||
struct {
|
||||
gsize vao_offset;
|
||||
gsize vao_size;
|
||||
} draw;
|
||||
struct {
|
||||
graphene_matrix_t matrix;
|
||||
graphene_vec4_t offset;
|
||||
} color_matrix;
|
||||
struct {
|
||||
float radius;
|
||||
graphene_size_t size;
|
||||
float dir[2];
|
||||
} blur;
|
||||
struct {
|
||||
float outline[4];
|
||||
float corner_widths[4];
|
||||
float corner_heights[4];
|
||||
float radius;
|
||||
float spread;
|
||||
float offset[2];
|
||||
float color[4];
|
||||
} inset_shadow;
|
||||
struct {
|
||||
float outline[4];
|
||||
float corner_widths[4];
|
||||
float corner_heights[4];
|
||||
float radius;
|
||||
float spread;
|
||||
float offset[2];
|
||||
float color[4];
|
||||
} outset_shadow;
|
||||
struct {
|
||||
float outline[4];
|
||||
float corner_widths[4];
|
||||
float corner_heights[4];
|
||||
float radius;
|
||||
float spread;
|
||||
float offset[2];
|
||||
float color[4];
|
||||
} unblurred_outset_shadow;
|
||||
struct {
|
||||
float color[4];
|
||||
} shadow;
|
||||
struct {
|
||||
float widths[4];
|
||||
float color[4];
|
||||
GskRoundedRect outline;
|
||||
} border;
|
||||
struct {
|
||||
float progress;
|
||||
int source2;
|
||||
} cross_fade;
|
||||
struct {
|
||||
int source2;
|
||||
int mode;
|
||||
} blend;
|
||||
struct {
|
||||
float child_bounds[4];
|
||||
float texture_rect[4];
|
||||
} repeat;
|
||||
struct {
|
||||
char *filename;
|
||||
int width;
|
||||
int height;
|
||||
} dump;
|
||||
struct {
|
||||
char text[180]; /* Size of linear_gradient, so 'should be enough' without growing RenderOp */
|
||||
} debug_group;
|
||||
};
|
||||
} RenderOp;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -276,9 +153,9 @@ typedef struct
|
||||
float current_opacity;
|
||||
float dx, dy;
|
||||
|
||||
gsize buffer_size;
|
||||
OpBuffer render_ops;
|
||||
GArray *vertices;
|
||||
|
||||
GArray *render_ops;
|
||||
GskGLRenderer *renderer;
|
||||
|
||||
/* Stack of modelview matrices */
|
||||
@ -298,6 +175,7 @@ void ops_dump_framebuffer (RenderOpBuilder *builder,
|
||||
int height);
|
||||
void ops_init (RenderOpBuilder *builder);
|
||||
void ops_free (RenderOpBuilder *builder);
|
||||
void ops_reset (RenderOpBuilder *builder);
|
||||
void ops_push_debug_group (RenderOpBuilder *builder,
|
||||
const char *text);
|
||||
void ops_pop_debug_group (RenderOpBuilder *builder);
|
||||
@ -358,7 +236,8 @@ void ops_offset (RenderOpBuilder *builder,
|
||||
float x,
|
||||
float y);
|
||||
|
||||
RenderOp *ops_begin (RenderOpBuilder *builder,
|
||||
guint kind);
|
||||
gpointer ops_begin (RenderOpBuilder *builder,
|
||||
OpKind kind);
|
||||
OpBuffer *ops_get_buffer (RenderOpBuilder *builder);
|
||||
|
||||
#endif
|
||||
|
133
gsk/gl/opbuffer.c
Normal file
133
gsk/gl/opbuffer.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include "opbuffer.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static guint op_sizes[OP_LAST] = {
|
||||
0,
|
||||
sizeof (OpOpacity),
|
||||
sizeof (OpColor),
|
||||
sizeof (OpMatrix),
|
||||
sizeof (OpMatrix),
|
||||
sizeof (OpProgram),
|
||||
sizeof (OpRenderTarget),
|
||||
sizeof (OpClip),
|
||||
sizeof (OpViewport),
|
||||
sizeof (OpTexture),
|
||||
sizeof (OpRepeat),
|
||||
sizeof (OpLinearGradient),
|
||||
sizeof (OpColorMatrix),
|
||||
sizeof (OpBlur),
|
||||
sizeof (OpShadow),
|
||||
sizeof (OpShadow),
|
||||
sizeof (OpBorder),
|
||||
sizeof (OpBorder),
|
||||
sizeof (OpBorder),
|
||||
sizeof (OpCrossFade),
|
||||
sizeof (OpShadow),
|
||||
0,
|
||||
sizeof (OpDraw),
|
||||
sizeof (OpDumpFrameBuffer),
|
||||
sizeof (OpDebugGroup),
|
||||
0,
|
||||
sizeof (OpBlend),
|
||||
};
|
||||
|
||||
void
|
||||
op_buffer_init (OpBuffer *buffer)
|
||||
{
|
||||
static gsize initialized = FALSE;
|
||||
|
||||
if (g_once_init_enter (&initialized))
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (op_sizes); i++)
|
||||
{
|
||||
guint size = op_sizes[i];
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
/* Round all op entry sizes to the nearest 16 to ensure
|
||||
* that we guarantee proper alignments for all op entries.
|
||||
* This is only done once on first use.
|
||||
*/
|
||||
#define CHECK_SIZE(s) else if (size < (s)) { size = s; }
|
||||
if (0) {}
|
||||
CHECK_SIZE (16)
|
||||
CHECK_SIZE (32)
|
||||
CHECK_SIZE (48)
|
||||
CHECK_SIZE (64)
|
||||
CHECK_SIZE (80)
|
||||
CHECK_SIZE (96)
|
||||
CHECK_SIZE (112)
|
||||
CHECK_SIZE (128)
|
||||
CHECK_SIZE (144)
|
||||
CHECK_SIZE (160)
|
||||
CHECK_SIZE (176)
|
||||
CHECK_SIZE (192)
|
||||
else g_assert_not_reached ();
|
||||
#undef CHECK_SIZE
|
||||
|
||||
op_sizes[i] = size;
|
||||
}
|
||||
}
|
||||
|
||||
g_once_init_leave (&initialized, TRUE);
|
||||
}
|
||||
|
||||
memset (buffer, 0, sizeof *buffer);
|
||||
|
||||
buffer->buflen = 4096;
|
||||
buffer->bufpos = 0;
|
||||
buffer->buf = g_malloc (buffer->buflen);
|
||||
buffer->index = g_array_new (FALSE, FALSE, sizeof (OpBufferEntry));
|
||||
|
||||
/* Add dummy entry to guarantee non-empty index */
|
||||
op_buffer_add (buffer, OP_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
op_buffer_destroy (OpBuffer *buffer)
|
||||
{
|
||||
g_free (buffer->buf);
|
||||
g_array_unref (buffer->index);
|
||||
}
|
||||
|
||||
void
|
||||
op_buffer_clear (OpBuffer *buffer)
|
||||
{
|
||||
if (buffer->index->len > 1)
|
||||
g_array_remove_range (buffer->index, 1, buffer->index->len - 1);
|
||||
buffer->bufpos = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ensure_buffer_space_for (OpBuffer *buffer,
|
||||
guint size)
|
||||
{
|
||||
if G_UNLIKELY (buffer->bufpos + size >= buffer->buflen)
|
||||
{
|
||||
buffer->buflen *= 2;
|
||||
buffer->buf = g_realloc (buffer->buf, buffer->buflen);
|
||||
}
|
||||
}
|
||||
|
||||
gpointer
|
||||
op_buffer_add (OpBuffer *buffer,
|
||||
OpKind kind)
|
||||
{
|
||||
guint size = op_sizes[kind];
|
||||
OpBufferEntry entry;
|
||||
|
||||
entry.pos = buffer->bufpos;
|
||||
entry.kind = kind;
|
||||
|
||||
if (size > 0)
|
||||
ensure_buffer_space_for (buffer, size);
|
||||
|
||||
g_array_append_val (buffer->index, entry);
|
||||
|
||||
buffer->bufpos += size;
|
||||
|
||||
return &buffer->buf[entry.pos];
|
||||
}
|
257
gsk/gl/opbuffer.h
Normal file
257
gsk/gl/opbuffer.h
Normal file
@ -0,0 +1,257 @@
|
||||
#ifndef __OP_BUFFER_H__
|
||||
#define __OP_BUFFER_H__
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gsk/gsk.h>
|
||||
#include <graphene.h>
|
||||
|
||||
#include "gskgldriverprivate.h"
|
||||
|
||||
typedef struct _Program Program;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OP_NONE = 0,
|
||||
OP_CHANGE_OPACITY = 1,
|
||||
OP_CHANGE_COLOR = 2,
|
||||
OP_CHANGE_PROJECTION = 3,
|
||||
OP_CHANGE_MODELVIEW = 4,
|
||||
OP_CHANGE_PROGRAM = 5,
|
||||
OP_CHANGE_RENDER_TARGET = 6,
|
||||
OP_CHANGE_CLIP = 7,
|
||||
OP_CHANGE_VIEWPORT = 8,
|
||||
OP_CHANGE_SOURCE_TEXTURE = 9,
|
||||
OP_CHANGE_REPEAT = 10,
|
||||
OP_CHANGE_LINEAR_GRADIENT = 11,
|
||||
OP_CHANGE_COLOR_MATRIX = 12,
|
||||
OP_CHANGE_BLUR = 13,
|
||||
OP_CHANGE_INSET_SHADOW = 14,
|
||||
OP_CHANGE_OUTSET_SHADOW = 15,
|
||||
OP_CHANGE_BORDER = 16,
|
||||
OP_CHANGE_BORDER_COLOR = 17,
|
||||
OP_CHANGE_BORDER_WIDTH = 18,
|
||||
OP_CHANGE_CROSS_FADE = 19,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
|
||||
OP_CLEAR = 21,
|
||||
OP_DRAW = 22,
|
||||
OP_DUMP_FRAMEBUFFER = 23,
|
||||
OP_PUSH_DEBUG_GROUP = 24,
|
||||
OP_POP_DEBUG_GROUP = 25,
|
||||
OP_CHANGE_BLEND = 26,
|
||||
OP_LAST
|
||||
} OpKind;
|
||||
|
||||
/* OpNode are allocated within OpBuffer.pos, but we keep
|
||||
* a secondary index into the locations of that buffer
|
||||
* from OpBuffer.index. This allows peeking at the kind
|
||||
* and quickly replacing existing entries when necessary.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
guint pos;
|
||||
OpKind kind;
|
||||
} OpBufferEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint8 *buf;
|
||||
gsize buflen;
|
||||
gsize bufpos;
|
||||
GArray *index;
|
||||
} OpBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float opacity;
|
||||
} OpOpacity;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
} OpMatrix;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const Program *program;
|
||||
} OpProgram;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
} OpColor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int render_target_id;
|
||||
} OpRenderTarget;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GskRoundedRect clip;
|
||||
} OpClip;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
graphene_rect_t viewport;
|
||||
} OpViewport;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int texture_id;
|
||||
} OpTexture;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gsize vao_offset;
|
||||
gsize vao_size;
|
||||
} OpDraw;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float color_offsets[8];
|
||||
float color_stops[4 * 8];
|
||||
graphene_point_t start_point;
|
||||
graphene_point_t end_point;
|
||||
int n_color_stops;
|
||||
} OpLinearGradient;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
graphene_vec4_t offset;
|
||||
} OpColorMatrix;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float radius;
|
||||
graphene_size_t size;
|
||||
float dir[2];
|
||||
} OpBlur;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float outline[4];
|
||||
float corner_widths[4];
|
||||
float corner_heights[4];
|
||||
float radius;
|
||||
float spread;
|
||||
float offset[2];
|
||||
float color[4];
|
||||
} OpShadow;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float widths[4];
|
||||
float color[4];
|
||||
GskRoundedRect outline;
|
||||
} OpBorder;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float progress;
|
||||
int source2;
|
||||
} OpCrossFade;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
int width;
|
||||
int height;
|
||||
} OpDumpFrameBuffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char text[64];
|
||||
} OpDebugGroup;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int source2;
|
||||
int mode;
|
||||
} OpBlend;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float child_bounds[4];
|
||||
float texture_rect[4];
|
||||
} OpRepeat;
|
||||
|
||||
void op_buffer_init (OpBuffer *buffer);
|
||||
void op_buffer_destroy (OpBuffer *buffer);
|
||||
void op_buffer_clear (OpBuffer *buffer);
|
||||
gpointer op_buffer_add (OpBuffer *buffer,
|
||||
OpKind kind);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GArray *index;
|
||||
OpBuffer *buffer;
|
||||
guint pos;
|
||||
} OpBufferIter;
|
||||
|
||||
static inline void
|
||||
op_buffer_iter_init (OpBufferIter *iter,
|
||||
OpBuffer *buffer)
|
||||
{
|
||||
iter->index = buffer->index;
|
||||
iter->buffer = buffer;
|
||||
iter->pos = 1; /* Skip first OP_NONE */
|
||||
}
|
||||
|
||||
static inline gpointer
|
||||
op_buffer_iter_next (OpBufferIter *iter,
|
||||
OpKind *kind)
|
||||
{
|
||||
const OpBufferEntry *entry;
|
||||
|
||||
if (iter->pos == iter->index->len)
|
||||
return NULL;
|
||||
|
||||
entry = &g_array_index (iter->index, OpBufferEntry, iter->pos);
|
||||
|
||||
iter->pos++;
|
||||
|
||||
*kind = entry->kind;
|
||||
return &iter->buffer->buf[entry->pos];
|
||||
}
|
||||
|
||||
static inline void
|
||||
op_buffer_pop_tail (OpBuffer *buffer)
|
||||
{
|
||||
/* Never truncate the first OP_NONE */
|
||||
if G_LIKELY (buffer->index->len > 0)
|
||||
buffer->index->len--;
|
||||
}
|
||||
|
||||
static inline gpointer
|
||||
op_buffer_peek_tail (OpBuffer *buffer,
|
||||
OpKind *kind)
|
||||
{
|
||||
const OpBufferEntry *entry;
|
||||
|
||||
entry = &g_array_index (buffer->index, OpBufferEntry, buffer->index->len - 1);
|
||||
*kind = entry->kind;
|
||||
return &buffer->buf[entry->pos];
|
||||
}
|
||||
|
||||
static inline gpointer
|
||||
op_buffer_peek_tail_checked (OpBuffer *buffer,
|
||||
OpKind kind)
|
||||
{
|
||||
const OpBufferEntry *entry;
|
||||
|
||||
entry = &g_array_index (buffer->index, OpBufferEntry, buffer->index->len - 1);
|
||||
|
||||
if (entry->kind == kind)
|
||||
return &buffer->buf[entry->pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline guint
|
||||
op_buffer_n_ops (OpBuffer *buffer)
|
||||
{
|
||||
return buffer->index->len - 1;
|
||||
}
|
||||
|
||||
#endif /* __OP_BUFFER_H__ */
|
@ -3414,6 +3414,7 @@ struct _GskTextNode
|
||||
GdkRGBA color;
|
||||
graphene_point_t offset;
|
||||
|
||||
gpointer render_data;
|
||||
guint num_glyphs;
|
||||
PangoGlyphInfo glyphs[];
|
||||
};
|
||||
@ -3423,6 +3424,7 @@ gsk_text_node_finalize (GskRenderNode *node)
|
||||
{
|
||||
GskTextNode *self = (GskTextNode *) node;
|
||||
|
||||
g_free (self->render_data);
|
||||
g_object_unref (self->font);
|
||||
}
|
||||
|
||||
@ -3545,6 +3547,7 @@ gsk_text_node_new (PangoFont *font,
|
||||
self->has_color_glyphs = font_has_color_glyphs (font);
|
||||
self->color = *color;
|
||||
self->offset = *offset;
|
||||
self->render_data = NULL;
|
||||
self->num_glyphs = glyphs->num_glyphs;
|
||||
memcpy (self->glyphs, glyphs->glyphs, sizeof (PangoGlyphInfo) * glyphs->num_glyphs);
|
||||
|
||||
@ -3625,6 +3628,24 @@ gsk_text_node_get_offset (GskRenderNode *node)
|
||||
return &self->offset;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_text_node_set_render_data (GskRenderNode *node,
|
||||
gpointer data)
|
||||
{
|
||||
GskTextNode *self = (GskTextNode *) node;
|
||||
|
||||
self->render_data = data;
|
||||
}
|
||||
|
||||
gpointer
|
||||
gsk_text_node_get_render_data (GskRenderNode *node)
|
||||
{
|
||||
GskTextNode *self = (GskTextNode *) node;
|
||||
|
||||
return self->render_data;
|
||||
}
|
||||
|
||||
|
||||
/*** GSK_BLUR_NODE ***/
|
||||
|
||||
typedef struct _GskBlurNode GskBlurNode;
|
||||
|
@ -46,6 +46,10 @@ void gsk_render_node_diff (GskRenderNode *nod
|
||||
void gsk_render_node_diff_impossible (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
cairo_region_t *region);
|
||||
void gsk_text_node_set_render_data (GskRenderNode *node,
|
||||
gpointer data);
|
||||
gpointer gsk_text_node_get_render_data (GskRenderNode *node);
|
||||
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -48,6 +48,7 @@ gsk_private_sources = files([
|
||||
'gl/gskglnodesample.c',
|
||||
'gl/gskgltextureatlas.c',
|
||||
'gl/gskgliconcache.c',
|
||||
'gl/opbuffer.c',
|
||||
'gl/stb_rect_pack.c',
|
||||
])
|
||||
|
||||
|
@ -22,13 +22,35 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
gdouble scale,
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_stream (GInputStream *stream,
|
||||
const char *format,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean aspect,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_resource_scaled (const gchar *resource_path,
|
||||
gdouble scale,
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
const char *format,
|
||||
double scale,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_resource (const char *resource_path,
|
||||
const char *format,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_resource_at_scale (const char *resource_path,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean preserve_aspect,
|
||||
GError **error);
|
||||
GdkPixbuf *_gdk_pixbuf_new_from_resource_scaled (const char *resource_path,
|
||||
const char *format,
|
||||
double scale,
|
||||
GError **error);
|
||||
|
||||
GdkPixbuf *gtk_make_symbolic_pixbuf_from_data (const char *data,
|
||||
gsize len,
|
||||
|
@ -3276,17 +3276,16 @@ gtk_icon_info_get_filename (GtkIconInfo *icon_info)
|
||||
gboolean
|
||||
gtk_icon_info_is_symbolic (GtkIconInfo *icon_info)
|
||||
{
|
||||
gchar *icon_uri;
|
||||
const char *path;
|
||||
gboolean is_symbolic;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ICON_INFO (icon_info), FALSE);
|
||||
|
||||
icon_uri = NULL;
|
||||
path = NULL;
|
||||
if (icon_info->icon_file)
|
||||
icon_uri = g_file_get_uri (icon_info->icon_file);
|
||||
path = g_file_peek_path (icon_info->icon_file);
|
||||
|
||||
is_symbolic = (icon_uri != NULL) && (icon_uri_is_symbolic (icon_uri, -1));
|
||||
g_free (icon_uri);
|
||||
is_symbolic = (path != NULL) && (icon_uri_is_symbolic (path, -1));
|
||||
|
||||
return is_symbolic;
|
||||
}
|
||||
@ -3384,16 +3383,19 @@ icon_info_ensure_scale_and_texture (GtkIconInfo *icon_info)
|
||||
&icon_info->load_error);
|
||||
else if (size == 0)
|
||||
source_pixbuf = _gdk_pixbuf_new_from_resource_scaled (icon_info->filename,
|
||||
"svg",
|
||||
icon_info->desired_scale,
|
||||
&icon_info->load_error);
|
||||
else
|
||||
source_pixbuf = gdk_pixbuf_new_from_resource_at_scale (icon_info->filename,
|
||||
size, size, TRUE,
|
||||
&icon_info->load_error);
|
||||
source_pixbuf = _gdk_pixbuf_new_from_resource_at_scale (icon_info->filename,
|
||||
"svg",
|
||||
size, size, TRUE,
|
||||
&icon_info->load_error);
|
||||
}
|
||||
else
|
||||
source_pixbuf = gdk_pixbuf_new_from_resource (icon_info->filename,
|
||||
&icon_info->load_error);
|
||||
source_pixbuf = _gdk_pixbuf_new_from_resource (icon_info->filename,
|
||||
"png",
|
||||
&icon_info->load_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3425,19 +3427,22 @@ icon_info_ensure_scale_and_texture (GtkIconInfo *icon_info)
|
||||
&icon_info->load_error);
|
||||
else if (size == 0)
|
||||
source_pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream,
|
||||
"svg",
|
||||
icon_info->desired_scale,
|
||||
NULL,
|
||||
&icon_info->load_error);
|
||||
else
|
||||
source_pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
|
||||
size, size,
|
||||
TRUE, NULL,
|
||||
source_pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream,
|
||||
"svg",
|
||||
size, size,
|
||||
TRUE, NULL,
|
||||
&icon_info->load_error);
|
||||
}
|
||||
else
|
||||
source_pixbuf = gdk_pixbuf_new_from_stream (stream,
|
||||
NULL,
|
||||
&icon_info->load_error);
|
||||
source_pixbuf = _gdk_pixbuf_new_from_stream (stream,
|
||||
"png",
|
||||
NULL,
|
||||
&icon_info->load_error);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
}
|
||||
@ -3938,7 +3943,8 @@ gtk_icon_info_load_symbolic_svg (GtkIconInfo *icon_info,
|
||||
g_free (height);
|
||||
|
||||
stream = g_memory_input_stream_new_from_data (data, -1, g_free);
|
||||
pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream,
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream,
|
||||
"svg",
|
||||
gdk_texture_get_width (icon_info->texture),
|
||||
gdk_texture_get_height (icon_info->texture),
|
||||
TRUE,
|
||||
|
@ -90,6 +90,7 @@ size_prepared_cb (GdkPixbufLoader *loader,
|
||||
*/
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
const char *format,
|
||||
gdouble scale,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
@ -97,10 +98,18 @@ _gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
GdkPixbufLoader *loader;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
if (format)
|
||||
{
|
||||
loader = gdk_pixbuf_loader_new_with_type (format, error);
|
||||
if (!loader)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
|
||||
g_signal_connect (loader, "size-prepared",
|
||||
G_CALLBACK (size_prepared_cb), &scale);
|
||||
if (scale != 0)
|
||||
g_signal_connect (loader, "size-prepared",
|
||||
G_CALLBACK (size_prepared_cb), &scale);
|
||||
|
||||
pixbuf = load_from_stream (loader, stream, cancellable, error);
|
||||
|
||||
@ -109,14 +118,69 @@ _gdk_pixbuf_new_from_stream_scaled (GInputStream *stream,
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
size_prepared_cb2 (GdkPixbufLoader *loader,
|
||||
gint width,
|
||||
gint height,
|
||||
gpointer data)
|
||||
{
|
||||
int *scales = data;
|
||||
|
||||
gdk_pixbuf_loader_set_size (loader, scales[0], scales[1]);
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_stream_at_scale (GInputStream *stream,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean aspect,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GdkPixbufLoader *loader;
|
||||
GdkPixbuf *pixbuf;
|
||||
int scales[2];
|
||||
|
||||
if (format)
|
||||
{
|
||||
loader = gdk_pixbuf_loader_new_with_type (format, error);
|
||||
if (!loader)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
loader = gdk_pixbuf_loader_new ();
|
||||
|
||||
scales[0] = width;
|
||||
scales[1] = height;
|
||||
g_signal_connect (loader, "size-prepared",
|
||||
G_CALLBACK (size_prepared_cb2), scales);
|
||||
|
||||
pixbuf = load_from_stream (loader, stream, cancellable, error);
|
||||
|
||||
g_object_unref (loader);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_stream (GInputStream *stream,
|
||||
const char *format,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return _gdk_pixbuf_new_from_stream_scaled (stream, format, 0, cancellable, error);
|
||||
}
|
||||
|
||||
/* Like gdk_pixbuf_new_from_resource_at_scale, but
|
||||
* load the image at its original size times the
|
||||
* given scale.
|
||||
*/
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_resource_scaled (const gchar *resource_path,
|
||||
gdouble scale,
|
||||
GError **error)
|
||||
_gdk_pixbuf_new_from_resource_scaled (const char *resource_path,
|
||||
const char *format,
|
||||
double scale,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
@ -125,12 +189,42 @@ _gdk_pixbuf_new_from_resource_scaled (const gchar *resource_path,
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, scale, NULL, error);
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_scaled (stream, format, scale, NULL, error);
|
||||
g_object_unref (stream);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_resource (const char *resource_path,
|
||||
const char *format,
|
||||
GError **error)
|
||||
{
|
||||
return _gdk_pixbuf_new_from_resource_scaled (resource_path, format, 0, error);
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
_gdk_pixbuf_new_from_resource_at_scale (const char *resource_path,
|
||||
const char *format,
|
||||
int width,
|
||||
int height,
|
||||
gboolean preserve_aspect,
|
||||
GError **error)
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
stream = g_resources_open_stream (resource_path, 0, error);
|
||||
if (stream == NULL)
|
||||
return NULL;
|
||||
|
||||
pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream, format, width, height, preserve_aspect, NULL, error);
|
||||
g_object_unref (stream);
|
||||
|
||||
return pixbuf;
|
||||
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
load_symbolic_svg (const char *escaped_file_data,
|
||||
int width,
|
||||
@ -332,11 +426,11 @@ gtk_make_symbolic_pixbuf_from_resource (const char *path,
|
||||
}
|
||||
|
||||
GdkPixbuf *
|
||||
gtk_make_symbolic_pixbuf_from_file (GFile *file,
|
||||
int width,
|
||||
int height,
|
||||
double scale,
|
||||
GError **error)
|
||||
gtk_make_symbolic_pixbuf_from_file (GFile *file,
|
||||
int width,
|
||||
int height,
|
||||
double scale,
|
||||
GError **error)
|
||||
{
|
||||
char *data;
|
||||
gsize size;
|
||||
@ -373,11 +467,11 @@ gtk_make_symbolic_texture_from_resource (const char *path,
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gtk_make_symbolic_texture_from_file (GFile *file,
|
||||
int width,
|
||||
int height,
|
||||
double scale,
|
||||
GError **error)
|
||||
gtk_make_symbolic_texture_from_file (GFile *file,
|
||||
int width,
|
||||
int height,
|
||||
double scale,
|
||||
GError **error)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
|
Loading…
Reference in New Issue
Block a user