third_party/cairo/src/cairo-cogl-surface.c
static CoglTexture *
_cairo_cogl_acquire_cogl_surface_texture (cairo_cogl_surface_t        *reference_surface,
                                          cairo_surface_t             *surface,
                                          const cairo_rectangle_int_t *surface_extents,
                                          const cairo_matrix_t        *pattern_matrix,
                                          cairo_matrix_t              *out_matrix,
                                          const cairo_bool_t           need_mirrored_texture,
                                          cairo_bool_t                *is_mirrored_texture)
{
    CoglTexture *texture;
    cairo_surface_t *clone = NULL;
    cairo_cogl_surface_t *cogl_surface =
        (cairo_cogl_surface_t *)surface;
    cairo_bool_t do_mirror_texture;
    cairo_cogl_device_t *dev =
        to_device (reference_surface->base.device);
    double xscale, yscale;
    int new_width = surface_extents->width;
    int new_height = surface_extents->height;

    if (surface_extents->x < 0 || surface_extents->y < 0 ||
        (surface_extents->x + surface_extents->width) >
            cogl_surface->width ||
        (surface_extents->y + surface_extents->height) >
            cogl_surface->height)
        return NULL;

    *out_matrix = *pattern_matrix;
    *is_mirrored_texture = FALSE;

    if (unlikely (_cairo_surface_flush (surface, 0))) {
        g_warning ("Error flushing source surface while getting "
                   "pattern texture");
        goto BAIL;
    }

    *is_mirrored_texture =
        need_mirrored_texture || cogl_surface->is_mirrored_snapshot;
    do_mirror_texture =
        need_mirrored_texture && !cogl_surface->is_mirrored_snapshot;

    /* There seems to be a bug in which cogl isn't flushing its own
     * internal journal when reading from dependent sub-textures.
     * If this is ever fixed, the following block of code can be
     * removed. */
    {
        _cairo_cogl_surface_ensure_framebuffer (cogl_surface);
        cogl_framebuffer_finish (cogl_surface->framebuffer);
    }
    /* We copy the surface to a new texture, thereby making a
     * snapshot of it, as its contents may change between the time
     * we log the pipeline and when we flush the journal. The sub
     * texture itself cannot be used while drawing primitives, so we do
     * a copy to a 2d texture. */
    texture = cogl_sub_texture_new (dev->cogl_context,
                                    cogl_surface->texture,
                                    surface_extents->x,
                                    surface_extents->y,
                                    surface_extents->width,
                                    surface_extents->height);
    if (unlikely (!texture))
        goto BAIL;

    /* If we do not support NPOT dimensions, scale the new texture to
     * the next power of two while copying */
    if (!dev->has_npots) {
        new_width = (int)pow (2, ceil (log2 (new_width)));
        new_height = (int)pow (2, ceil (log2 (new_height)));
    }
    texture = _cairo_cogl_scale_texture (dev->cogl_context,
                                         texture,
                                         new_width,
                                         new_height,
                                         do_mirror_texture,
                                         TRUE);
    if (unlikely (!texture))
        goto BAIL;

    clone =
        _cairo_cogl_surface_create_full (dev,
                                         reference_surface->base.content,
                                         NULL,
                                         texture);
    if (unlikely (clone->status)) {
        g_warning ("Could not get clone surface for texture");
        goto BAIL;
    }
    _cairo_surface_attach_snapshot (surface, clone, NULL);

    /* Attaching the snapshot will take a reference on the clone surface... */
    cairo_surface_destroy (clone);
    clone = NULL;

    /* Convert from un-normalized source coordinates in backend
     * coordinates to normalized texture coordinates. */
    if (*is_mirrored_texture) {
        xscale = 0.5 / surface_extents->width;
        yscale = 0.5 / surface_extents->height;
    } else {
        xscale = 1.0 / surface_extents->width;
        yscale = 1.0 / surface_extents->height;
    }
    _cairo_cogl_matrix_all_scale (out_matrix, xscale, yscale);

    return texture;

BAIL:
    if (texture)
        cogl_object_unref (texture);
    if (clone)
        cairo_surface_destroy (clone);

    return NULL;
}
/* NB: a reference for the texture is transferred to the caller which
 * should be unrefed */
a reference for the texture is transferred to the caller which
should be unrefed
a reference for the texture is transferred to the caller which should be unrefed
static CoglTexture *
_cairo_cogl_acquire_cogl_surface_texture (cairo_cogl_surface_t        *reference_surface,
                                          cairo_surface_t             *surface,
                                          const cairo_rectangle_int_t *surface_extents,
                                          const cairo_matrix_t        *pattern_matrix,
                                          cairo_matrix_t              *out_matrix,
                                          const cairo_bool_t           need_mirrored_texture,
                                          cairo_bool_t                *is_mirrored_texture)
{
    CoglTexture *texture;
    cairo_surface_t *clone = NULL;
    cairo_cogl_surface_t *cogl_surface =
        (cairo_cogl_surface_t *)surface;
    cairo_bool_t do_mirror_texture;
    cairo_cogl_device_t *dev =
        to_device (reference_surface->base.device);
    double xscale, yscale;
    int new_width = surface_extents->width;
    int new_height = surface_extents->height;
    if (surface_extents->x < 0 || surface_extents->y < 0 ||
        (surface_extents->x + surface_extents->width) >
            cogl_surface->width ||
        (surface_extents->y + surface_extents->height) >
            cogl_surface->height)
        return NULL;
    *out_matrix = *pattern_matrix;
    *is_mirrored_texture = FALSE;
    if (unlikely (_cairo_surface_flush (surface, 0))) {
        g_warning ("Error flushing source surface while getting "
                   "pattern texture");
        goto BAIL;
    }
    *is_mirrored_texture =
        need_mirrored_texture || cogl_surface->is_mirrored_snapshot;
    do_mirror_texture =
        need_mirrored_texture && !cogl_surface->is_mirrored_snapshot;
    {
        _cairo_cogl_surface_ensure_framebuffer (cogl_surface);
        cogl_framebuffer_finish (cogl_surface->framebuffer);
    }
    texture = cogl_sub_texture_new (dev->cogl_context,
                                    cogl_surface->texture,
                                    surface_extents->x,
                                    surface_extents->y,
                                    surface_extents->width,
                                    surface_extents->height);
    if (unlikely (!texture))
        goto BAIL;
    if (!dev->has_npots) {
        new_width = (int)pow (2, ceil (log2 (new_width)));
        new_height = (int)pow (2, ceil (log2 (new_height)));
    }
    texture = _cairo_cogl_scale_texture (dev->cogl_context,
                                         texture,
                                         new_width,
                                         new_height,
                                         do_mirror_texture,
                                         TRUE);
    if (unlikely (!texture))
        goto BAIL;
    clone =
        _cairo_cogl_surface_create_full (dev,
                                         reference_surface->base.content,
                                         NULL,
                                         texture);
    if (unlikely (clone->status)) {
        g_warning ("Could not get clone surface for texture");
        goto BAIL;
    }
    _cairo_surface_attach_snapshot (surface, clone, NULL);
    cairo_surface_destroy (clone);
    clone = NULL;
    if (*is_mirrored_texture) {
        xscale = 0.5 / surface_extents->width;
        yscale = 0.5 / surface_extents->height;
    } else {
        xscale = 1.0 / surface_extents->width;
        yscale = 1.0 / surface_extents->height;
    }
    _cairo_cogl_matrix_all_scale (out_matrix, xscale, yscale);
    return texture;
BAIL:
    if (texture)
        cogl_object_unref (texture);
    if (clone)
        cairo_surface_destroy (clone);
    return NULL;
}
static CoglTexture * _cairo_cogl_acquire_cogl_surface_texture ( cairo_cogl_surface_t * reference_surface , cairo_surface_t * surface , const cairo_rectangle_int_t * surface_extents , const cairo_matrix_t * pattern_matrix , cairo_matrix_t * out_matrix , const cairo_bool_t need_mirrored_texture , cairo_bool_t * is_mirrored_texture ) { CoglTexture * texture ; cairo_surface_t * clone = NULL ; cairo_cogl_surface_t * cogl_surface = ( cairo_cogl_surface_t * ) surface ; cairo_bool_t do_mirror_texture ; cairo_cogl_device_t * dev = to_device ( reference_surface -> base . device ) ; double xscale , yscale ; int new_width = surface_extents -> width ; int new_height = surface_extents -> height ; if ( surface_extents -> x < 0 || surface_extents -> y < 0 || ( surface_extents -> x + surface_extents -> width ) > cogl_surface -> width || ( surface_extents -> y + surface_extents -> height ) > cogl_surface -> height ) return NULL ; * out_matrix = * pattern_matrix ; * is_mirrored_texture = FALSE ; if ( unlikely ( _cairo_surface_flush ( surface , 0 ) ) ) { g_warning ( " " " " ) ; goto BAIL ; } * is_mirrored_texture = need_mirrored_texture || cogl_surface -> is_mirrored_snapshot ; do_mirror_texture = need_mirrored_texture && ! cogl_surface -> is_mirrored_snapshot ; { _cairo_cogl_surface_ensure_framebuffer ( cogl_surface ) ; cogl_framebuffer_finish ( cogl_surface -> framebuffer ) ; } texture = cogl_sub_texture_new ( dev -> cogl_context , cogl_surface -> texture , surface_extents -> x , surface_extents -> y , surface_extents -> width , surface_extents -> height ) ; if ( unlikely ( ! texture ) ) goto BAIL ; if ( ! dev -> has_npots ) { new_width = ( int ) pow ( 2 , ceil ( log2 ( new_width ) ) ) ; new_height = ( int ) pow ( 2 , ceil ( log2 ( new_height ) ) ) ; } texture = _cairo_cogl_scale_texture ( dev -> cogl_context , texture , new_width , new_height , do_mirror_texture , TRUE ) ; if ( unlikely ( ! texture ) ) goto BAIL ; clone = _cairo_cogl_surface_create_full ( dev , reference_surface -> base . content , NULL , texture ) ; if ( unlikely ( clone -> status ) ) { g_warning ( " " ) ; goto BAIL ; } _cairo_surface_attach_snapshot ( surface , clone , NULL ) ; cairo_surface_destroy ( clone ) ; clone = NULL ; if ( * is_mirrored_texture ) { xscale = 0.5 / surface_extents -> width ; yscale = 0.5 / surface_extents -> height ; } else { xscale = 1.0 / surface_extents -> width ; yscale = 1.0 / surface_extents -> height ; } _cairo_cogl_matrix_all_scale ( out_matrix , xscale , yscale ) ; return texture ; BAIL : if ( texture ) cogl_object_unref ( texture ) ; if ( clone ) cairo_surface_destroy ( clone ) ; return NULL ; }
NB: a reference for the texture is transferred to the caller which
 should be unrefed
NB : a reference for the texture is transferred to the caller which should be unrefed
/* There seems to be a bug in which cogl isn't flushing its own
     * internal journal when reading from dependent sub-textures.
     * If this is ever fixed, the following block of code can be
     * removed. */ /* We copy the surface to a new texture, thereby making a
     * snapshot of it, as its contents may change between the time
     * we log the pipeline and when we flush the journal. The sub
     * texture itself cannot be used while drawing primitives, so we do
     * a copy to a 2d texture. */ /* If we do not support NPOT dimensions, scale the new texture to
     * the next power of two while copying */ /* Attaching the snapshot will take a reference on the clone surface... */ /* Convert from un-normalized source coordinates in backend
     * coordinates to normalized texture coordinates. */