forked from AuroraMiddleware/gtk
gl renderer: Implement a subset of repeat nodes
This commit is contained in:
parent
8d1a2247e0
commit
2914c360a9
@ -340,6 +340,7 @@ struct _GskGLRenderer
|
||||
Program border_program;
|
||||
Program cross_fade_program;
|
||||
Program blend_program;
|
||||
Program repeat_program;
|
||||
};
|
||||
};
|
||||
|
||||
@ -2082,6 +2083,90 @@ render_blend_node (GskGLRenderer *self,
|
||||
ops_draw (builder, vertex_data);
|
||||
}
|
||||
|
||||
static inline void
|
||||
render_repeat_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
GskRenderNode *child = gsk_repeat_node_get_child (node);
|
||||
const graphene_rect_t *child_bounds = gsk_repeat_node_peek_child_bounds (node);
|
||||
TextureRegion region;
|
||||
gboolean is_offscreen;
|
||||
RenderOp op;
|
||||
|
||||
if (child_bounds != NULL &&
|
||||
!graphene_rect_equal (child_bounds, &child->bounds))
|
||||
{
|
||||
/* TODO: Implement these repeat nodes. */
|
||||
render_fallback_node (self, node, builder);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Draw the entire child on a texture */
|
||||
add_offscreen_ops (self, builder,
|
||||
&child->bounds,
|
||||
child,
|
||||
®ion, &is_offscreen,
|
||||
RESET_CLIP | RESET_OPACITY);
|
||||
|
||||
ops_set_program (builder, &self->repeat_program);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
op.op = OP_CHANGE_REPEAT;
|
||||
op.repeat.child_bounds[0] = 0; /* Both currently unused */
|
||||
op.repeat.child_bounds[1] = 0;
|
||||
op.repeat.child_bounds[2] = node->bounds.size.width / child_bounds->size.width;
|
||||
op.repeat.child_bounds[3] = node->bounds.size.height / child_bounds->size.height;
|
||||
|
||||
op.repeat.texture_rect[0] = region.x;
|
||||
op.repeat.texture_rect[2] = region.x2;
|
||||
|
||||
if (is_offscreen)
|
||||
{
|
||||
op.repeat.texture_rect[1] = region.y2;
|
||||
op.repeat.texture_rect[3] = region.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
op.repeat.texture_rect[1] = region.y;
|
||||
op.repeat.texture_rect[3] = region.y2;
|
||||
}
|
||||
|
||||
ops_add (builder, &op);
|
||||
|
||||
if (is_offscreen)
|
||||
{
|
||||
const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
|
||||
{ { min_x, min_y }, { region.x, region.y2 }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
|
||||
{ { max_x, max_y }, { region.x2, region.y }, },
|
||||
{ { min_x, max_y }, { region.x, region.y }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y2 }, },
|
||||
};
|
||||
|
||||
ops_draw (builder, offscreen_vertex_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
|
||||
{ { min_x, min_y }, { region.x, region.y }, },
|
||||
{ { min_x, max_y }, { region.x, region.y2 }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y }, },
|
||||
|
||||
{ { max_x, max_y }, { region.x2, region.y2 }, },
|
||||
{ { min_x, max_y }, { region.x, region.y2 }, },
|
||||
{ { max_x, min_y }, { region.x2, region.y }, },
|
||||
};
|
||||
|
||||
ops_draw (builder, onscreen_vertex_data);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_viewport_op (const Program *program,
|
||||
const RenderOp *op)
|
||||
@ -2368,6 +2453,14 @@ apply_blend_op (const Program *program,
|
||||
glUniform1i (program->blend.mode_location, op->blend.mode);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_repeat_op (const Program *program,
|
||||
const RenderOp *op)
|
||||
{
|
||||
glUniform4fv (program->repeat.child_bounds_location, 1, op->repeat.child_bounds);
|
||||
glUniform4fv (program->repeat.texture_rect_location, 1, op->repeat.texture_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_dispose (GObject *gobject)
|
||||
{
|
||||
@ -2389,19 +2482,21 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
static const struct {
|
||||
const char *name;
|
||||
const char *fs;
|
||||
const char *vs;
|
||||
} program_definitions[] = {
|
||||
{ "blit", "blit.fs.glsl" },
|
||||
{ "color", "color.fs.glsl" },
|
||||
{ "coloring", "coloring.fs.glsl" },
|
||||
{ "color matrix", "color_matrix.fs.glsl" },
|
||||
{ "linear gradient", "linear_gradient.fs.glsl" },
|
||||
{ "blur", "blur.fs.glsl" },
|
||||
{ "inset shadow", "inset_shadow.fs.glsl" },
|
||||
{ "outset shadow", "outset_shadow.fs.glsl" },
|
||||
{ "blit", "blit.fs.glsl" },
|
||||
{ "color", "color.fs.glsl" },
|
||||
{ "coloring", "coloring.fs.glsl" },
|
||||
{ "color matrix", "color_matrix.fs.glsl" },
|
||||
{ "linear gradient", "linear_gradient.fs.glsl" },
|
||||
{ "blur", "blur.fs.glsl" },
|
||||
{ "inset shadow", "inset_shadow.fs.glsl" },
|
||||
{ "outset shadow", "outset_shadow.fs.glsl" },
|
||||
{ "unblurred outset shadow", "unblurred_outset_shadow.fs.glsl" },
|
||||
{ "border", "border.fs.glsl" },
|
||||
{ "cross fade", "cross_fade.fs.glsl" },
|
||||
{ "blend", "blend.fs.glsl" },
|
||||
{ "border", "border.fs.glsl" },
|
||||
{ "cross fade", "cross_fade.fs.glsl" },
|
||||
{ "blend", "blend.fs.glsl" },
|
||||
{ "repeat", "repeat.fs.glsl" },
|
||||
};
|
||||
|
||||
builder = gsk_shader_builder_new ();
|
||||
@ -2454,6 +2549,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
prog->index = i;
|
||||
prog->id = gsk_shader_builder_create_program (builder,
|
||||
program_definitions[i].fs,
|
||||
program_definitions[i].vs,
|
||||
&shader_error);
|
||||
|
||||
if (shader_error != NULL)
|
||||
@ -2461,8 +2557,8 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
g_propagate_prefixed_error (error, shader_error,
|
||||
"Unable to create '%s' program (from %s and %s):\n",
|
||||
program_definitions[i].name,
|
||||
"blit.vs.glsl",
|
||||
program_definitions[i].fs);
|
||||
program_definitions[i].fs,
|
||||
program_definitions[i].vs);
|
||||
|
||||
g_object_unref (builder);
|
||||
return FALSE;
|
||||
@ -2536,6 +2632,10 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blend, source2);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blend, mode);
|
||||
|
||||
/* repeat */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (repeat, child_bounds);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (repeat, texture_rect);
|
||||
|
||||
g_object_unref (builder);
|
||||
return TRUE;
|
||||
}
|
||||
@ -2863,8 +2963,11 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
render_blend_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEAT_NODE:
|
||||
render_repeat_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
default:
|
||||
{
|
||||
@ -3151,6 +3254,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
|
||||
apply_unblurred_outset_shadow_op (program, op);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_REPEAT:
|
||||
apply_repeat_op (program, op);
|
||||
break;
|
||||
|
||||
case OP_DRAW:
|
||||
OP_PRINT (" -> draw %ld, size %ld and program %d\n",
|
||||
op->draw.vao_offset, op->draw.vao_size, program->index);
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "gskrendernodeprivate.h"
|
||||
|
||||
#define GL_N_VERTICES 6
|
||||
#define GL_N_PROGRAMS 12
|
||||
#define GL_N_PROGRAMS 13
|
||||
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ enum {
|
||||
OP_PUSH_DEBUG_GROUP = 24,
|
||||
OP_POP_DEBUG_GROUP = 25,
|
||||
OP_CHANGE_BLEND = 26,
|
||||
OP_CHANGE_REPEAT = 27,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@ -139,6 +140,10 @@ typedef struct
|
||||
int source2_location;
|
||||
int mode_location;
|
||||
} blend;
|
||||
struct {
|
||||
int child_bounds_location;
|
||||
int texture_rect_location;
|
||||
} repeat;
|
||||
};
|
||||
|
||||
} Program;
|
||||
@ -149,7 +154,7 @@ typedef struct
|
||||
|
||||
union {
|
||||
float opacity;
|
||||
graphene_matrix_t modelview; /* TODO: Make both matrix members just "matrix" */
|
||||
graphene_matrix_t modelview;
|
||||
graphene_matrix_t projection;
|
||||
const Program *program;
|
||||
int texture_id;
|
||||
@ -221,6 +226,10 @@ typedef struct
|
||||
int source2;
|
||||
int mode;
|
||||
} blend;
|
||||
struct {
|
||||
float child_bounds[4];
|
||||
float texture_rect[4];
|
||||
} repeat;
|
||||
struct {
|
||||
char *filename;
|
||||
int width;
|
||||
|
@ -257,6 +257,7 @@ gsk_shader_builder_set_common_vertex_shader (GskShaderBuilder *self,
|
||||
int
|
||||
gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *fragment_shader,
|
||||
const char *vertex_shader,
|
||||
GError **error)
|
||||
{
|
||||
int vertex_id;
|
||||
@ -268,7 +269,16 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
g_return_val_if_fail (fragment_shader != NULL, -1);
|
||||
g_return_val_if_fail (builder->common_vertex_shader_id != 0, -1);
|
||||
|
||||
vertex_id = builder->common_vertex_shader_id;
|
||||
if (vertex_shader == NULL)
|
||||
vertex_id = builder->common_vertex_shader_id;
|
||||
else
|
||||
vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
|
||||
builder->vertex_preamble,
|
||||
vertex_shader,
|
||||
error);
|
||||
if (vertex_id < 0)
|
||||
return -1;
|
||||
|
||||
fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
|
||||
builder->fragment_preamble,
|
||||
fragment_shader,
|
||||
|
@ -31,6 +31,7 @@ void gsk_shader_builder_set_common_vertex_shader (GskShad
|
||||
|
||||
int gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *fragment_shader,
|
||||
const char *vertex_shader,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -12,6 +12,7 @@ gsk_private_gl_shaders = [
|
||||
'resources/glsl/border.fs.glsl',
|
||||
'resources/glsl/cross_fade.fs.glsl',
|
||||
'resources/glsl/blend.fs.glsl',
|
||||
'resources/glsl/repeat.fs.glsl',
|
||||
'resources/glsl/es2_common.fs.glsl',
|
||||
'resources/glsl/es2_common.vs.glsl',
|
||||
'resources/glsl/gl3_common.fs.glsl',
|
||||
|
34
gsk/resources/glsl/repeat.fs.glsl
Normal file
34
gsk/resources/glsl/repeat.fs.glsl
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
uniform vec4 u_child_bounds;
|
||||
uniform vec4 u_texture_rect;
|
||||
|
||||
|
||||
float wrap(float f, float wrap_for) {
|
||||
return mod(f, wrap_for);
|
||||
}
|
||||
|
||||
/* We get the texture coordinates via vUv,
|
||||
* but that might be on a texture atlas, so we need to do the
|
||||
* wrapping ourselves.
|
||||
*/
|
||||
void main() {
|
||||
|
||||
/* We map the texture coordinate to [1;0], then wrap it and scale the result again */
|
||||
|
||||
float tw = u_texture_rect.z - u_texture_rect.x;
|
||||
float th = u_texture_rect.w - u_texture_rect.y;
|
||||
|
||||
float mapped_x = (vUv.x - u_texture_rect.x) / tw;
|
||||
float mapped_y = (vUv.y - u_texture_rect.y) / th;
|
||||
|
||||
float wrapped_x = wrap(mapped_x * u_child_bounds.z, 1.0);
|
||||
float wrapped_y = wrap(mapped_y * u_child_bounds.w, 1.0);
|
||||
|
||||
vec2 tp;
|
||||
tp.x = u_texture_rect.x + (wrapped_x * tw);
|
||||
tp.y = u_texture_rect.y + (wrapped_y * th);
|
||||
|
||||
vec4 diffuse = Texture(u_source, tp);
|
||||
|
||||
setOutputColor(diffuse * u_alpha);
|
||||
}
|
Loading…
Reference in New Issue
Block a user