cogl: Properly support unbounded operators

This makes it so that operators requiring transparent values to be
used outside of the bounds of the source and/or mask textures will
trigger a second rendering of transparent pixels.

Signed-off-by: George Matsumura <gmmatsumura01@bvsd.org>
This commit is contained in:
George Matsumura 2020-07-18 19:03:28 -06:00
parent b258f0203c
commit 9248ba1419
8 changed files with 828 additions and 810 deletions

View file

@ -72,7 +72,7 @@ _cairo_cogl_context_reset_static_data (void)
static cairo_status_t
_cairo_cogl_context_rectangle_real (cairo_cogl_context_t *cr,
double x, double y,
double x, double y,
double width, double height)
{
cairo_status_t status;
@ -174,7 +174,8 @@ _cairo_cogl_context_rotate (void *abstract_cr, double theta)
}
static cairo_status_t
_cairo_cogl_context_transform (void *abstract_cr, const cairo_matrix_t *matrix)
_cairo_cogl_context_transform (void *abstract_cr,
const cairo_matrix_t *matrix)
{
cairo_cogl_context_t *cr = abstract_cr;
@ -189,7 +190,8 @@ _cairo_cogl_context_transform (void *abstract_cr, const cairo_matrix_t *matrix)
}
static cairo_status_t
_cairo_cogl_context_set_matrix (void *abstract_cr, const cairo_matrix_t *matrix)
_cairo_cogl_context_set_matrix (void *abstract_cr,
const cairo_matrix_t *matrix)
{
cairo_cogl_context_t *cr = abstract_cr;
@ -313,9 +315,9 @@ _cairo_cogl_context_line_to (void *abstract_cr, double x, double y)
static cairo_status_t
_cairo_cogl_context_curve_to (void *abstract_cr,
double x1, double y1,
double x2, double y2,
double x3, double y3)
double x1, double y1,
double x2, double y2,
double x3, double y3)
{
cairo_cogl_context_t *cr = abstract_cr;
cairo_status_t status;
@ -352,10 +354,13 @@ _cairo_cogl_context_curve_to (void *abstract_cr,
}
static cairo_status_t
_cairo_cogl_context_arc (void *abstract_cr,
double xc, double yc, double radius,
double angle1, double angle2,
cairo_bool_t forward)
_cairo_cogl_context_arc (void *abstract_cr,
double xc,
double yc,
double radius,
double angle1,
double angle2,
cairo_bool_t forward)
{
cairo_cogl_context_t *cr = abstract_cr;
cairo_status_t status;
@ -471,9 +476,9 @@ _cairo_cogl_context_rel_line_to (void *abstract_cr, double dx, double dy)
static cairo_status_t
_cairo_cogl_context_rel_curve_to (void *abstract_cr,
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3)
double dx1, double dy1,
double dx2, double dy2,
double dx3, double dy3)
{
cairo_cogl_context_t *cr = abstract_cr;
cairo_status_t status;
@ -577,8 +582,8 @@ _cairo_cogl_context_close_path (void *abstract_cr)
static cairo_status_t
_cairo_cogl_context_rectangle (void *abstract_cr,
double x, double y,
double width, double height)
double x, double y,
double width, double height)
{
cairo_cogl_context_t *cr = abstract_cr;
@ -636,7 +641,7 @@ _cairo_cogl_context_has_current_point (void *abstract_cr)
}
static cairo_bool_t
_cairo_cogl_context_get_current_point (void *abstract_cr,
_cairo_cogl_context_get_current_point (void *abstract_cr,
double *x,
double *y)
{
@ -671,7 +676,7 @@ _cairo_cogl_context_copy_path_flat (void *abstract_cr)
}
static cairo_status_t
_cairo_cogl_context_append_path (void *abstract_cr,
_cairo_cogl_context_append_path (void *abstract_cr,
const cairo_path_t *path)
{
cairo_cogl_context_t *cr = abstract_cr;
@ -719,18 +724,15 @@ _cairo_cogl_surface_set_side_band_state (cairo_cogl_surface_t *surface,
static cairo_cogl_surface_t *
_cairo_cogl_get_cogl_surface (cairo_surface_t *target)
{
/* Collapse all nested subsurfaces. If another method of target
* surface redirection is added to cairo, we can add a test here. */
while (1) {
if (_cairo_surface_is_subsurface (target)) {
target = _cairo_surface_subsurface_get_target (target);
} else if (target->type == CAIRO_SURFACE_TYPE_COGL) {
return (cairo_cogl_surface_t *)target;
} else {
/* return NULL if the target is not a cogl surface */
return NULL;
}
}
/* Subsurfaces are always 1-depth */
if (_cairo_surface_is_subsurface (target))
target = _cairo_surface_subsurface_get_target (target);
if (target->type == CAIRO_SURFACE_TYPE_COGL)
return (cairo_cogl_surface_t *)target;
else
/* return NULL if the target is not a cogl surface */
return NULL;
}
static cairo_status_t
@ -743,6 +745,19 @@ _cairo_cogl_context_fill (void *abstract_cr)
if (cr->path_is_rectangle) {
if (surface) {
cairo_matrix_t ctm;
status =
_cairo_surface_begin_modification (cr->base.gstate->target);
if (status)
return status;
ctm = cr->base.gstate->ctm;
if (_cairo_surface_is_subsurface (cr->base.gstate->target))
cairo_matrix_translate (&ctm,
((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.x,
((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.y);
status = _cairo_cogl_surface_fill_rectangle ((cairo_surface_t *)surface,
cr->base.gstate->op,
cr->base.gstate->source,
@ -750,7 +765,7 @@ _cairo_cogl_context_fill (void *abstract_cr)
cr->y,
cr->width,
cr->height,
&cr->base.gstate->ctm,
&ctm,
cr->base.gstate->clip);
if (status == CAIRO_STATUS_SUCCESS)
goto DONE;
@ -786,6 +801,19 @@ _cairo_cogl_context_fill_preserve (void *abstract_cr)
if (cr->path_is_rectangle) {
if (surface) {
cairo_matrix_t ctm;
status =
_cairo_surface_begin_modification (cr->base.gstate->target);
if (status)
return status;
ctm = cr->base.gstate->ctm;
if (_cairo_surface_is_subsurface (cr->base.gstate->target))
cairo_matrix_translate (&ctm,
((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.x,
((cairo_surface_subsurface_t *)cr->base.gstate->target)->extents.y);
status = _cairo_cogl_surface_fill_rectangle ((cairo_surface_t *)surface,
cr->base.gstate->op,
cr->base.gstate->source,
@ -793,7 +821,7 @@ _cairo_cogl_context_fill_preserve (void *abstract_cr)
cr->y,
cr->width,
cr->height,
&cr->base.gstate->ctm,
&ctm,
cr->base.gstate->clip);
if (status == CAIRO_STATUS_SUCCESS)
goto DONE;

View file

@ -67,15 +67,15 @@ typedef struct _cairo_cogl_linear_gradient {
} cairo_cogl_linear_gradient_t;
cairo_int_status_t
_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *context,
cairo_extend_t extend_mode,
int n_stops,
const cairo_gradient_stop_t *stops,
_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *context,
cairo_extend_t extend_mode,
int n_stops,
const cairo_gradient_stop_t *stops,
cairo_cogl_linear_gradient_t **gradient_out);
cairo_cogl_linear_texture_entry_t *
_cairo_cogl_linear_gradient_texture_for_extend (cairo_cogl_linear_gradient_t *gradient,
cairo_extend_t extend_mode);
cairo_extend_t extend_mode);
cairo_cogl_linear_gradient_t *
_cairo_cogl_linear_gradient_reference (cairo_cogl_linear_gradient_t *gradient);

View file

@ -48,7 +48,7 @@ _cairo_cogl_linear_gradient_hash (unsigned int n_stops,
}
static cairo_cogl_linear_gradient_t *
_cairo_cogl_linear_gradient_lookup (cairo_cogl_device_t *ctx,
_cairo_cogl_linear_gradient_lookup (cairo_cogl_device_t *ctx,
unsigned long hash,
unsigned int n_stops,
const cairo_gradient_stop_t *stops)
@ -116,7 +116,8 @@ _cairo_cogl_util_next_p2 (int a)
}
static float
get_max_color_component_range (const cairo_color_stop_t *color0, const cairo_color_stop_t *color1)
get_max_color_component_range (const cairo_color_stop_t *color0,
const cairo_color_stop_t *color1)
{
float range;
float max = 0;
@ -198,7 +199,7 @@ _cairo_cogl_linear_gradient_width_for_stops (cairo_extend_t extend,
/* Aim to create gradient textures without an alpha component so we can avoid
* needing to use blending... */
static CoglTextureComponents
_cairo_cogl_linear_gradient_components_for_stops (cairo_extend_t extend,
_cairo_cogl_linear_gradient_components_for_stops (cairo_extend_t extend,
unsigned int n_stops,
const cairo_gradient_stop_t *stops)
{
@ -238,7 +239,7 @@ _cairo_cogl_compatibility_from_extend_mode (cairo_extend_t extend_mode)
cairo_cogl_linear_texture_entry_t *
_cairo_cogl_linear_gradient_texture_for_extend (cairo_cogl_linear_gradient_t *gradient,
cairo_extend_t extend_mode)
cairo_extend_t extend_mode)
{
GList *l;
cairo_cogl_gradient_compatibility_t compatibility =
@ -351,10 +352,10 @@ dump_gradient_to_png (CoglTexture *texture)
#endif
cairo_int_status_t
_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *device,
cairo_extend_t extend_mode,
int n_stops,
const cairo_gradient_stop_t *stops,
_cairo_cogl_get_linear_gradient (cairo_cogl_device_t *device,
cairo_extend_t extend_mode,
int n_stops,
const cairo_gradient_stop_t *stops,
cairo_cogl_linear_gradient_t **gradient_out)
{
unsigned long hash;
@ -411,8 +412,9 @@ _cairo_cogl_get_linear_gradient (cairo_cogl_device_t *device,
gradient->n_stops = n_stops;
gradient->stops = gradient->stops_embedded;
memcpy (gradient->stops_embedded, stops, sizeof (cairo_gradient_stop_t) * n_stops);
} else
} else {
_cairo_cogl_linear_gradient_reference (gradient);
}
entry = _cairo_malloc (sizeof (cairo_cogl_linear_texture_entry_t));
if (!entry) {

View file

@ -61,7 +61,7 @@ typedef struct _cairo_cogl_device {
CoglContext *cogl_context;
CoglTexture *dummy_texture;
cairo_bool_t has_npots, has_mirrored_repeat;
CoglAttributeBuffer *buffer_stack;
size_t buffer_stack_size;
@ -83,8 +83,6 @@ typedef struct _cairo_cogl_device {
*/
CoglPipeline *template_pipelines[CAIRO_OPERATOR_ADD + 1][CAIRO_COGL_TEMPLATE_TYPE_COUNT];
CoglMatrix identity;
/* Caches 1d linear gradient textures */
cairo_cache_t linear_cache;

File diff suppressed because it is too large Load diff

View file

@ -37,8 +37,8 @@
CoglPath *
_cairo_cogl_util_path_from_cairo (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
float tolerance);
cairo_fill_rule_t fill_rule,
float tolerance);
int
_cairo_cogl_util_next_p2 (int a);

View file

@ -80,8 +80,8 @@ _cogl_close_path (void *closure)
CoglPath *
_cairo_cogl_util_path_from_cairo (const cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
float tolerance)
cairo_fill_rule_t fill_rule,
float tolerance)
{
CoglPath *cogl_path = cogl_path_new ();
cairo_status_t status;

View file

@ -48,7 +48,7 @@ cairo_public cairo_device_t *
cairo_cogl_device_create (CoglContext *context);
cairo_public cairo_surface_t *
cairo_cogl_surface_create (cairo_device_t *device,
cairo_cogl_surface_create (cairo_device_t *device,
CoglFramebuffer *framebuffer);
cairo_public CoglFramebuffer *