diff options
-rw-r--r-- | .gitlab-ci.yml | 2 | ||||
-rw-r--r-- | gsk/gl/gskglcommandqueue.c | 6 | ||||
-rw-r--r-- | gsk/gl/gskglcommandqueueprivate.h | 2 | ||||
-rw-r--r-- | gsk/gl/gskglrenderjob.c | 1842 | ||||
-rw-r--r-- | tests/meson.build | 2 | ||||
-rw-r--r-- | tests/testclipboard2.c | 461 | ||||
-rw-r--r-- | tests/testdnd.c | 597 |
7 files changed, 949 insertions, 1963 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9da8b055aa..9d22e3798d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,7 +24,7 @@ stages: variables: COMMON_MESON_FLAGS: "-Dwerror=true -Dcairo:werror=false -Dgi-docgen:werror=false -Dgraphene:werror=false -Dlibepoxy:werror=false -Dlibsass:werror=false -Dpango:werror=false -Dsassc:werror=false -Dgdk-pixbuf:werror=false -Dglib:werror=false -Dlibcloudproviders:werror=false -Dlibpng:werror=false -Dlibtiff:werror=false -Dsysprof:werror=false -Dwayland-protocols:werror=false -Dharfbuzz:werror=false -Dfreetype2:werror=false -Dfontconfig:werror=false -Dfribidi:werror=false -Dlibffi:werror=false -Dlibjpeg-turbo:werror=false -Dmutest:werror=false -Dpixman:werror=false -Dproxy-libintl:werror=false" BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true" - FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-demos=false -Dbuild-examples=false -Dbuild-tests=false -Dbuild-testsuite=true" + FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true" MESON_TEST_TIMEOUT_MULTIPLIER: 3 FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v46" diff --git a/gsk/gl/gskglcommandqueue.c b/gsk/gl/gskglcommandqueue.c index 6c6a27ca88..204d2555d9 100644 --- a/gsk/gl/gskglcommandqueue.c +++ b/gsk/gl/gskglcommandqueue.c @@ -579,7 +579,7 @@ discard_batch (GskGLCommandQueue *self) self->batches.len--; } -void +gboolean gsk_gl_command_queue_begin_draw (GskGLCommandQueue *self, GskGLUniformProgram *program, guint width, @@ -596,7 +596,7 @@ gsk_gl_command_queue_begin_draw (GskGLCommandQueue *self, * of batches we can have in one frame. */ if (will_ignore_batch (self)) - return; + return FALSE; self->program_info = program; @@ -617,6 +617,8 @@ gsk_gl_command_queue_begin_draw (GskGLCommandQueue *self, self->fbo_max = MAX (self->fbo_max, batch->draw.framebuffer); self->in_draw = TRUE; + + return TRUE; } void diff --git a/gsk/gl/gskglcommandqueueprivate.h b/gsk/gl/gskglcommandqueueprivate.h index df3afb1eea..e9bb2f4003 100644 --- a/gsk/gl/gskglcommandqueueprivate.h +++ b/gsk/gl/gskglcommandqueueprivate.h @@ -331,7 +331,7 @@ void gsk_gl_command_queue_delete_program (GskGLCommandQueue void gsk_gl_command_queue_clear (GskGLCommandQueue *self, guint clear_bits, const graphene_rect_t *viewport); -void gsk_gl_command_queue_begin_draw (GskGLCommandQueue *self, +gboolean gsk_gl_command_queue_begin_draw (GskGLCommandQueue *self, GskGLUniformProgram *program_info, guint width, guint height); diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c index 85ee17eac8..962b3d56f0 100644 --- a/gsk/gl/gskglrenderjob.c +++ b/gsk/gl/gskglrenderjob.c @@ -363,36 +363,6 @@ rect_contains_rect (const graphene_rect_t *r1, (r2->origin.y + r2->size.height) <= (r1->origin.y + r1->size.height); } -static inline gboolean -rounded_inner_rect_contains_rect (const GskRoundedRect *rounded, - const graphene_rect_t *rect) -{ - const graphene_rect_t *rounded_bounds = &rounded->bounds; - graphene_rect_t inner; - float offset_x; - float offset_y; - - /* TODO: This is pretty conservative and we could go further, - * more fine-grained checks to avoid offscreen drawing. - */ - - offset_x = MAX (rounded->corner[GSK_CORNER_TOP_LEFT].width, - rounded->corner[GSK_CORNER_BOTTOM_LEFT].width); - offset_y = MAX (rounded->corner[GSK_CORNER_TOP_LEFT].height, - rounded->corner[GSK_CORNER_TOP_RIGHT].height); - - inner.origin.x = rounded_bounds->origin.x + offset_x; - inner.origin.y = rounded_bounds->origin.y + offset_y; - inner.size.width = rounded_bounds->size.width - offset_x - - MAX (rounded->corner[GSK_CORNER_TOP_RIGHT].width, - rounded->corner[GSK_CORNER_BOTTOM_RIGHT].width); - inner.size.height = rounded_bounds->size.height - offset_y - - MAX (rounded->corner[GSK_CORNER_BOTTOM_LEFT].height, - rounded->corner[GSK_CORNER_BOTTOM_RIGHT].height); - - return rect_contains_rect (&inner, rect); -} - static inline gboolean G_GNUC_PURE rect_intersects (const graphene_rect_t *r1, const graphene_rect_t *r2) @@ -1125,16 +1095,17 @@ gsk_gl_render_job_draw_offscreen_rect (GskGLRenderJob *job, color); } -static inline void +static inline gboolean gsk_gl_render_job_begin_draw (GskGLRenderJob *job, GskGLProgram *program) { job->current_program = program; - gsk_gl_command_queue_begin_draw (job->command_queue, - program->program_info, - job->viewport.size.width, - job->viewport.size.height); + if (!gsk_gl_command_queue_begin_draw (job->command_queue, + program->program_info, + job->viewport.size.width, + job->viewport.size.height)) + return FALSE; gsk_gl_uniform_state_set4fv (program->uniforms, program->program_info, @@ -1166,6 +1137,8 @@ gsk_gl_render_job_begin_draw (GskGLRenderJob *job, UNIFORM_SHARED_ALPHA, job->driver->stamps[UNIFORM_SHARED_ALPHA], job->alpha); + + return TRUE; } #define CHOOSE_PROGRAM(job,name) \ @@ -1297,7 +1270,9 @@ done: gsk_transform_unref (transform); } - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)); + if (!gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit))) + goto out; + gsk_gl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, @@ -1306,6 +1281,7 @@ done: gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds); gsk_gl_render_job_end_draw (job); +out: if (scale_x < 0 || scale_y < 0) gsk_gl_render_job_pop_modelview (job); } @@ -1360,54 +1336,58 @@ blur_offscreen (GskGLRenderJob *job, /* Begin drawing the first horizontal pass, using offscreen as the * source texture for the program. */ - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blur)); - 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_uniform1f (job->current_program, - UNIFORM_BLUR_RADIUS, 0, - blur_radius_x); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_BLUR_SIZE, 0, - texture_to_blur_width, - texture_to_blur_height); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_BLUR_DIR, 0, - 1, 0); - gsk_gl_render_job_draw_coords (job, - 0, 0, texture_to_blur_width, texture_to_blur_height, - 0, 1, 1, 0, - (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blur))) + { + 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_uniform1f (job->current_program, + UNIFORM_BLUR_RADIUS, 0, + blur_radius_x); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_BLUR_SIZE, 0, + texture_to_blur_width, + texture_to_blur_height); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_BLUR_DIR, 0, + 1, 0); + gsk_gl_render_job_draw_coords (job, + 0, 0, texture_to_blur_width, texture_to_blur_height, + 0, 1, 1, 0, + (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); + gsk_gl_render_job_end_draw (job); + } /* Bind second pass framebuffer and clear it */ gsk_gl_command_queue_bind_framebuffer (job->command_queue, pass2->framebuffer_id); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); /* Draw using blur program with first pass as source texture */ - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blur)); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - pass1->texture_id); - gsk_gl_program_set_uniform1f (job->current_program, - UNIFORM_BLUR_RADIUS, 0, - blur_radius_y); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_BLUR_SIZE, 0, - texture_to_blur_width, - texture_to_blur_height); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_BLUR_DIR, 0, - 0, 1); - gsk_gl_render_job_draw_coords (job, - 0, 0, texture_to_blur_width, texture_to_blur_height, - 0, 1, 1, 0, - (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blur))) + { + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + pass1->texture_id); + gsk_gl_program_set_uniform1f (job->current_program, + UNIFORM_BLUR_RADIUS, 0, + blur_radius_y); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_BLUR_SIZE, 0, + texture_to_blur_width, + texture_to_blur_height); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_BLUR_DIR, 0, + 0, 1); + gsk_gl_render_job_draw_coords (job, + 0, 0, texture_to_blur_width, texture_to_blur_height, + 0, 1, 1, 0, + (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); + gsk_gl_render_job_end_draw (job); + } gsk_gl_render_job_pop_modelview (job); gsk_gl_render_job_pop_clip (job); @@ -1506,30 +1486,33 @@ gsk_gl_render_job_visit_color_node (GskGLRenderJob *job, { GskGLRenderOffscreen offscreen = {0}; - gsk_gl_render_job_begin_draw (job, program); - - /* The top left few pixels in our atlases are always - * solid white, so we can use it here, without - * having to choose any particular atlas texture. - */ - offscreen.was_offscreen = FALSE; - offscreen.area.x = 1.f / ATLAS_SIZE; - offscreen.area.y = 1.f / ATLAS_SIZE; - offscreen.area.x2 = 2.f / ATLAS_SIZE; - offscreen.area.y2 = 2.f / ATLAS_SIZE; - - gsk_gl_render_job_draw_offscreen_with_color (job, - &node->bounds, - &offscreen, - color); + if (gsk_gl_render_job_begin_draw (job, program)) + { + /* The top left few pixels in our atlases are always + * solid white, so we can use it here, without + * having to choose any particular atlas texture. + */ + offscreen.was_offscreen = FALSE; + offscreen.area.x = 1.f / ATLAS_SIZE; + offscreen.area.y = 1.f / ATLAS_SIZE; + offscreen.area.x2 = 2.f / ATLAS_SIZE; + offscreen.area.y2 = 2.f / ATLAS_SIZE; + + gsk_gl_render_job_draw_offscreen_with_color (job, + &node->bounds, + &offscreen, + color); - gsk_gl_render_job_end_draw (job); + gsk_gl_render_job_end_draw (job); + } } else { - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, color); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color))) + { + gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, color); + gsk_gl_render_job_end_draw (job); + } } } @@ -1549,22 +1532,24 @@ gsk_gl_render_job_visit_linear_gradient_node (GskGLRenderJob *job, g_assert (n_color_stops < MAX_GRADIENT_STOPS); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, linear_gradient)); - gsk_gl_program_set_uniform1i (job->current_program, - UNIFORM_LINEAR_GRADIENT_NUM_COLOR_STOPS, 0, - n_color_stops); - gsk_gl_program_set_uniform1fv (job->current_program, - UNIFORM_LINEAR_GRADIENT_COLOR_STOPS, 0, - n_color_stops * 5, - (const float *)stops); - gsk_gl_program_set_uniform4f (job->current_program, - UNIFORM_LINEAR_GRADIENT_POINTS, 0, - x1, y1, x2 - x1, y2 - y1); - gsk_gl_program_set_uniform1i (job->current_program, - UNIFORM_LINEAR_GRADIENT_REPEAT, 0, - repeat); - gsk_gl_render_job_draw_rect (job, &node->bounds); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, linear_gradient))) + { + gsk_gl_program_set_uniform1i (job->current_program, + UNIFORM_LINEAR_GRADIENT_NUM_COLOR_STOPS, 0, + n_color_stops); + gsk_gl_program_set_uniform1fv (job->current_program, + UNIFORM_LINEAR_GRADIENT_COLOR_STOPS, 0, + n_color_stops * 5, + (const float *)stops); + gsk_gl_program_set_uniform4f (job->current_program, + UNIFORM_LINEAR_GRADIENT_POINTS, 0, + x1, y1, x2 - x1, y2 - y1); + gsk_gl_program_set_uniform1i (job->current_program, + UNIFORM_LINEAR_GRADIENT_REPEAT, 0, + repeat); + gsk_gl_render_job_draw_rect (job, &node->bounds); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -1581,22 +1566,24 @@ gsk_gl_render_job_visit_conic_gradient_node (GskGLRenderJob *job, g_assert (n_color_stops < MAX_GRADIENT_STOPS); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, conic_gradient)); - gsk_gl_program_set_uniform1i (job->current_program, - UNIFORM_CONIC_GRADIENT_NUM_COLOR_STOPS, 0, - n_color_stops); - gsk_gl_program_set_uniform1fv (job->current_program, - UNIFORM_CONIC_GRADIENT_COLOR_STOPS, 0, - n_color_stops * 5, - (const float *)stops); - gsk_gl_program_set_uniform4f (job->current_program, - UNIFORM_CONIC_GRADIENT_GEOMETRY, 0, - job->offset_x + center->x, - job->offset_y + center->y, - scale, - bias); - gsk_gl_render_job_draw_rect (job, &node->bounds); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, conic_gradient))) + { + gsk_gl_program_set_uniform1i (job->current_program, + UNIFORM_CONIC_GRADIENT_NUM_COLOR_STOPS, 0, + n_color_stops); + gsk_gl_program_set_uniform1fv (job->current_program, + UNIFORM_CONIC_GRADIENT_COLOR_STOPS, 0, + n_color_stops * 5, + (const float *)stops); + gsk_gl_program_set_uniform4f (job->current_program, + UNIFORM_CONIC_GRADIENT_GEOMETRY, 0, + job->offset_x + center->x, + job->offset_y + center->y, + scale, + bias); + gsk_gl_render_job_draw_rect (job, &node->bounds); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -1616,28 +1603,30 @@ gsk_gl_render_job_visit_radial_gradient_node (GskGLRenderJob *job, g_assert (n_color_stops < MAX_GRADIENT_STOPS); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, radial_gradient)); - gsk_gl_program_set_uniform1i (job->current_program, - UNIFORM_RADIAL_GRADIENT_NUM_COLOR_STOPS, 0, - n_color_stops); - gsk_gl_program_set_uniform1fv (job->current_program, - UNIFORM_RADIAL_GRADIENT_COLOR_STOPS, 0, - n_color_stops * 5, - (const float *)stops); - gsk_gl_program_set_uniform1i (job->current_program, - UNIFORM_RADIAL_GRADIENT_REPEAT, 0, - repeat); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_RADIAL_GRADIENT_RANGE, 0, - scale, bias); - gsk_gl_program_set_uniform4f (job->current_program, - UNIFORM_RADIAL_GRADIENT_GEOMETRY, 0, - job->offset_x + center->x, - job->offset_y + center->y, - 1.0f / (hradius * job->scale_x), - 1.0f / (vradius * job->scale_y)); - gsk_gl_render_job_draw_rect (job, &node->bounds); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, radial_gradient))) + { + gsk_gl_program_set_uniform1i (job->current_program, + UNIFORM_RADIAL_GRADIENT_NUM_COLOR_STOPS, 0, + n_color_stops); + gsk_gl_program_set_uniform1fv (job->current_program, + UNIFORM_RADIAL_GRADIENT_COLOR_STOPS, 0, + n_color_stops * 5, + (const float *)stops); + gsk_gl_program_set_uniform1i (job->current_program, + UNIFORM_RADIAL_GRADIENT_REPEAT, 0, + repeat); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_RADIAL_GRADIENT_RANGE, 0, + scale, bias); + gsk_gl_program_set_uniform4f (job->current_program, + UNIFORM_RADIAL_GRADIENT_GEOMETRY, 0, + job->offset_x + center->x, + job->offset_y + center->y, + 1.0f / (hradius * job->scale_x), + 1.0f / (vradius * job->scale_y)); + gsk_gl_render_job_draw_rect (job, &node->bounds); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -1690,14 +1679,16 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job, g_assert (offscreen.texture_id); - 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_render_job_draw_offscreen_rect (job, clip); - gsk_gl_render_job_end_draw (job); + if (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_render_job_draw_offscreen_rect (job, clip); + gsk_gl_render_job_end_draw (job); + } } } @@ -1778,14 +1769,16 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job, g_assert (offscreen.texture_id); - 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_render_job_draw_offscreen (job, &node->bounds, &offscreen); - gsk_gl_render_job_end_draw (job); + if (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_render_job_draw_offscreen (job, &node->bounds, &offscreen); + gsk_gl_render_job_end_draw (job); + } } } @@ -1799,41 +1792,42 @@ gsk_gl_render_job_visit_rect_border_node (GskGLRenderJob *job, const graphene_size_t *size = &node->bounds.size; guint16 color[4]; - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - - if (widths[0] > 0) + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color))) { - rgba_to_half (&colors[0], color); - gsk_gl_render_job_draw_rect_with_color (job, - &GRAPHENE_RECT_INIT (origin->x, origin->y, size->width - widths[1], widths[0]), - color); - } + if (widths[0] > 0) + { + rgba_to_half (&colors[0], color); + gsk_gl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x, origin->y, size->width - widths[1], widths[0]), + color); + } - if (widths[1] > 0) - { - rgba_to_half (&colors[1], color); - gsk_gl_render_job_draw_rect_with_color (job, - &GRAPHENE_RECT_INIT (origin->x + size->width - widths[1], origin->y, widths[1], size->height - widths[2]), - color); - } + if (widths[1] > 0) + { + rgba_to_half (&colors[1], color); + gsk_gl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x + size->width - widths[1], origin->y, widths[1], size->height - widths[2]), + color); + } - if (widths[2] > 0) - { - rgba_to_half (&colors[2], color); - gsk_gl_render_job_draw_rect_with_color (job, - &GRAPHENE_RECT_INIT (origin->x + widths[3], origin->y + size->height - widths[2], size->width - widths[3], widths[2]), - color); - } + if (widths[2] > 0) + { + rgba_to_half (&colors[2], color); + gsk_gl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x + widths[3], origin->y + size->height - widths[2], size->width - widths[3], widths[2]), + color); + } - if (widths[3] > 0) - { - rgba_to_half (&colors[3], color); - gsk_gl_render_job_draw_rect_with_color (job, - &GRAPHENE_RECT_INIT (origin->x, origin->y + widths[0], widths[3], size->height - widths[0]), - color); - } + if (widths[3] > 0) + { + rgba_to_half (&colors[3], color); + gsk_gl_render_job_draw_rect_with_color (job, + &GRAPHENE_RECT_INIT (origin->x, origin->y + widths[0], widths[3], size->height - widths[0]), + color); + } - gsk_gl_render_job_end_draw (job); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -1882,77 +1876,78 @@ gsk_gl_render_job_visit_border_node (GskGLRenderJob *job, gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, border)); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, border))) + { + gsk_gl_program_set_uniform4fv (job->current_program, + UNIFORM_BORDER_WIDTHS, 0, + 1, + widths); + gsk_gl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_BORDER_OUTLINE_RECT, 0, + &outline); - gsk_gl_program_set_uniform4fv (job->current_program, - UNIFORM_BORDER_WIDTHS, 0, - 1, - widths); - gsk_gl_program_set_uniform_rounded_rect (job->current_program, - UNIFORM_BORDER_OUTLINE_RECT, 0, - &outline); + if (widths[0] > 0) + { + GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); - if (widths[0] > 0) - { - GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); + rgba_to_half (&colors[0], color); - rgba_to_half (&colors[0], color); + vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[1] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[1] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[3] = (GskGLDrawVertex) { .position = { max_x - sizes[1].w, min_y + sizes[1].h }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[4] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + } - vertices[3] = (GskGLDrawVertex) { .position = { max_x - sizes[1].w, min_y + sizes[1].h }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[4] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - } + if (widths[1] > 0) + { + GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); - if (widths[1] > 0) - { - GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); + rgba_to_half (&colors[1], color); - rgba_to_half (&colors[1], color); + vertices[0] = (GskGLDrawVertex) { .position = { max_x - sizes[1].w, min_y + sizes[1].h }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[1] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[0] = (GskGLDrawVertex) { .position = { max_x - sizes[1].w, min_y + sizes[1].h }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[1] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[4] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + } - vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[4] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - } + if (widths[2] > 0) + { + GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); - if (widths[2] > 0) - { - GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); + rgba_to_half (&colors[2], color); - rgba_to_half (&colors[2], color); + vertices[0] = (GskGLDrawVertex) { .position = { min_x + sizes[3].w, max_y - sizes[3].h }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[2] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[0] = (GskGLDrawVertex) { .position = { min_x + sizes[3].w, max_y - sizes[3].h }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[2] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[4] = (GskGLDrawVertex) { .position = { min_x , max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[5] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + } - vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[4] = (GskGLDrawVertex) { .position = { min_x , max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[5] = (GskGLDrawVertex) { .position = { max_x - sizes[2].w, max_y - sizes[2].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - } + if (widths[3] > 0) + { + GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); - if (widths[3] > 0) - { - GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue); + rgba_to_half (&colors[3], color); - rgba_to_half (&colors[3], color); + vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[2] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .uv = { 0, 1 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[2] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[3] = (GskGLDrawVertex) { .position = { min_x + sizes[3].w, max_y - sizes[3].h }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; + vertices[5] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + } - vertices[3] = (GskGLDrawVertex) { .position = { min_x + sizes[3].w, max_y - sizes[3].h }, .uv = { 1, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .uv = { 0, 0 }, .color = { color[0], color[1], color[2], color[3] } }; - vertices[5] = (GskGLDrawVertex) { .position = { min_x + sizes[0].w, min_y + sizes[0].h }, .uv = { 1, 1 }, .color = { color[0], color[1], color[2], color[3] } }; + gsk_gl_render_job_end_draw (job); } - - gsk_gl_render_job_end_draw (job); } /* A special case for a pattern that occurs frequently with CSS @@ -1986,26 +1981,27 @@ gsk_gl_render_job_visit_css_background (GskGLRenderJob *job, gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, filled_border)); - - gsk_gl_program_set_uniform4fv (job->current_program, - UNIFORM_FILLED_BORDER_WIDTHS, 0, - 1, - widths); - gsk_gl_program_set_uniform_rounded_rect (job->current_program, - UNIFORM_FILLED_BORDER_OUTLINE_RECT, 0, - &outline); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, filled_border))) + { + gsk_gl_program_set_uniform4fv (job->current_program, + UNIFORM_FILLED_BORDER_WIDTHS, 0, + 1, + widths); + gsk_gl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_FILLED_BORDER_OUTLINE_RECT, 0, + &outline); - vertices = gsk_gl_command_queue_add_vertices (job->command_queue); + vertices = gsk_gl_command_queue_add_vertices (job->command_queue); - vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; - vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; - vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; - vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; - vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; - vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; + vertices[0] = (GskGLDrawVertex) { .position = { min_x, min_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; + vertices[1] = (GskGLDrawVertex) { .position = { min_x, max_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; + vertices[2] = (GskGLDrawVertex) { .position = { max_x, min_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; + vertices[3] = (GskGLDrawVertex) { .position = { max_x, max_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; + vertices[4] = (GskGLDrawVertex) { .position = { min_x, max_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; + vertices[5] = (GskGLDrawVertex) { .position = { max_x, min_y }, .color = { color[0], color[1], color[2], color[3] }, .color2 = { color2[0], color2[1], color2[2], color2[3] } }; - gsk_gl_render_job_end_draw (job); + gsk_gl_render_job_end_draw (job); + } } /* Returns TRUE if applying @transform to @bounds @@ -2136,16 +2132,18 @@ gsk_gl_render_job_visit_transform_node (GskGLRenderJob *job, 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_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); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit))) + { + 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); + } if (transform) gsk_gl_render_job_pop_modelview (job); @@ -2177,20 +2175,22 @@ gsk_gl_render_job_visit_unblurred_inset_shadow_node (GskGLRenderJob *job, gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); - gsk_gl_program_set_uniform_rounded_rect (job->current_program, - UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, - &transformed_outline); - gsk_gl_program_set_uniform1f (job->current_program, - UNIFORM_INSET_SHADOW_SPREAD, 0, - gsk_inset_shadow_node_get_spread (node)); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_INSET_SHADOW_OFFSET, 0, - gsk_inset_shadow_node_get_dx (node), - gsk_inset_shadow_node_get_dy (node)); - rgba_to_half (gsk_inset_shadow_node_get_color (node), color); - gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, color); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow))) + { + gsk_gl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, + &transformed_outline); + gsk_gl_program_set_uniform1f (job->current_program, + UNIFORM_INSET_SHADOW_SPREAD, 0, + gsk_inset_shadow_node_get_spread (node)); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_INSET_SHADOW_OFFSET, 0, + gsk_inset_shadow_node_get_dx (node), + gsk_inset_shadow_node_get_dy (node)); + rgba_to_half (gsk_inset_shadow_node_get_color (node), color); + gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, color); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -2278,22 +2278,24 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job, gsk_gl_render_job_translate_rounded_rect (job, &outline_to_blur, &transformed_outline); /* Actual inset shadow outline drawing */ - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)); - gsk_gl_program_set_uniform_rounded_rect (job->current_program, - UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, - &transformed_outline); - gsk_gl_program_set_uniform1f (job->current_program, - UNIFORM_INSET_SHADOW_SPREAD, 0, - spread * MAX (scale_x, scale_y)); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_INSET_SHADOW_OFFSET, 0, - offset_x * scale_x, - offset_y * scale_y); - rgba_to_half (gsk_inset_shadow_node_get_color (node), color); - gsk_gl_render_job_draw_with_color (job, - 0, 0, texture_width, texture_height, - color); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow))) + { + gsk_gl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0, + &transformed_outline); + gsk_gl_program_set_uniform1f (job->current_program, + UNIFORM_INSET_SHADOW_SPREAD, 0, + spread * MAX (scale_x, scale_y)); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_INSET_SHADOW_OFFSET, 0, + offset_x * scale_x, + offset_y * scale_y); + rgba_to_half (gsk_inset_shadow_node_get_color (node), color); + gsk_gl_render_job_draw_with_color (job, + 0, 0, texture_width, texture_height, + color); + gsk_gl_render_job_end_draw (job); + } gsk_gl_render_job_pop_modelview (job); gsk_gl_render_job_pop_clip (job); @@ -2341,14 +2343,16 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job, offscreen.area.x2 = tx2; offscreen.area.y2 = ty2; - 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, - blurred_texture_id); - gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen); - gsk_gl_render_job_end_draw (job); + if (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, + blurred_texture_id); + gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen); + gsk_gl_render_job_end_draw (job); + } if (needs_clip) gsk_gl_render_job_pop_clip (job); @@ -2383,60 +2387,62 @@ gsk_gl_render_job_visit_unblurred_outset_shadow_node (GskGLRenderJob *job, gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow)); - gsk_gl_program_set_uniform_rounded_rect (job->current_program, - UNIFORM_UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, 0, - &transformed_outline); - gsk_gl_program_set_uniform1f (job->current_program, - UNIFORM_UNBLURRED_OUTSET_SHADOW_SPREAD, 0, - spread); - gsk_gl_program_set_uniform2f (job->current_program, - UNIFORM_UNBLURRED_OUTSET_SHADOW_OFFSET, 0, - dx, dy); - - /* Corners... */ - if (corner_sizes[0][0] > 0 && corner_sizes[0][1] > 0) /* Top left */ - gsk_gl_render_job_draw_with_color (job, - x, y, corner_sizes[0][0], corner_sizes[0][1], - color); - if (corner_sizes[1][0] > 0 && corner_sizes[1][1] > 0) /* Top right */ - gsk_gl_render_job_draw_with_color (job, - x + w - corner_sizes[1][0], y, - corner_sizes[1][0], corner_sizes[1][1], - color); - if (corner_sizes[2][0] > 0 && corner_sizes[2][1] > 0) /* Bottom right */ - gsk_gl_render_job_draw_with_color (job, - x + w - corner_sizes[2][0], y + h - corner_sizes[2][1], - corner_sizes[2][0], corner_sizes[2][1], - color); - if (corner_sizes[3][0] > 0 && corner_sizes[3][1] > 0) /* Bottom left */ - gsk_gl_render_job_draw_with_color (job, - x, y + h - corner_sizes[3][1], - corner_sizes[3][0], corner_sizes[3][1], - color); - /* Edges... */; - if (edge_sizes[0] > 0) /* Top */ - gsk_gl_render_job_draw_with_color (job, - x + corner_sizes[0][0], y, - w - corner_sizes[0][0] - corner_sizes[1][0], edge_sizes[0], - color); - if (edge_sizes[1] > 0) /* Right */ - gsk_gl_render_job_draw_with_color (job, - x + w - edge_sizes[1], y + corner_sizes[1][1], - edge_sizes[1], h - corner_sizes[1][1] - corner_sizes[2][1], - color); - if (edge_sizes[2] > 0) /* Bottom */ - gsk_gl_render_job_draw_with_color (job, - x + corner_sizes[3][0], y + h - edge_sizes[2], - w - corner_sizes[3][0] - corner_sizes[2][0], edge_sizes[2], - color); - if (edge_sizes[3] > 0) /* Left */ - gsk_gl_render_job_draw_with_color (job, - x, y + corner_sizes[0][1], - edge_sizes[3], h - corner_sizes[0][1] - corner_sizes[3][1], - color); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow))) + { + gsk_gl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, 0, + &transformed_outline); + gsk_gl_program_set_uniform1f (job->current_program, + UNIFORM_UNBLURRED_OUTSET_SHADOW_SPREAD, 0, + spread); + gsk_gl_program_set_uniform2f (job->current_program, + UNIFORM_UNBLURRED_OUTSET_SHADOW_OFFSET, 0, + dx, dy); + + /* Corners... */ + if (corner_sizes[0][0] > 0 && corner_sizes[0][1] > 0) /* Top left */ + gsk_gl_render_job_draw_with_color (job, + x, y, corner_sizes[0][0], corner_sizes[0][1], + color); + if (corner_sizes[1][0] > 0 && corner_sizes[1][1] > 0) /* Top right */ + gsk_gl_render_job_draw_with_color (job, + x + w - corner_sizes[1][0], y, + corner_sizes[1][0], corner_sizes[1][1], + color); + if (corner_sizes[2][0] > 0 && corner_sizes[2][1] > 0) /* Bottom right */ + gsk_gl_render_job_draw_with_color (job, + x + w - corner_sizes[2][0], y + h - corner_sizes[2][1], + corner_sizes[2][0], corner_sizes[2][1], + color); + if (corner_sizes[3][0] > 0 && corner_sizes[3][1] > 0) /* Bottom left */ + gsk_gl_render_job_draw_with_color (job, + x, y + h - corner_sizes[3][1], + corner_sizes[3][0], corner_sizes[3][1], + color); + /* Edges... */; + if (edge_sizes[0] > 0) /* Top */ + gsk_gl_render_job_draw_with_color (job, + x + corner_sizes[0][0], y, + w - corner_sizes[0][0] - corner_sizes[1][0], edge_sizes[0], + color); + if (edge_sizes[1] > 0) /* Right */ + gsk_gl_render_job_draw_with_color (job, + x + w - edge_sizes[1], y + corner_sizes[1][1], + edge_sizes[1], h - corner_sizes[1][1] - corner_sizes[2][1], + color); + if (edge_sizes[2] > 0) /* Bottom */ + gsk_gl_render_job_draw_with_color (job, + x + corner_sizes[3][0], y + h - edge_sizes[2], + w - corner_sizes[3][0] - corner_sizes[2][0], edge_sizes[2], + color); + if (edge_sizes[3] > 0) /* Left */ + gsk_gl_render_job_draw_with_color (job, + x, y + corner_sizes[0][1], + edge_sizes[3], h - corner_sizes[0][1] - corner_sizes[3][1], + color); - gsk_gl_render_job_end_draw (job); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -2556,10 +2562,12 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job, gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); /* Draw the outline using color program */ - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_gl_render_job_draw_with_color (job, 0, 0, texture_width, texture_height, - (guint16[]){ FP16_ONE, FP16_ONE, FP16_ONE, FP16_ONE }); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color))) + { + gsk_gl_render_job_draw_with_color (job, 0, 0, texture_width, texture_height, + (guint16[]){ FP16_ONE, FP16_ONE, FP16_ONE, FP16_ONE }); + gsk_gl_render_job_end_draw (job); + } /* Reset state from offscreen */ gsk_gl_render_job_pop_clip (job); @@ -2600,7 +2608,33 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job, offscreen.texture_id = blurred_texture_id; init_full_texture_region (&offscreen); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow)); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow))) + { + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + blurred_texture_id); + gsk_gl_program_set_uniform_rounded_rect (job->current_program, + UNIFORM_OUTSET_SHADOW_OUTLINE_RECT, 0, + &transformed_outline); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, + min_y, + texture_width / scale_x, + texture_height / scale_y), + &offscreen, + color); + gsk_gl_render_job_end_draw (job); + } + + return; + } + + /* slicing */ + + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow))) + { gsk_gl_program_set_uniform_texture (job->current_program, UNIFORM_SHARED_SOURCE, 0, GL_TEXTURE_2D, @@ -2609,184 +2643,162 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job, gsk_gl_program_set_uniform_rounded_rect (job->current_program, UNIFORM_OUTSET_SHADOW_OUTLINE_RECT, 0, &transformed_outline); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (min_x, - min_y, - texture_width / scale_x, - texture_height / scale_y), - &offscreen, - color); - gsk_gl_render_job_end_draw (job); - - return; - } - - /* slicing */ - - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, outset_shadow)); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - blurred_texture_id); - gsk_gl_program_set_uniform_rounded_rect (job->current_program, - UNIFORM_OUTSET_SHADOW_OUTLINE_RECT, 0, - &transformed_outline); - - { - float min_x = floorf (outline->bounds.origin.x - spread - half_blur_extra + dx); - float min_y = floorf (outline->bounds.origin.y - spread - half_blur_extra + dy); - float max_x = ceilf (outline->bounds.origin.x + outline->bounds.size.width + - half_blur_extra + dx + spread); - float max_y = ceilf (outline->bounds.origin.y + outline->bounds.size.height + - half_blur_extra + dy + spread); - const GskGLTextureNineSlice *slices; - float left_width, center_width, right_width; - float top_height, center_height, bottom_height; - GskGLTexture *texture; - - texture = gsk_gl_driver_get_texture_by_id (job->driver, blurred_texture_id); - slices = gsk_gl_texture_get_nine_slice (texture, &scaled_outline, extra_blur_pixels_x, extra_blur_pixels_y); - - offscreen.was_offscreen = TRUE; - - /* Our texture coordinates MUST be scaled, while the actual vertex coords - * MUST NOT be scaled. - */ - - left_width = slices[NINE_SLICE_TOP_LEFT].rect.width / scale_x; - right_width = slices[NINE_SLICE_TOP_RIGHT].rect.width / scale_x; - center_width = (max_x - min_x) - (left_width + right_width); - - top_height = slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y; - bottom_height = slices[NINE_SLICE_BOTTOM_LEFT].rect.height / scale_y; - center_height = (max_y - min_y) - (top_height + bottom_height); - /* Top left */ - if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_LEFT])) { - memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_LEFT].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (min_x, - min_y, - left_width, - top_height), - &offscreen, - color); - } - - /* Top center */ - if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_CENTER])) - { - memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_CENTER].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (min_x + left_width, - min_y, - center_width, - top_height), - &offscreen, - color); - } + float min_x = floorf (outline->bounds.origin.x - spread - half_blur_extra + dx); + float min_y = floorf (outline->bounds.origin.y - spread - half_blur_extra + dy); + float max_x = ceilf (outline->bounds.origin.x + outline->bounds.size.width + + half_blur_extra + dx + spread); + float max_y = ceilf (outline->bounds.origin.y + outline->bounds.size.height + + half_blur_extra + dy + spread); + const GskGLTextureNineSlice *slices; + float left_width, center_width, right_width; + float top_height, center_height, bottom_height; + GskGLTexture *texture; + + texture = gsk_gl_driver_get_texture_by_id (job->driver, blurred_texture_id); + slices = gsk_gl_texture_get_nine_slice (texture, &scaled_outline, extra_blur_pixels_x, extra_blur_pixels_y); + + offscreen.was_offscreen = TRUE; + + /* Our texture coordinates MUST be scaled, while the actual vertex coords + * MUST NOT be scaled. + */ + + left_width = slices[NINE_SLICE_TOP_LEFT].rect.width / scale_x; + right_width = slices[NINE_SLICE_TOP_RIGHT].rect.width / scale_x; + center_width = (max_x - min_x) - (left_width + right_width); + + top_height = slices[NINE_SLICE_TOP_LEFT].rect.height / scale_y; + bottom_height = slices[NINE_SLICE_BOTTOM_LEFT].rect.height / scale_y; + center_height = (max_y - min_y) - (top_height + bottom_height); + + /* Top left */ + if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_LEFT])) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_LEFT].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, + min_y, + left_width, + top_height), + &offscreen, + color); + } - /* Top right */ - if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_RIGHT])) - { - memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_RIGHT].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (max_x - right_width, - min_y, - right_width, - top_height), - &offscreen, - color); - } + /* Top center */ + if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_CENTER])) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_CENTER].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x + left_width, + min_y, + center_width, + top_height), + &offscreen, + color); + } - /* Bottom right */ - if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_RIGHT])) - { - memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_RIGHT].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (max_x - right_width, - max_y - bottom_height, - right_width, - bottom_height), - &offscreen, - color); - } + /* Top right */ + if (nine_slice_is_visible (&slices[NINE_SLICE_TOP_RIGHT])) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_TOP_RIGHT].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (max_x - right_width, + min_y, + right_width, + top_height), + &offscreen, + color); + } - /* Bottom left */ - if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_LEFT])) - { - memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_LEFT].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (min_x, - max_y - bottom_height, - left_width, - bottom_height), - &offscreen, - color); - } + /* Bottom right */ + if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_RIGHT])) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_RIGHT].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (max_x - right_width, + max_y - bottom_height, + right_width, + bottom_height), + &offscreen, + color); + } - /* Left side */ - if (nine_slice_is_visible (&slices[NINE_SLICE_LEFT_CENTER])) - { - memcpy (&offscreen.area, &slices[NINE_SLICE_LEFT_CENTER].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (min_x, - min_y + top_height, - left_width, - center_height), - &offscreen, - color); - } + /* Bottom left */ + if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_LEFT])) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_LEFT].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, + max_y - bottom_height, + left_width, + bottom_height), + &offscreen, + color); + } - /* Right side */ - if (nine_slice_is_visible (&slices[NINE_SLICE_RIGHT_CENTER])) - { - memcpy (&offscreen.area, &slices[NINE_SLICE_RIGHT_CENTER].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (max_x - right_width, - min_y + top_height, - right_width, - center_height), - &offscreen, - color); - } + /* Left side */ + if (nine_slice_is_visible (&slices[NINE_SLICE_LEFT_CENTER])) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_LEFT_CENTER].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x, + min_y + top_height, + left_width, + center_height), + &offscreen, + color); + } - /* Bottom side */ - if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_CENTER])) - { - memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_CENTER].area, sizeof offscreen.area); - gsk_gl_render_job_draw_offscreen_with_color (job, - &GRAPHENE_RECT_INIT (min_x + left_width, - max_y - bottom_height, - center_width, - bottom_height), - &offscreen, - color); - } + /* Right side */ + if (nine_slice_is_visible (&slices[NINE_SLICE_RIGHT_CENTER])) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_RIGHT_CENTER].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (max_x - right_width, + min_y + top_height, + right_width, + center_height), + &offscreen, + color); + } - /* Middle */ - if (nine_slice_is_visible (&slices[NINE_SLICE_CENTER])) - { - if (!gsk_rounded_rect_contains_rect (outline, &GRAPHENE_RECT_INIT (min_x + left_width, - min_y + top_height, - center_width, - center_height))) + /* Bottom side */ + if (nine_slice_is_visible (&slices[NINE_SLICE_BOTTOM_CENTER])) { - memcpy (&offscreen.area, &slices[NINE_SLICE_CENTER].area, sizeof offscreen.area); + memcpy (&offscreen.area, &slices[NINE_SLICE_BOTTOM_CENTER].area, sizeof offscreen.area); gsk_gl_render_job_draw_offscreen_with_color (job, &GRAPHENE_RECT_INIT (min_x + left_width, - min_y + top_height, + max_y - bottom_height, center_width, - center_height), + bottom_height), &offscreen, color); } + + /* Middle */ + if (nine_slice_is_visible (&slices[NINE_SLICE_CENTER])) + { + if (!gsk_rounded_rect_contains_rect (outline, &GRAPHENE_RECT_INIT (min_x + left_width, + min_y + top_height, + center_width, + center_height))) + { + memcpy (&offscreen.area, &slices[NINE_SLICE_CENTER].area, sizeof offscreen.area); + gsk_gl_render_job_draw_offscreen_with_color (job, + &GRAPHENE_RECT_INIT (min_x + left_width, + min_y + top_height, + center_width, + center_height), + &offscreen, + color); + } + } } - } - gsk_gl_render_job_end_draw (job); + gsk_gl_render_job_end_draw (job); + } } static inline gboolean G_GNUC_PURE @@ -2853,22 +2865,24 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job, g_assert (offscreen_end.texture_id); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, cross_fade)); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - offscreen_start.texture_id); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_CROSS_FADE_SOURCE2, 0, - GL_TEXTURE_2D, - GL_TEXTURE1, - offscreen_end.texture_id); - gsk_gl_program_set_uniform1f (job->current_program, - UNIFORM_CROSS_FADE_PROGRESS, 0, - progress); - gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen_end); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, cross_fade))) + { + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + offscreen_start.texture_id); + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_CROSS_FADE_SOURCE2, 0, + GL_TEXTURE_2D, + GL_TEXTURE1, + offscreen_end.texture_id); + gsk_gl_program_set_uniform1f (job->current_program, + UNIFORM_CROSS_FADE_PROGRESS, 0, + progress); + gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen_end); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -2902,14 +2916,16 @@ gsk_gl_render_job_visit_opacity_node (GskGLRenderJob *job, g_assert (offscreen.texture_id); - 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_render_job_draw_offscreen (job, &node->bounds, &offscreen); - gsk_gl_render_job_end_draw (job); + if (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_render_job_draw_offscreen (job, &node->bounds, &offscreen); + gsk_gl_render_job_end_draw (job); + } } gsk_gl_render_job_set_alpha (job, prev_alpha); @@ -2982,101 +2998,102 @@ gsk_gl_render_job_visit_text_node (GskGLRenderJob *job, yshift = compute_phase_and_pos (y, &ypos); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)); - - batch = gsk_gl_command_queue_get_batch (job->command_queue); - vertices = gsk_gl_command_queue_add_n_vertices (job->command_queue, num_glyphs); - - /* We use one quad per character */ - for (i = 0, gi = glyphs; i < num_glyphs; i++, gi++) + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring))) { - const GskGLGlyphValue *glyph; - float glyph_x, glyph_y, glyph_x2, glyph_y2; - float tx, ty, tx2, ty2; - float cx; - float cy; - guint texture_id; - - lookup.glyph = gi->glyph; + batch = gsk_gl_command_queue_get_batch (job->command_queue); + vertices = gsk_gl_command_queue_add_n_vertices (job->command_queue, num_glyphs); - /* If the glyph has color, we don't need to recolor anything. - * We tell the shader by setting the color to vec4(-1). - */ - if (!force_color && gi->attr.is_color) - c = nc; - else - c = cc; - - cx = (float)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - lookup.xshift = compute_phase_and_pos (x + cx, &cx); - - if G_UNLIKELY (gi->geometry.y_offset != 0) + /* We use one quad per character */ + for (i = 0, gi = glyphs; i < num_glyphs; i++, gi++) { - cy = (float)(gi->geometry.y_offset) / PANGO_SCALE; - lookup.yshift = compute_phase_and_pos (y + cy, &cy); - } - else - { - lookup.yshift = yshift; - cy = ypos; - } + const GskGLGlyphValue *glyph; + float glyph_x, glyph_y, glyph_x2, glyph_y2; + float tx, ty, tx2, ty2; + float cx; + float cy; + guint texture_id; + + lookup.glyph = gi->glyph; + + /* If the glyph has color, we don't need to recolor anything. + * We tell the shader by setting the color to vec4(-1). + */ + if (!force_color && gi->attr.is_color) + c = nc; + else + c = cc; + + cx = (float)(x_position + gi->geometry.x_offset) / PANGO_SCALE; + lookup.xshift = compute_phase_and_pos (x + cx, &cx); + + if G_UNLIKELY (gi->geometry.y_offset != 0) + { + cy = (float)(gi->geometry.y_offset) / PANGO_SCALE; + lookup.yshift = compute_phase_and_pos (y + cy, &cy); + } + else + { + lookup.yshift = yshift; + cy = ypos; + } - x_position += gi->geometry.width; + x_position += gi->geometry.width; - texture_id = gsk_gl_glyph_library_lookup_or_add (library, &lookup, &glyph); - if G_UNLIKELY (texture_id == 0) - continue; + texture_id = gsk_gl_glyph_library_lookup_or_add (library, &lookup, &glyph); + if G_UNLIKELY (texture_id == 0) + continue; - if G_UNLIKELY (last_texture != texture_id || batch->draw.vbo_count + GSK_GL_N_VERTICES > 0xffff) - { - if G_LIKELY (last_texture != 0) + if G_UNLIKELY (last_texture != texture_id || batch->draw.vbo_count + GSK_GL_N_VERTICES > 0xffff) { - guint vbo_offset = batch->draw.vbo_offset + batch->draw.vbo_count; + if G_LIKELY (last_texture != 0) + { + guint vbo_offset = batch->draw.vbo_offset + batch->draw.vbo_count; + + /* Since we have batched added our VBO vertices to avoid repeated + * calls to the buffer, we need to manually tweak the vbo offset + * of the new batch as otherwise it will point at the end of our + * vbo array. + */ + gsk_gl_render_job_split_draw (job); + batch = gsk_gl_command_queue_get_batch (job->command_queue); + batch->draw.vbo_offset = vbo_offset; + } - /* Since we have batched added our VBO vertices to avoid repeated - * calls to the buffer, we need to manually tweak the vbo offset - * of the new batch as otherwise it will point at the end of our - * vbo array. - */ - gsk_gl_render_job_split_draw (job); - batch = gsk_gl_command_queue_get_batch (job->command_queue); - batch->draw.vbo_offset = vbo_offset; + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + texture_id); + last_texture = texture_id; } - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - texture_id); - last_texture = texture_id; - } + tx = glyph->entry.area.x; + ty = glyph->entry.area.y; + tx2 = glyph->entry.area.x2; + ty2 = glyph->entry.area.y2; - tx = glyph->entry.area.x; - ty = glyph->entry.area.y; - tx2 = glyph->entry.area.x2; - ty2 = glyph->entry.area.y2; + glyph_x = cx + glyph->ink_rect.x; + glyph_y = cy + glyph->ink_rect.y; + glyph_x2 = glyph_x + glyph->ink_rect.width; + glyph_y2 = glyph_y + glyph->ink_rect.height; - glyph_x = cx + glyph->ink_rect.x; - glyph_y = cy + glyph->ink_rect.y; - glyph_x2 = glyph_x + glyph->ink_rect.width; - glyph_y2 = glyph_y + glyph->ink_rect.height; + *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x, glyph_y }, .uv = { tx, ty }, .color = { c[0], c[1], c[2], c[3] } }; + *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x, glyph_y2 }, .uv = { tx, ty2 }, .color = { c[0], c[1], c[2], c[3] } }; + *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x2, glyph_y }, .uv = { tx2, ty }, .color = { c[0], c[1], c[2], c[3] } }; - *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x, glyph_y }, .uv = { tx, ty }, .color = { c[0], c[1], c[2], c[3] } }; - *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x, glyph_y2 }, .uv = { tx, ty2 }, .color = { c[0], c[1], c[2], c[3] } }; - *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x2, glyph_y }, .uv = { tx2, ty }, .color = { c[0], c[1], c[2], c[3] } }; + *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x2, glyph_y2 }, .uv = { tx2, ty2 }, .color = { c[0], c[1], c[2], c[3] } }; + *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x, glyph_y2 }, .uv = { tx, ty2 }, .color = { c[0], c[1], c[2], c[3] } }; + *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x2, glyph_y }, .uv = { tx2, ty }, .color = { c[0], c[1], c[2], c[3] } }; - *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x2, glyph_y2 }, .uv = { tx2, ty2 }, .color = { c[0], c[1], c[2], c[3] } }; - *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x, glyph_y2 }, .uv = { tx, ty2 }, .color = { c[0], c[1], c[2], c[3] } }; - *(vertices++) = (GskGLDrawVertex) { .position = { glyph_x2, glyph_y }, .uv = { tx2, ty }, .color = { c[0], c[1], c[2], c[3] } }; - - batch->draw.vbo_count += GSK_GL_N_VERTICES; - used++; - } + batch->draw.vbo_count += GSK_GL_N_VERTICES; + used++; + } - if (used != num_glyphs) - gsk_gl_command_queue_retract_n_vertices (job->command_queue, num_glyphs - used); + if (used != num_glyphs) + gsk_gl_command_queue_retract_n_vertices (job->command_queue, num_glyphs - used); - gsk_gl_render_job_end_draw (job); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -3160,15 +3177,17 @@ gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job, } gsk_gl_render_job_offset (job, dx, dy); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring)); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - offscreen.texture_id); - rgba_to_half (&shadow->color, color); - gsk_gl_render_job_draw_offscreen_with_color (job, &bounds, &offscreen, color); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, coloring))) + { + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + offscreen.texture_id); + rgba_to_half (&shadow->color, color); + gsk_gl_render_job_draw_offscreen_with_color (job, &bounds, &offscreen, color); + gsk_gl_render_job_end_draw (job); + } gsk_gl_render_job_offset (job, -dx, -dy); } @@ -3214,17 +3233,19 @@ gsk_gl_render_job_visit_blur_node (GskGLRenderJob *job, if (cache_texture) gsk_gl_driver_cache_texture (job->driver, &key, offscreen.texture_id); - 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_render_job_draw_coords (job, - min_x, min_y, max_x, max_y, - 0, 1, 1, 0, - (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO } ); - gsk_gl_render_job_end_draw (job); + if (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_render_job_draw_coords (job, + min_x, min_y, max_x, max_y, + 0, 1, 1, 0, + (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO } ); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -3262,14 +3283,16 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job, { gsk_gl_render_job_pop_modelview (job); - 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, - bottom_offscreen.texture_id); - gsk_gl_render_job_draw_offscreen (job, &node->bounds, &bottom_offscreen); - gsk_gl_render_job_end_draw (job); + if (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, + bottom_offscreen.texture_id); + gsk_gl_render_job_draw_offscreen (job, &node->bounds, &bottom_offscreen); + gsk_gl_render_job_end_draw (job); + } return; } @@ -3277,22 +3300,24 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job, gsk_gl_render_job_pop_modelview (job); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blend)); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - bottom_offscreen.texture_id); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_BLEND_SOURCE2, 0, - GL_TEXTURE_2D, - GL_TEXTURE1, - top_offscreen.texture_id); - gsk_gl_program_set_uniform1i (job->current_program, - UNIFORM_BLEND_MODE, 0, - gsk_blend_node_get_blend_mode (node)); - gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blend))) + { + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + bottom_offscreen.texture_id); + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_BLEND_SOURCE2, 0, + GL_TEXTURE_2D, + GL_TEXTURE1, + top_offscreen.texture_id); + gsk_gl_program_set_uniform1i (job->current_program, + UNIFORM_BLEND_MODE, 0, + gsk_blend_node_get_blend_mode (node)); + gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -3337,22 +3362,24 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job, gsk_gl_render_job_pop_modelview (job); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, mask)); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - source_offscreen.texture_id); - gsk_gl_program_set_uniform_texture (job->current_program, - UNIFORM_MASK_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE1, - mask_offscreen.texture_id); - gsk_gl_program_set_uniform1i (job->current_program, - UNIFORM_MASK_MODE, 0, - gsk_mask_node_get_mask_mode (node)); - gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, mask))) + { + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + source_offscreen.texture_id); + gsk_gl_program_set_uniform_texture (job->current_program, + UNIFORM_MASK_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE1, + mask_offscreen.texture_id); + gsk_gl_program_set_uniform1i (job->current_program, + UNIFORM_MASK_MODE, 0, + gsk_mask_node_get_mask_mode (node)); + gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -3376,21 +3403,23 @@ gsk_gl_render_job_visit_color_matrix_node (GskGLRenderJob *job, graphene_vec4_to_float (gsk_color_matrix_node_get_color_offset (node), offset); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color_matrix)); - 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_matrix (job->current_program, - UNIFORM_COLOR_MATRIX_COLOR_MATRIX, 0, - gsk_color_matrix_node_get_color_matrix (node)); - gsk_gl_program_set_uniform4fv (job->current_program, - UNIFORM_COLOR_MATRIX_COLOR_OFFSET, 0, - 1, - offset); - gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color_matrix))) + { + 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_matrix (job->current_program, + UNIFORM_COLOR_MATRIX_COLOR_MATRIX, 0, + gsk_color_matrix_node_get_color_matrix (node)); + gsk_gl_program_set_uniform4fv (job->current_program, + UNIFORM_COLOR_MATRIX_COLOR_OFFSET, 0, + 1, + offset); + gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -3399,9 +3428,11 @@ gsk_gl_render_job_visit_gl_shader_node_fallback (GskGLRenderJob *job, { guint16 pink[4] = { 15360, 13975, 14758, 15360 }; /* 255 105 180 */ - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color)); - gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, pink); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color))) + { + gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, pink); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -3453,68 +3484,70 @@ gsk_gl_render_job_visit_gl_shader_node (GskGLRenderJob *job, base = g_bytes_get_data (args, NULL); uniforms = gsk_gl_shader_get_uniforms (shader, &n_uniforms); - gsk_gl_render_job_begin_draw (job, program); - for (guint i = 0; i < n_children; i++) - gsk_gl_program_set_uniform_texture (program, - UNIFORM_CUSTOM_TEXTURE1 + i, 0, - GL_TEXTURE_2D, - GL_TEXTURE0 + i, - offscreens[i].texture_id); - gsk_gl_program_set_uniform2f (program, - UNIFORM_CUSTOM_SIZE, 0, - node->bounds.size.width, - node->bounds.size.height); - for (guint i = 0; i < n_uniforms; i++) + if (gsk_gl_render_job_begin_draw (job, program)) { - const GskGLUniform *u = &uniforms[i]; - const guint8 *data = base + u->offset; - - switch (u->type) + for (guint i = 0; i < n_children; i++) + gsk_gl_program_set_uniform_texture (program, + UNIFORM_CUSTOM_TEXTURE1 + i, 0, + GL_TEXTURE_2D, + GL_TEXTURE0 + i, + offscreens[i].texture_id); + gsk_gl_program_set_uniform2f (program, + UNIFORM_CUSTOM_SIZE, 0, + node->bounds.size.width, + node->bounds.size.height); + for (guint i = 0; i < n_uniforms; i++) { - default: - case GSK_GL_UNIFORM_TYPE_NONE: - break; - case GSK_GL_UNIFORM_TYPE_FLOAT: - gsk_gl_uniform_state_set1fv (job->command_queue->uniforms, - program->program_info, - UNIFORM_CUSTOM_ARG0 + i, - 0, 1, (const float *)data); - break; - case GSK_GL_UNIFORM_TYPE_INT: - gsk_gl_uniform_state_set1i (job->command_queue->uniforms, - program->program_info, - UNIFORM_CUSTOM_ARG0 + i, - 0, *(const gint32 *)data); - break; - case GSK_GL_UNIFORM_TYPE_UINT: - case GSK_GL_UNIFORM_TYPE_BOOL: - gsk_gl_uniform_state_set1ui (job->command_queue->uniforms, - program->program_info, - UNIFORM_CUSTOM_ARG0 + i, - 0, *(const guint32 *)data); - break; - case GSK_GL_UNIFORM_TYPE_VEC2: - gsk_gl_uniform_state_set2fv (job->command_queue->uniforms, - program->program_info, - UNIFORM_CUSTOM_ARG0 + i, - 0, 1, (const float *)data); - break; - case GSK_GL_UNIFORM_TYPE_VEC3: - gsk_gl_uniform_state_set3fv (job->command_queue->uniforms, - program->program_info, - UNIFORM_CUSTOM_ARG0 + i, - 0, 1, (const float *)data); - break; - case GSK_GL_UNIFORM_TYPE_VEC4: - gsk_gl_uniform_state_set4fv (job->command_queue->uniforms, - program->program_info, - UNIFORM_CUSTOM_ARG0 + i, - 0, 1, (const float *)data); - break; + const GskGLUniform *u = &uniforms[i]; + const guint8 *data = base + u->offset; + + switch (u->type) + { + default: + case GSK_GL_UNIFORM_TYPE_NONE: + break; + case GSK_GL_UNIFORM_TYPE_FLOAT: + gsk_gl_uniform_state_set1fv (job->command_queue->uniforms, + program->program_info, + UNIFORM_CUSTOM_ARG0 + i, + 0, 1, (const float *)data); + break; + case GSK_GL_UNIFORM_TYPE_INT: + gsk_gl_uniform_state_set1i (job->command_queue->uniforms, + program->program_info, + UNIFORM_CUSTOM_ARG0 + i, + 0, *(const gint32 *)data); + break; + case GSK_GL_UNIFORM_TYPE_UINT: + case GSK_GL_UNIFORM_TYPE_BOOL: + gsk_gl_uniform_state_set1ui (job->command_queue->uniforms, + program->program_info, + UNIFORM_CUSTOM_ARG0 + i, + 0, *(const guint32 *)data); + break; + case GSK_GL_UNIFORM_TYPE_VEC2: + gsk_gl_uniform_state_set2fv (job->command_queue->uniforms, + program->program_info, + UNIFORM_CUSTOM_ARG0 + i, + 0, 1, (const float *)data); + break; + case GSK_GL_UNIFORM_TYPE_VEC3: + gsk_gl_uniform_state_set3fv (job->command_queue->uniforms, + program->program_info, + UNIFORM_CUSTOM_ARG0 + i, + 0, 1, (const float *)data); + break; + case GSK_GL_UNIFORM_TYPE_VEC4: + gsk_gl_uniform_state_set4fv (job->command_queue->uniforms, + program->program_info, + UNIFORM_CUSTOM_ARG0 + i, + 0, 1, (const float *)data); + break; + } } + gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds); + gsk_gl_render_job_end_draw (job); } - gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds); - gsk_gl_render_job_end_draw (job); } } @@ -3583,18 +3616,19 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job, g_assert (offscreen.texture_id); g_assert (offscreen.was_offscreen == FALSE); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)); - - gsk_gl_program_set_uniform_texture_with_sync (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - offscreen.texture_id, - offscreen.has_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR, - GL_LINEAR, - offscreen.sync); - gsk_gl_render_job_draw_offscreen (job, bounds, &offscreen); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit))) + { + gsk_gl_program_set_uniform_texture_with_sync (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + offscreen.texture_id, + offscreen.has_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR, + GL_LINEAR, + offscreen.sync); + gsk_gl_render_job_draw_offscreen (job, bounds, &offscreen); + gsk_gl_render_job_end_draw (job); + } } else { @@ -3608,36 +3642,37 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job, g_assert (slices != NULL); g_assert (n_slices > 0); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)); - - for (unsigned int i = 0; i < n_slices; i++) + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit))) { - const GskGLTextureSlice *slice = &slices[i]; - float x1, x2, y1, y2; - - x1 = min_x + (scale_x * slice->rect.x); - x2 = x1 + (slice->rect.width * scale_x); - y1 = min_y + (scale_y * slice->rect.y); - y2 = y1 + (slice->rect.height * scale_y); - - if (i > 0) - gsk_gl_render_job_split_draw (job); - gsk_gl_program_set_uniform_texture_with_filter (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - slice->texture_id, - use_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR, - GL_LINEAR); + for (unsigned int i = 0; i < n_slices; i++) + { + const GskGLTextureSlice *slice = &slices[i]; + float x1, x2, y1, y2; - gsk_gl_render_job_draw_coords (job, - x1, y1, x2, y2, - slice->area.x, slice->area.y, - slice->area.x2, slice->area.y2, - (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); - } + x1 = min_x + (scale_x * slice->rect.x); + x2 = x1 + (slice->rect.width * scale_x); + y1 = min_y + (scale_y * slice->rect.y); + y2 = y1 + (slice->rect.height * scale_y); - gsk_gl_render_job_end_draw (job); + if (i > 0) + gsk_gl_render_job_split_draw (job); + gsk_gl_program_set_uniform_texture_with_filter (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + slice->texture_id, + use_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR, + GL_LINEAR); + + gsk_gl_render_job_draw_coords (job, + x1, y1, x2, y2, + slice->area.x, slice->area.y, + slice->area.x2, slice->area.y2, + (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); + } + + gsk_gl_render_job_end_draw (job); + } } } @@ -3736,20 +3771,22 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job, u1 = (clip_rect.origin.x + clip_rect.size.width - bounds->origin.x) / bounds->size.width; 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_with_sync (job->current_program, - UNIFORM_SHARED_SOURCE, 0, - GL_TEXTURE_2D, - GL_TEXTURE0, - texture_id, - min_filter, - mag_filter, - sync); - gsk_gl_render_job_draw_coords (job, - 0, 0, clip_rect.size.width, clip_rect.size.height, - u0, v0, u1, v1, - (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit))) + { + gsk_gl_program_set_uniform_texture_with_sync (job->current_program, + UNIFORM_SHARED_SOURCE, 0, + GL_TEXTURE_2D, + GL_TEXTURE0, + texture_id, + min_filter, + mag_filter, + sync); + gsk_gl_render_job_draw_coords (job, + 0, 0, clip_rect.size.width, clip_rect.size.height, + u0, v0, u1, v1, + (guint16[]) { FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO }); + gsk_gl_render_job_end_draw (job); + } } else { @@ -3760,42 +3797,43 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job, gsk_gl_driver_slice_texture (job->driver, texture, filter == GSK_SCALING_FILTER_TRILINEAR, &slices, &n_slices); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)); - - for (guint i = 0; i < n_slices; i++) + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit))) { - const GskGLTextureSlice *slice = &slices[i]; - graphene_rect_t slice_bounds; + for (guint i = 0; i < n_slices; i++) + { + const GskGLTextureSlice *slice = &slices[i]; + graphene_rect_t slice_bounds; - slice_bounds.origin.x = bounds->origin.x - clip_rect.origin.x + slice->rect.x * scale_x; - slice_bounds.origin.y = bounds->origin.y - clip_rect.origin.y + slice->rect.y * scale_y; - slice_bounds.size.width = slice->rect.width * scale_x; - slice_bounds.size.height = slice->rect.height * scale_y; + slice_bounds.origin.x = bounds->origin.x - clip_rect.origin.x + slice->rect.x * scale_x; + slice_bounds.origin.y = bounds->origin.y - clip_rect.origin.y + slice->rect.y * scale_y; + slice_bounds.size.width = slice->rect.width * scale_x; + slice_bounds.size.height = slice->rect.height * scale_y; - if (!graphene_rect_intersection (&slice_bounds, &viewport, NULL)) - continue; + if (!graphene_rect_intersection (&slice_bounds, &viewport, NULL)) + continue; - if (i > 0) - gsk_gl_render_job_split_draw (job); + if (i > 0) + gsk_gl_render_job_split_draw (job); - 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, - slice_bounds.origin.x + slice_bounds.size.width, - slice_bounds.origin.y + slice_bounds.size.height, - slice->area.x, slice->area.y, - slice->area.x2, slice->area.y2, - (guint16[]){ FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO } ); - } + 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, + slice_bounds.origin.x + slice_bounds.size.width, + slice_bounds.origin.y + slice_bounds.size.height, + slice->area.x, slice->area.y, + slice->area.x2, slice->area.y2, + (guint16[]){ FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO } ); + } - gsk_gl_render_job_end_draw (job); + gsk_gl_render_job_end_draw (job); + } } gsk_gl_render_job_pop_clip (job); @@ -3809,21 +3847,23 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job, gsk_gl_driver_cache_texture (job->driver, &key, texture_id); render_texture: - 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, - texture_id); - gsk_gl_render_job_draw_coords (job, - job->offset_x + clip_rect.origin.x, - job->offset_y + clip_rect.origin.y, - job->offset_x + clip_rect.origin.x + clip_rect.size.width, - job->offset_y + clip_rect.origin.y + clip_rect.size.height, - 0, clip_rect.size.width / ceilf (clip_rect.size.width), - clip_rect.size.height / ceilf (clip_rect.size.height), 0, - (guint16[]){ FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO } ); - gsk_gl_render_job_end_draw (job); + if (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, + texture_id); + gsk_gl_render_job_draw_coords (job, + job->offset_x + clip_rect.origin.x, + job->offset_y + clip_rect.origin.y, + job->offset_x + clip_rect.origin.x + clip_rect.size.width, + job->offset_y + clip_rect.origin.y + clip_rect.size.height, + 0, clip_rect.size.width / ceilf (clip_rect.size.width), + clip_rect.size.height / ceilf (clip_rect.size.height), 0, + (guint16[]){ FP16_ZERO, FP16_ZERO, FP16_ZERO, FP16_ZERO } ); + gsk_gl_render_job_end_draw (job); + } } static inline void @@ -3859,26 +3899,28 @@ gsk_gl_render_job_visit_repeat_node (GskGLRenderJob *job, if (!gsk_gl_render_job_visit_node_with_offscreen (job, child, &offscreen)) g_assert_not_reached (); - gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, repeat)); - 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_uniform4f (job->current_program, - UNIFORM_REPEAT_CHILD_BOUNDS, 0, - (node->bounds.origin.x - child_bounds->origin.x) / child_bounds->size.width, - (node->bounds.origin.y - child_bounds->origin.y) / child_bounds->size.height, - node->bounds.size.width / child_bounds->size.width, - node->bounds.size.height / child_bounds->size.height); - gsk_gl_program_set_uniform4f (job->current_program, - UNIFORM_REPEAT_TEXTURE_RECT, 0, - offscreen.area.x, - offscreen.was_offscreen ? offscreen.area.y2 : offscreen.area.y, - offscreen.area.x2, - offscreen.was_offscreen ? offscreen.area.y : offscreen.area.y2); - gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen); - gsk_gl_render_job_end_draw (job); + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, repeat))) + { + 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_uniform4f (job->current_program, + UNIFORM_REPEAT_CHILD_BOUNDS, 0, + (node->bounds.origin.x - child_bounds->origin.x) / child_bounds->size.width, + (node->bounds.origin.y - child_bounds->origin.y) / child_bounds->size.height, + node->bounds.size.width / child_bounds->size.width, + node->bounds.size.height / child_bounds->size.height); + gsk_gl_program_set_uniform4f (job->current_program, + UNIFORM_REPEAT_TEXTURE_RECT, 0, + offscreen.area.x, + offscreen.was_offscreen ? offscreen.area.y2 : offscreen.area.y, + offscreen.area.x2, + offscreen.was_offscreen ? offscreen.area.y : offscreen.area.y2); + gsk_gl_render_job_draw_offscreen (job, &node->bounds, &offscreen); + gsk_gl_render_job_end_draw (job); + } } static void @@ -4343,14 +4385,16 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job, gsk_gl_render_job_set_alpha (job, 1.0f); gsk_gl_command_queue_bind_framebuffer (job->command_queue, job->framebuffer); gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); - 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, - texture_id); - gsk_gl_render_job_draw_rect (job, &job->viewport); - gsk_gl_render_job_end_draw (job); + if (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, + texture_id); + gsk_gl_render_job_draw_rect (job, &job->viewport); + gsk_gl_render_job_end_draw (job); + } gdk_gl_context_push_debug_group (job->command_queue->context, "Executing command queue"); gsk_gl_command_queue_execute (job->command_queue, surface_height, 1, NULL, job->default_framebuffer); diff --git a/tests/meson.build b/tests/meson.build index c9c6e6a4cd..3294b47d08 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -25,13 +25,11 @@ gtk_tests = [ ['testbaseline'], ['testbaseline2'], ['testcalendar'], - ['testclipboard2'], ['testcombo'], ['testcolumnview'], ['testcombochange'], ['testcellrenderertext'], ['testdialog'], - ['testdnd'], ['testdnd2'], ['testdndresize'], ['testellipsise'], diff --git a/tests/testclipboard2.c b/tests/testclipboard2.c deleted file mode 100644 index 32df2cba95..0000000000 --- a/tests/testclipboard2.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (C) 2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <gtk/gtk.h> - -static GdkTexture * -render_paintable_to_texture (GdkPaintable *paintable) -{ - GtkSnapshot *snapshot; - GskRenderNode *node; - int width, height; - cairo_surface_t *surface; - cairo_t *cr; - GdkTexture *texture; - GBytes *bytes; - - width = gdk_paintable_get_intrinsic_width (paintable); - height = gdk_paintable_get_intrinsic_height (paintable); - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - - snapshot = gtk_snapshot_new (); - gdk_paintable_snapshot (paintable, snapshot, width, height); - node = gtk_snapshot_free_to_node (snapshot); - - cr = cairo_create (surface); - gsk_render_node_draw (node, cr); - cairo_destroy (cr); - - gsk_render_node_unref (node); - - bytes = g_bytes_new_with_free_func (cairo_image_surface_get_data (surface), - cairo_image_surface_get_height (surface) - * cairo_image_surface_get_stride (surface), - (GDestroyNotify) cairo_surface_destroy, - cairo_surface_reference (surface)); - texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface), - cairo_image_surface_get_height (surface), - GDK_MEMORY_DEFAULT, - bytes, - cairo_image_surface_get_stride (surface)); - g_bytes_unref (bytes); - cairo_surface_destroy (surface); - - return texture; -} - -static void -clipboard_changed_cb (GdkClipboard *clipboard, - GtkWidget *stack) -{ - GtkWidget *child; - - gtk_stack_set_visible_child_name (GTK_STACK (stack), "info"); - - child = gtk_stack_get_child_by_name (GTK_STACK (stack), "image"); - gtk_image_clear (GTK_IMAGE (child)); - - child = gtk_stack_get_child_by_name (GTK_STACK (stack), "text"); - gtk_label_set_text (GTK_LABEL (child), ""); -} - -static void -texture_loaded_cb (GObject *clipboard, - GAsyncResult *res, - gpointer data) -{ - GError *error = NULL; - GdkTexture *texture; - - texture = gdk_clipboard_read_texture_finish (GDK_CLIPBOARD (clipboard), res, &error); - if (texture == NULL) - { - g_print ("%s\n", error->message); - g_error_free (error); - return; - } - - gtk_image_set_from_paintable (data, GDK_PAINTABLE (texture)); - g_object_unref (texture); -} - -static void -text_loaded_cb (GObject *clipboard, - GAsyncResult *res, - gpointer data) -{ - GError *error = NULL; - char *text; - - text = gdk_clipboard_read_text_finish (GDK_CLIPBOARD (clipboard), res, &error); - if (text == NULL) - { - g_print ("%s\n", error->message); - g_error_free (error); - return; - } - - gtk_label_set_text (data, text); - g_free (text); -} - -static void -visible_child_changed_cb (GtkWidget *stack, - GParamSpec *pspec, - GdkClipboard *clipboard) -{ - const char *visible_child = gtk_stack_get_visible_child_name (GTK_STACK (stack)); - - if (visible_child == NULL) - { - /* nothing to do here but avoiding crashes in g_str_equal() */ - } - else if (g_str_equal (visible_child, "image")) - { - GtkWidget *image = gtk_stack_get_child_by_name (GTK_STACK (stack), "image"); - - gdk_clipboard_read_texture_async (clipboard, - NULL, - texture_loaded_cb, - image); - } - else if (g_str_equal (visible_child, "text")) - { - GtkWidget *label = gtk_stack_get_child_by_name (GTK_STACK (stack), "text"); - - gdk_clipboard_read_text_async (clipboard, - NULL, - text_loaded_cb, - label); - } -} - -#ifdef G_OS_UNIX /* portal usage supported on *nix only */ - -static GSList * -get_file_list (const char *dir) -{ - GFileEnumerator *enumerator; - GFile *file; - GFileInfo *info; - GSList *list = NULL; - - file = g_file_new_for_path (dir); - enumerator = g_file_enumerate_children (file, "standard::name,standard::type", 0, NULL, NULL); - g_object_unref (file); - if (enumerator == NULL) - return NULL; - - while (g_file_enumerator_iterate (enumerator, &info, &file, NULL, NULL) && file != NULL) - { - /* the portal can't handle directories */ - if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR) - continue; - - list = g_slist_prepend (list, g_object_ref (file)); - } - - return g_slist_reverse (list); -} - -#else /* G_OS_UNIX -- original non-portal-enabled code */ - -static GList * -get_file_list (const char *dir) -{ - GFileEnumerator *enumerator; - GFile *file; - GList *list = NULL; - - file = g_file_new_for_path (dir); - enumerator = g_file_enumerate_children (file, "standard::name", 0, NULL, NULL); - g_object_unref (file); - if (enumerator == NULL) - return NULL; - - while (g_file_enumerator_iterate (enumerator, NULL, &file, NULL, NULL) && file != NULL) - list = g_list_prepend (list, g_object_ref (file)); - - return g_list_reverse (list); -} - -#endif /* !G_OS_UNIX */ - -static void -format_list_add_row (GtkWidget *list, - const char *format_name, - GdkContentFormats *formats) -{ - GtkWidget *box; - - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); - gtk_box_append (GTK_BOX (box), gtk_label_new (format_name)); - - gdk_content_formats_unref (formats); - gtk_list_box_insert (GTK_LIST_BOX (list), box, -1); -} - -static void -clipboard_formats_change_cb (GdkClipboard *clipboard, - GParamSpec *pspec, - GtkWidget *list) -{ - GdkContentFormats *formats; - GtkWidget *row; - const char * const *mime_types; - const GType *gtypes; - gsize i, n; - - while ((row = GTK_WIDGET (gtk_list_box_get_row_at_index (GTK_LIST_BOX (list), 0)))) - gtk_list_box_remove (GTK_LIST_BOX (list), row); - - formats = gdk_clipboard_get_formats (clipboard); - - gtypes = gdk_content_formats_get_gtypes (formats, &n); - for (i = 0; i < n; i++) - { - format_list_add_row (list, - g_type_name (gtypes[i]), - gdk_content_formats_new_for_gtype (gtypes[i])); - } - - mime_types = gdk_content_formats_get_mime_types (formats, &n); - for (i = 0; i < n; i++) - { - format_list_add_row (list, - mime_types[i], - gdk_content_formats_new ((const char *[2]) { mime_types[i], NULL }, 1)); - } -} - -static GtkWidget * -get_formats_list (GdkClipboard *clipboard) -{ - GtkWidget *sw, *list; - - sw = gtk_scrolled_window_new (); - - list = gtk_list_box_new (); - g_signal_connect_object (clipboard, "notify::formats", G_CALLBACK (clipboard_formats_change_cb), list, 0); - clipboard_formats_change_cb (clipboard, NULL, list); - gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list); - - return sw; -} - -static GtkWidget * -get_contents_widget (GdkClipboard *clipboard) -{ - GtkWidget *stack, *child; - - stack = gtk_stack_new (); - gtk_widget_set_hexpand (stack, TRUE); - gtk_widget_set_vexpand (stack, TRUE); - g_signal_connect (stack, "notify::visible-child", G_CALLBACK (visible_child_changed_cb), clipboard); - g_signal_connect_object (clipboard, "changed", G_CALLBACK (clipboard_changed_cb), stack, 0); - - child = get_formats_list (clipboard); - gtk_stack_add_titled (GTK_STACK (stack), child, "info", "Info"); - - child = gtk_image_new (); - gtk_stack_add_titled (GTK_STACK (stack), child, "image", "Image"); - - child = gtk_label_new (NULL); - gtk_label_set_wrap (GTK_LABEL (child), TRUE); - gtk_stack_add_titled (GTK_STACK (stack), child, "text", "Text"); - - return stack; -} - -static void -provider_button_clicked_cb (GtkWidget *button, - GdkClipboard *clipboard) -{ - gdk_clipboard_set_content (clipboard, - g_object_get_data (G_OBJECT (button), "provider")); -} - -static void -add_provider_button (GtkWidget *box, - GdkContentProvider *provider, - GdkClipboard *clipboard, - const char *name) -{ - GtkWidget *button; - - button = gtk_button_new_with_label (name); - g_signal_connect (button, "clicked", G_CALLBACK (provider_button_clicked_cb), clipboard); - if (provider) - g_object_set_data_full (G_OBJECT (button), "provider", provider, g_object_unref); - - gtk_box_append (GTK_BOX (box), button); -} - -static GtkWidget * -get_button_list (GdkClipboard *clipboard, - const char *info) -{ - static const guchar invalid_utf8[] = { 'L', 'i', 'b', 'e', 'r', 't', 0xe9, ',', ' ', - 0xc9, 'g', 'a', 'l', 'i', 't', 0xe9, ',', ' ', - 'F', 'r', 'a', 't', 'e', 'r', 'n', 'i', 't', 0xe9, 0 }; - GtkWidget *box; - GtkIconPaintable *icon; - GdkTexture *texture; - GValue value = G_VALUE_INIT; - - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - - gtk_box_append (GTK_BOX (box), gtk_label_new (info)); - - add_provider_button (box, - NULL, - clipboard, - "Empty"); - - g_value_init (&value, GDK_TYPE_PIXBUF); - icon = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_for_display (gdk_clipboard_get_display (clipboard)), - "utilities-terminal", - NULL, - 48, 1, - gtk_widget_get_direction (box), - 0); - texture = render_paintable_to_texture (GDK_PAINTABLE (icon)); - g_value_take_object (&value, gdk_pixbuf_get_from_texture (texture)); - g_object_unref (texture); - g_object_unref (icon); - add_provider_button (box, - gdk_content_provider_new_for_value (&value), - clipboard, - "GdkPixbuf"); - g_value_unset (&value); - - add_provider_button (box, - gdk_content_provider_new_typed (G_TYPE_STRING, "Hello Clipboard ☺"), - clipboard, - "gchararry"); - - add_provider_button (box, - gdk_content_provider_new_for_bytes ("text/plain;charset=utf-8", - g_bytes_new_static ("𝕳𝖊𝖑𝖑𝖔 𝖀𝖓𝖎𝖈𝖔𝖉𝖊", - strlen ("𝕳𝖊𝖑𝖑𝖔 𝖀𝖓𝖎𝖈𝖔𝖉𝖊") + 1)), - clipboard, - "text/plain"); - - add_provider_button (box, - gdk_content_provider_new_for_bytes ("text/plain;charset=utf-8", - g_bytes_new_static (invalid_utf8, sizeof(invalid_utf8))), - clipboard, - "Invalid UTF-8"); - - g_value_init (&value, G_TYPE_FILE); - g_value_take_object (&value, g_file_new_for_path (g_get_home_dir ())); - add_provider_button (box, - gdk_content_provider_new_for_value (&value), - clipboard, - "home directory"); - g_value_unset (&value); - - g_value_init (&value, GDK_TYPE_FILE_LIST); - g_value_take_boxed (&value, get_file_list (g_get_home_dir ())); - add_provider_button (box, - gdk_content_provider_new_for_value (&value), - clipboard, - "files in home"); - return box; -} - -static GtkWidget * -get_clipboard_widget (GdkClipboard *clipboard, - GdkClipboard *alt_clipboard, - const char *name) -{ - GtkWidget *vbox, *hbox, *stack, *switcher; - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_box_append (GTK_BOX (hbox), vbox); - gtk_box_append (GTK_BOX (vbox), gtk_label_new (name)); - switcher = gtk_stack_switcher_new (); - gtk_box_append (GTK_BOX (vbox), switcher); - stack = get_contents_widget (clipboard); - gtk_box_append (GTK_BOX (vbox), stack); - gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (switcher), GTK_STACK (stack)); - gtk_box_append (GTK_BOX (hbox), get_button_list (clipboard, "Set Locally:")); - if (clipboard != alt_clipboard) - gtk_box_append (GTK_BOX (hbox), get_button_list (alt_clipboard, "Set Remotely:")); - - return hbox; -} - -static GtkWidget * -get_window_contents (GdkDisplay *display, - GdkDisplay *alt_display) -{ - GtkWidget *box; - - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_box_set_homogeneous (GTK_BOX (box), TRUE); - gtk_box_append (GTK_BOX (box), - get_clipboard_widget (gdk_display_get_clipboard (display), - gdk_display_get_clipboard (alt_display), - "Clipboard")); - gtk_box_append (GTK_BOX (box), - get_clipboard_widget (gdk_display_get_primary_clipboard (display), - gdk_display_get_primary_clipboard (alt_display), - "Primary Clipboard")); - - return box; -} - -static void -quit_cb (GtkWidget *widget, - gpointer data) -{ - gboolean *done = data; - - *done = TRUE; - - g_main_context_wakeup (NULL); -} - -int -main (int argc, char **argv) -{ - GtkWidget *window; - GdkDisplay *alt_display; - gboolean done = FALSE; - - gtk_init (); - - alt_display = gdk_display_open (NULL); - if (alt_display == NULL) - alt_display = gdk_display_get_default (); - - window = gtk_window_new (); - g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done); - gtk_window_set_child (GTK_WINDOW (window), - get_window_contents (gtk_widget_get_display (window), - alt_display)); - - gtk_window_present (GTK_WINDOW (window)); - - while (!done) - g_main_context_iteration (NULL, TRUE); - - return 0; -} diff --git a/tests/testdnd.c b/tests/testdnd.c deleted file mode 100644 index 66e3c3c94a..0000000000 --- a/tests/testdnd.c +++ /dev/null @@ -1,597 +0,0 @@ -/* testdnd.c - * Copyright (C) 1998 Red Hat, Inc. - * Author: Owen Taylor - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "config.h" -#include "gtk/gtk.h" - -/* Target side drag signals */ - -/* XPM */ -static const char * drag_icon_xpm[] = { -"36 48 9 1", -" c None", -". c #020204", -"+ c #8F8F90", -"@ c #D3D3D2", -"# c #AEAEAC", -"$ c #ECECEC", -"% c #A2A2A4", -"& c #FEFEFC", -"* c #BEBEBC", -" .....................", -" ..&&&&&&&&&&&&&&&&&&&.", -" ...&&&&&&&&&&&&&&&&&&&.", -" ..&.&&&&&&&&&&&&&&&&&&&.", -" ..&&.&&&&&&&&&&&&&&&&&&&.", -" ..&&&.&&&&&&&&&&&&&&&&&&&.", -" ..&&&&.&&&&&&&&&&&&&&&&&&&.", -" ..&&&&&.&&&@&&&&&&&&&&&&&&&.", -" ..&&&&&&.*$%$+$&&&&&&&&&&&&&.", -" ..&&&&&&&.%$%$+&&&&&&&&&&&&&&.", -" ..&&&&&&&&.#&#@$&&&&&&&&&&&&&&.", -" ..&&&&&&&&&.#$**#$&&&&&&&&&&&&&.", -" ..&&&&&&&&&&.&@%&%$&&&&&&&&&&&&&.", -" ..&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.", -" ..&&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.", -"................&$@&&&@&&&&&&&&&&&&.", -".&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&&&&&.", -".&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&&&.", -".&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&&&.", -".&&&&&&@#@@$&*@&@#@#$**#$&&&&&&&&&&.", -".&&&&&&&&&&&&&&&&&&&@%&%$&&&&&&&&&&.", -".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", -".&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&&&.", -".&&&&&&&&&+&$+&$&@&$@&&$@&&&&&&&&&&.", -".&&&&&&&&&+&&#@%#+@#@*$%&+$&&&&&&&&.", -".&&&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&.", -".&&&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&.", -".&&&&&&&&@#@@$&*@&@#@#$#*#$&&&&&&&&.", -".&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&&&.", -".&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&.", -".&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&&&&&.", -".&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&.", -".&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&&&&&.", -".&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&&&&&.", -".&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&&&&&.", -".&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&.", -".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", -".&&&&&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&.", -".&&&&&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&.", -".&&&&&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&.", -".&&&&&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&.", -".&&&&&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&.", -".&&&&&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&.", -".&&&&&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&.", -".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", -".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", -".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.", -"...................................."}; - -/* XPM */ -static const char * trashcan_closed_xpm[] = { -"64 80 17 1", -" c None", -". c #030304", -"+ c #5A5A5C", -"@ c #323231", -"# c #888888", -"$ c #1E1E1F", -"% c #767677", -"& c #494949", -"* c #9E9E9C", -"= c #111111", -"- c #3C3C3D", -"; c #6B6B6B", -"> c #949494", -", c #282828", -"' c #808080", -") c #545454", -"! c #AEAEAC", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ==......=$$...=== ", -" ..$------)+++++++++++++@$$... ", -" ..=@@-------&+++++++++++++++++++-.... ", -" =.$$@@@-&&)++++)-,$$$$=@@&+++++++++++++,..$ ", -" .$$$$@@&+++++++&$$$@@@@-&,$,-++++++++++;;;&.. ", -" $$$$,@--&++++++&$$)++++++++-,$&++++++;%%'%%;;$@ ", -" .-@@-@-&++++++++-@++++++++++++,-++++++;''%;;;%*-$ ", -" +------++++++++++++++++++++++++++++++;;%%%;;##*!. ", -" =+----+++++++++++++++++++++++;;;;;;;;;;;;%'>>). ", -" .=)&+++++++++++++++++;;;;;;;;;;;;;;%''>>#>#@. ", -" =..=&++++++++++++;;;;;;;;;;;;;%###>>###+%== ", -" .&....=-+++++%;;####''''''''''##'%%%)..#. ", -" .+-++@....=,+%#####'%%%%%%%%%;@$-@-@*++!. ", -" .+-++-+++-&-@$$=$=......$,,,@;&)+!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" =+-++-+++-+++++++++!++++!++++!+++!++!+++= ", -" $.++-+++-+++++++++!++++!++++!+++!++!+.$ ", -" =.++++++++++++++!++++!++++!+++!++.= ", -" $..+++++++++++++++!++++++...$ ", -" $$=.............=$$ ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; - -/* XPM */ -static const char * trashcan_open_xpm[] = { -"64 80 17 1", -" c None", -". c #030304", -"+ c #5A5A5C", -"@ c #323231", -"# c #888888", -"$ c #1E1E1F", -"% c #767677", -"& c #494949", -"* c #9E9E9C", -"= c #111111", -"- c #3C3C3D", -"; c #6B6B6B", -"> c #949494", -", c #282828", -"' c #808080", -") c #545454", -"! c #AEAEAC", -" ", -" ", -" ", -" ", -" ", -" ", -" .=.==.,@ ", -" ==.,@-&&&)-= ", -" .$@,&++;;;%>*- ", -" $,-+)+++%%;;'#+. ", -" =---+++++;%%%;%##@. ", -" @)++++++++;%%%%'#%$ ", -" $&++++++++++;%%;%##@= ", -" ,-++++)+++++++;;;'#%) ", -" @+++&&--&)++++;;%'#'-. ", -" ,&++-@@,,,,-)++;;;'>'+, ", -" =-++&@$@&&&&-&+;;;%##%+@ ", -" =,)+)-,@@&+++++;;;;%##%&@ ", -" @--&&,,@&)++++++;;;;'#)@ ", -" ---&)-,@)+++++++;;;%''+, ", -" $--&)+&$-+++++++;;;%%'';- ", -" .,-&+++-$&++++++;;;%''%&= ", -" $,-&)++)-@++++++;;%''%), ", -" =,@&)++++&&+++++;%'''+$@&++++++ ", -" .$@-++++++++++++;'#';,........=$@&++++ ", -" =$@@&)+++++++++++'##-.................=&++ ", -" .$$@-&)+++++++++;%#+$.....................=)+ ", -" $$,@-)+++++++++;%;@=........................,+ ", -" .$$@@-++++++++)-)@=............................ ", -" $,@---)++++&)@===............................,. ", -" $-@---&)))-$$=..............................=)!. ", -" --&-&&,,$=,==...........................=&+++!. ", -" =,=$..=$+)+++++&@$=.............=$@&+++++!++!. ", -" .)-++-+++++++++++++++++++++++++++!++!++!. ", -" .+-++-+++++++++++++++++++++++!+++!++!++!. ", -" .+-++-+++-+++++++++!+++!!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" .+-++-+++-+++++++++!++++!++++!+++!++!++!. ", -" =+-++-+++-+++++++++!++++!++++!+++!++!+++= ", -" $.++-+++-+++++++++!++++!++++!+++!++!+.$ ", -" =.++++++++++++++!++++!++++!+++!++.= ", -" $..+++++++++++++++!++++++...$ ", -" $$==...........==$$ ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; - -GdkPixbuf *trashcan_open; -GdkPixbuf *trashcan_closed; - - -static GdkDragAction -action_make_unique (GdkDragAction action) -{ - if (gdk_drag_action_is_unique (action)) - return action; - - if (action & GDK_ACTION_COPY) - return GDK_ACTION_COPY; - - if (action & GDK_ACTION_MOVE) - return GDK_ACTION_MOVE; - - if (action & GDK_ACTION_LINK) - return GDK_ACTION_LINK; - - g_assert_not_reached (); - return 0; -} - -static GdkDragAction -trash_drag_enter (GtkDropTarget *dest, - GdkDrop *drop, - double x, - double y, - GtkWidget *widget) -{ - char *s; - - gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_open); - - s = gdk_content_formats_to_string (gdk_drop_get_formats (drop)); - g_print ("trash enter: %s\n", s); - g_free (s); - - return action_make_unique (gdk_drop_get_actions (drop));; -} - -static GdkDragAction -trash_drag_leave (GtkDropTarget *dest, - GdkDrop *drop, - GtkWidget *widget) -{ - char *s; - - gtk_image_set_from_pixbuf (GTK_IMAGE (widget), trashcan_closed); - - s = gdk_content_formats_to_string (gdk_drop_get_formats (drop)); - g_print ("trash leave: %s\n", s); - g_free (s); - - return action_make_unique (gdk_drop_get_actions (drop)); -} - -static gboolean -trash_drag_drop (GtkDropTarget *dest, - GdkDrop *drop, - double x, - double y, - GtkWidget *widget) -{ - char *s; - - s = gdk_content_formats_to_string (gdk_drop_get_formats (drop)); - g_print ("trash drop: %s\n", s); - g_free (s); - - gdk_drop_finish (drop, action_make_unique (gdk_drop_get_actions (drop))); - - return TRUE; -} - -static gboolean -label_drag_drop (GtkDropTarget *dest, - const GValue *value, - int x, - int y, - GtkWidget *widget) -{ - g_print ("Received \"%s\" in label\n", g_value_get_string (value)); - return TRUE; -} - -/* The following is a rather elaborate example demonstrating/testing - * changing of the window hierarchy during a drag - in this case, - * via a "spring-loaded" popup window. - */ -static GtkWidget *popup_window = NULL; - -static gboolean popped_up = FALSE; -static gboolean in_popup = FALSE; -static guint popdown_timer = 0; -static guint popup_timer = 0; - -static int -popdown_cb (gpointer data) -{ - popdown_timer = 0; - - gtk_widget_set_visible (popup_window, FALSE); - popped_up = FALSE; - - return FALSE; -} - -static void -popup_enter (GtkDropTarget *dest) -{ - g_print ("popup enter\n"); - if (!in_popup) - { - in_popup = TRUE; - if (popdown_timer) - { - g_print ("removed popdown\n"); - g_source_remove (popdown_timer); - popdown_timer = 0; - } - } -} - -static void -popup_leave (GtkDropTarget *dest) -{ -g_print ("popup leave\n"); - if (in_popup) - { - in_popup = FALSE; - if (!popdown_timer) - { - g_print ("added popdown\n"); - popdown_timer = g_timeout_add (500, popdown_cb, NULL); - } - } -} - -static gboolean -popup_drop (GtkDropTarget *dest) -{ - popdown_cb (NULL); - return TRUE; -} - -static gboolean -popup_cb (gpointer data) -{ - if (!popped_up) - { - if (!popup_window) - { - GtkWidget *button; - GtkWidget *grid; - int i, j; - - popup_window = gtk_window_new (); - - grid = gtk_grid_new (); - - for (i=0; i<3; i++) - for (j=0; j<3; j++) - { - char buffer[128]; - GtkDropTarget *dest; - - g_snprintf(buffer, sizeof(buffer), "%d,%d", i, j); - button = gtk_button_new_with_label (buffer); - gtk_widget_set_hexpand (button, TRUE); - gtk_widget_set_vexpand (button, TRUE); - gtk_grid_attach (GTK_GRID (grid), button, i, j, 1, 1); - - dest = gtk_drop_target_new (G_TYPE_STRING, GDK_ACTION_COPY | GDK_ACTION_MOVE); - g_signal_connect (dest, "enter", G_CALLBACK (popup_enter), NULL); - g_signal_connect (dest, "leave", G_CALLBACK (popup_leave), NULL); - g_signal_connect (dest, "drop", G_CALLBACK (popup_drop), NULL); - gtk_widget_add_controller (button, GTK_EVENT_CONTROLLER (dest)); - } - gtk_window_set_child (GTK_WINDOW (popup_window), grid); - } - gtk_widget_set_visible (popup_window, TRUE); - popped_up = TRUE; - } - - popup_timer = FALSE; - - return FALSE; -} - -static void -popsite_enter (GtkDropControllerMotion *motion) -{ - g_print ("popsite enter\n"); - if (!popup_timer) - popup_timer = g_timeout_add (500, popup_cb, NULL); -} - -static void -popsite_leave (GtkDropControllerMotion *motion) -{ - g_print ("popsite leave\n"); - if (popup_timer) - { - g_source_remove (popup_timer); - popup_timer = 0; - } -} - -static void -quit_cb (GtkWidget *widget, - gpointer data) -{ - gboolean *done = data; - - *done = TRUE; - - g_main_context_wakeup (NULL); -} - -int -main (int argc, char **argv) -{ - GtkWidget *window; - GtkWidget *grid; - GtkWidget *label; - GtkWidget *pixmap; - GtkWidget *button; - GdkPixbuf *drag_icon; - GdkTexture *texture; - GdkContentProvider *content; - GtkDragSource *source; - GtkDropTarget *dest; - GtkDropTargetAsync *async; - GtkEventController *controller; - gboolean done = FALSE; - - gtk_init (); - - window = gtk_window_new (); - g_signal_connect (window, "destroy", - G_CALLBACK (quit_cb), &done); - - - grid = gtk_grid_new (); - gtk_window_set_child (GTK_WINDOW (window), grid); - - drag_icon = gdk_pixbuf_new_from_xpm_data (drag_icon_xpm); - texture = gdk_texture_new_for_pixbuf (drag_icon); - g_object_unref (drag_icon); - trashcan_open = gdk_pixbuf_new_from_xpm_data (trashcan_open_xpm); - trashcan_closed = gdk_pixbuf_new_from_xpm_data (trashcan_closed_xpm); - - label = gtk_label_new ("Drop Here\n"); - - dest = gtk_drop_target_new (G_TYPE_STRING, GDK_ACTION_COPY | GDK_ACTION_MOVE); - g_signal_connect (dest, "drop", G_CALLBACK (label_drag_drop), NULL); - gtk_widget_add_controller (label, GTK_EVENT_CONTROLLER (dest)); - - gtk_widget_set_hexpand (label, TRUE); - gtk_widget_set_vexpand (label, TRUE); - gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1); - - label = gtk_label_new ("Popup\n"); - - controller = gtk_drop_controller_motion_new (); - g_signal_connect (controller, "enter", G_CALLBACK (popsite_enter), NULL); - g_signal_connect (controller, "leave", G_CALLBACK (popsite_leave), NULL); - gtk_widget_add_controller (label, controller); - - gtk_widget_set_hexpand (label, TRUE); - gtk_widget_set_vexpand (label, TRUE); - gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1); - - pixmap = gtk_image_new_from_pixbuf (trashcan_closed); - async = gtk_drop_target_async_new (NULL, GDK_ACTION_ALL); - g_signal_connect (async, "drag-enter", G_CALLBACK (trash_drag_enter), pixmap); - g_signal_connect (async, "drag-leave", G_CALLBACK (trash_drag_leave), pixmap); - g_signal_connect (async, "drop", G_CALLBACK (trash_drag_drop), pixmap); - gtk_widget_add_controller (pixmap, GTK_EVENT_CONTROLLER (async)); - - gtk_widget_set_hexpand (pixmap, TRUE); - gtk_widget_set_vexpand (pixmap, TRUE); - gtk_grid_attach (GTK_GRID (grid), pixmap, 1, 0, 1, 1); - - - /* Drag site */ - - button = gtk_label_new ("Drag Here\n"); - - source = gtk_drag_source_new (); - content = gdk_content_provider_new_typed (G_TYPE_STRING, "I'm data!"); - gtk_drag_source_set_content (source, content); - g_object_unref (content); - gtk_drag_source_set_actions (source, GDK_ACTION_COPY|GDK_ACTION_MOVE); - gtk_widget_add_controller (button, GTK_EVENT_CONTROLLER (source)); - gtk_drag_source_set_icon (source, GDK_PAINTABLE (texture), 0, 0); - - g_object_unref (texture); - - gtk_widget_set_hexpand (button, TRUE); - gtk_widget_set_vexpand (button, TRUE); - gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1); - - gtk_window_present (GTK_WINDOW (window)); - - while (!done) - g_main_context_iteration (NULL, TRUE); - - return 0; -} |