static cairo_status_t _cairo_xcb_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { cairo_xcb_surface_t *surface = abstract_surface; cairo_surface_t *image; if (surface->fallback != NULL) { image = cairo_surface_reference (&surface->fallback->base); goto DONE; } image = _cairo_surface_has_snapshot (&surface->base, &_cairo_image_surface_backend); if (image != NULL) { image = cairo_surface_reference (image); goto DONE; } image = _get_image (surface, FALSE, 0, 0, surface->width, surface->height); if (unlikely (image->status)) return image->status; _cairo_surface_attach_snapshot (&surface->base, image, NULL); DONE: *image_out = (cairo_image_surface_t *) image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
/** * _cairo_surface_snapshot: * @surface: a #cairo_surface_t * * Make an immutable reference to @surface. It is an error to call a * surface-modifying function on the result of this function. The * resulting 'snapshot' is a lazily copied-on-write surface i.e. it * remains a reference to the original surface until that surface is * written to again, at which time a copy is made of the original surface * and the snapshot then points to that instead. Multiple snapshots of the * same unmodified surface point to the same copy. * * The caller owns the return value and should call * cairo_surface_destroy() when finished with it. This function will not * return %NULL, but will return a nil surface instead. * * Return value: The snapshot surface. Note that the return surface * may not necessarily be of the same type as @surface. **/ cairo_surface_t * _cairo_surface_snapshot (cairo_surface_t *surface) { cairo_surface_snapshot_t *snapshot; cairo_status_t status; TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->unique_id)); if (unlikely (surface->status)) return _cairo_surface_create_in_error (surface->status); if (unlikely (surface->finished)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); if (surface->snapshot_of != NULL) return cairo_surface_reference (surface); if (_cairo_surface_is_snapshot (surface)) return cairo_surface_reference (surface); snapshot = (cairo_surface_snapshot_t *) _cairo_surface_has_snapshot (surface, &_cairo_surface_snapshot_backend); if (snapshot != NULL) return cairo_surface_reference (&snapshot->base); snapshot = malloc (sizeof (cairo_surface_snapshot_t)); if (unlikely (snapshot == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); _cairo_surface_init (&snapshot->base, &_cairo_surface_snapshot_backend, NULL, /* device */ surface->content); snapshot->base.type = surface->type; CAIRO_MUTEX_INIT (snapshot->mutex); snapshot->target = surface; snapshot->clone = NULL; status = _cairo_surface_copy_mime_data (&snapshot->base, surface); if (unlikely (status)) { cairo_surface_destroy (&snapshot->base); return _cairo_surface_create_in_error (status); } snapshot->base.device_transform = surface->device_transform; snapshot->base.device_transform_inverse = surface->device_transform_inverse; _cairo_surface_attach_snapshot (surface, &snapshot->base, _cairo_surface_snapshot_copy_on_write); return &snapshot->base; }
static cairo_surface_t * attach_proxy (cairo_surface_t *source, cairo_surface_t *target) { struct proxy *proxy; proxy = malloc (sizeof (*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); _cairo_surface_init (&proxy->base, &proxy_backend, NULL, target->content, target->is_vector); proxy->target = target; _cairo_surface_attach_snapshot (source, &proxy->base, NULL); return &proxy->base; }
static cairo_status_t _cairo_xcb_surface_flush (void *abstract_surface, unsigned flags) { cairo_xcb_surface_t *surface = abstract_surface; cairo_status_t status; if (flags) return CAIRO_STATUS_SUCCESS; if (likely (surface->fallback == NULL)) { status = CAIRO_STATUS_SUCCESS; if (! surface->base.finished && surface->deferred_clear) status = _cairo_xcb_surface_clear (surface); return status; } status = surface->base.status; if (status == CAIRO_STATUS_SUCCESS && (! surface->base._finishing || ! surface->owns_pixmap)) { status = cairo_surface_status (&surface->fallback->base); if (status == CAIRO_STATUS_SUCCESS) status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage, CAIRO_FILL_RULE_WINDING, &surface->fallback_damage); if (status == CAIRO_STATUS_SUCCESS) status = _put_image_boxes (surface, surface->fallback, &surface->fallback_damage); if (status == CAIRO_STATUS_SUCCESS && ! surface->base._finishing) { _cairo_surface_attach_snapshot (&surface->base, &surface->fallback->base, cairo_surface_finish); } } _cairo_boxes_clear (&surface->fallback_damage); cairo_surface_destroy (&surface->fallback->base); surface->fallback = NULL; return status; }
cairo_status_t intel_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { intel_surface_t *surface = abstract_surface; cairo_surface_t *image; cairo_status_t status; void *ptr; if (surface->drm.fallback != NULL) { image = surface->drm.fallback; goto DONE; } image = _cairo_surface_has_snapshot (&surface->drm.base, &_cairo_image_surface_backend); if (image != NULL) goto DONE; if (surface->drm.base.backend->flush != NULL) { status = surface->drm.base.backend->flush (surface); if (unlikely (status)) return status; } ptr = intel_bo_map (to_intel_device (surface->drm.base.device), to_intel_bo (surface->drm.bo)); if (unlikely (ptr == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); image = cairo_image_surface_create_for_data (ptr, surface->drm.format, surface->drm.width, surface->drm.height, surface->drm.stride); if (unlikely (image->status)) return image->status; _cairo_surface_attach_snapshot (&surface->drm.base, image, surface_finish_and_destroy); DONE: *image_out = (cairo_image_surface_t *) cairo_surface_reference (image); *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
void _cairo_surface_subsurface_set_snapshot (cairo_surface_t *surface, cairo_surface_t *snapshot) { cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface; TRACE ((stderr, "%s: target=%d, snapshot=%d\n", __FUNCTION__, ss->target->unique_id, snapshot->unique_id)); if (ss->snapshot) _cairo_surface_detach_snapshot (ss->snapshot); ss->snapshot = cairo_surface_reference (snapshot); _cairo_surface_attach_snapshot (ss->target, &ss->base, _cairo_surface_subsurface_detach_snapshot); }
static cairo_status_t radeon_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { radeon_surface_t *surface = abstract_surface; cairo_surface_t *image; cairo_status_t status; /* XXX batch flush */ if (surface->base.fallback != NULL) { image = surface->base.fallback; goto DONE; } image = _cairo_surface_has_snapshot (&surface->base.base, &_cairo_image_surface_backend); if (image != NULL) goto DONE; if (surface->base.base.backend->flush != NULL) { status = surface->base.base.backend->flush (surface); if (unlikely (status)) return status; } image = radeon_bo_get_image (to_radeon_device (surface->base.base.device), to_radeon_bo (surface->base.bo), &surface->base); status = image->status; if (unlikely (status)) return status; _cairo_surface_attach_snapshot (&surface->base.base, image, cairo_surface_destroy); DONE: *image_out = (cairo_image_surface_t *) cairo_surface_reference (image); *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_recording_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { cairo_status_t status; cairo_recording_surface_t *surface = abstract_surface; cairo_surface_t *image; image = _cairo_surface_has_snapshot (&surface->base, &_cairo_image_surface_backend); if (image != NULL) { *image_out = (cairo_image_surface_t *) cairo_surface_reference (image); *image_extra = NULL; return CAIRO_STATUS_SUCCESS; } image = _cairo_image_surface_create_with_content (surface->content, surface->extents.width, surface->extents.height); if (unlikely (image->status)) return image->status; cairo_surface_set_device_offset (image, -surface->extents.x, -surface->extents.y); status = _cairo_recording_surface_replay (&surface->base, image); if (unlikely (status)) { cairo_surface_destroy (image); return status; } _cairo_surface_attach_snapshot (&surface->base, image, NULL); *image_out = (cairo_image_surface_t *) image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_xcb_surface_flush (void *abstract_surface) { cairo_xcb_surface_t *surface = abstract_surface; cairo_status_t status; if (surface->drm != NULL && ! surface->marked_dirty) return surface->drm->backend->flush (surface->drm); if (likely (surface->fallback == NULL)) { status = CAIRO_STATUS_SUCCESS; if (! surface->base.finished && surface->deferred_clear) status = _cairo_xcb_surface_clear (surface); return status; } status = surface->base.status; if (status == CAIRO_STATUS_SUCCESS && ! surface->base.finished) { status = cairo_surface_status (surface->fallback); if (status == CAIRO_STATUS_SUCCESS) { status = _put_image (surface, (cairo_image_surface_t *) surface->fallback); } if (status == CAIRO_STATUS_SUCCESS) { _cairo_surface_attach_snapshot (&surface->base, surface->fallback, cairo_surface_finish); } } cairo_surface_destroy (surface->fallback); surface->fallback = NULL; return status; }
static cairo_status_t _cairo_xcb_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra) { cairo_xcb_surface_t *surface = abstract_surface; cairo_image_surface_t *image; cairo_status_t status; if (surface->drm != NULL && ! surface->marked_dirty) { return _cairo_surface_acquire_source_image (surface->drm, image_out, image_extra); } if (surface->fallback != NULL) { image = (cairo_image_surface_t *) cairo_surface_reference (surface->fallback); goto DONE; } image = (cairo_image_surface_t *) _cairo_surface_has_snapshot (&surface->base, &_cairo_image_surface_backend); if (image != NULL) { image = (cairo_image_surface_t *) cairo_surface_reference (&image->base); goto DONE; } status = _get_image (surface, FALSE, &image); if (unlikely (status)) return status; _cairo_surface_attach_snapshot (&surface->base, &image->base, NULL); DONE: *image_out = image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS; }
void _cairo_surface_subsurface_set_snapshot (cairo_surface_t *surface, cairo_surface_t *snapshot) { cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface; TRACE ((stderr, "%s: target=%d, snapshot=%d\n", __FUNCTION__, ss->target->unique_id, snapshot->unique_id)); /* FIXME: attaching the subsurface as a snapshot to its target creates * a reference cycle. Let's make this call as a no-op until that bug * is fixed. */ return; if (ss->snapshot) _cairo_surface_detach_snapshot (ss->snapshot); ss->snapshot = cairo_surface_reference (snapshot); _cairo_surface_attach_snapshot (ss->target, &ss->base, _cairo_surface_subsurface_detach_snapshot); }
/** * _cairo_surface_snapshot * @surface: a #cairo_surface_t * * Make an immutable reference to @surface. It is an error to call a * surface-modifying function on the result of this function. The * resulting 'snapshot' is a lazily copied-on-write surface i.e. it * remains a reference to the original surface until that surface is * written to again, at which time a copy is made of the original surface * and the snapshot then points to that instead. Multiple snapshots of the * same unmodified surface point to the same copy. * * The caller owns the return value and should call * cairo_surface_destroy() when finished with it. This function will not * return %NULL, but will return a nil surface instead. * * Return value: The snapshot surface. Note that the return surface * may not necessarily be of the same type as @surface. **/ cairo_surface_t * _cairo_surface_snapshot (cairo_surface_t *surface) { cairo_surface_snapshot_t *snapshot; cairo_status_t status; if (unlikely (surface->status)) return _cairo_surface_create_in_error (surface->status); if (surface->finished) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); if (surface->snapshot_of != NULL) return cairo_surface_reference (surface); if (surface->backend->snapshot != NULL) { cairo_surface_t *snap; snap = _cairo_surface_has_snapshot (surface, surface->backend); if (snap != NULL) return cairo_surface_reference (snap); snap = surface->backend->snapshot (surface); if (snap != NULL) { if (unlikely (snap->status)) return snap; status = _cairo_surface_copy_mime_data (snap, surface); if (unlikely (status)) { cairo_surface_destroy (snap); return _cairo_surface_create_in_error (status); } snap->device_transform = surface->device_transform; snap->device_transform_inverse = surface->device_transform_inverse; _cairo_surface_attach_snapshot (surface, snap, NULL); return snap; } } snapshot = (cairo_surface_snapshot_t *) _cairo_surface_has_snapshot (surface, &_cairo_surface_snapshot_backend); if (snapshot != NULL) return cairo_surface_reference (&snapshot->base); snapshot = malloc (sizeof (cairo_surface_snapshot_t)); if (unlikely (snapshot == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); _cairo_surface_init (&snapshot->base, &_cairo_surface_snapshot_backend, NULL, /* device */ surface->content); snapshot->base.type = surface->type; snapshot->target = surface; snapshot->clone = NULL; status = _cairo_surface_copy_mime_data (&snapshot->base, surface); if (unlikely (status)) { cairo_surface_destroy (&snapshot->base); return _cairo_surface_create_in_error (status); } snapshot->base.device_transform = surface->device_transform; snapshot->base.device_transform_inverse = surface->device_transform_inverse; _cairo_surface_attach_snapshot (surface, &snapshot->base, _cairo_surface_snapshot_copy_on_write); return &snapshot->base; }
static cairo_xcb_pixmap_t * _cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target, const cairo_surface_pattern_t *pattern, const cairo_rectangle_int_t *extents, int tx, int ty) { cairo_surface_t *source; cairo_xcb_pixmap_t *pixmap; source = pattern->surface; pixmap = (cairo_xcb_pixmap_t *) _cairo_surface_has_snapshot (source, &_cairo_xcb_pixmap_backend); if (pixmap != NULL && pixmap->screen == target->screen) return (cairo_xcb_pixmap_t *) cairo_surface_reference (&pixmap->base); if (source->type == CAIRO_SURFACE_TYPE_XCB && ((cairo_xcb_surface_t *) source)->screen == target->screen) { cairo_xcb_surface_t *xcb_source = (cairo_xcb_surface_t *) source; if (xcb_source->depth == target->depth) pixmap = _copy_to_pixmap (xcb_source); } #if CAIRO_HAS_XLIB_XCB_FUNCTIONS else if (source->type == CAIRO_SURFACE_TYPE_XLIB && ((cairo_xlib_xcb_surface_t *) source)->xcb->screen == target->screen) { cairo_xcb_surface_t *xcb_source = ((cairo_xlib_xcb_surface_t *) source)->xcb; if (xcb_source->depth == target->depth) pixmap = _copy_to_pixmap (xcb_source); } #endif if (pixmap == NULL) { cairo_rectangle_int_t rect; if (! _cairo_surface_get_extents (source, &rect)) { rect.x = rect.y = 0; rect.width = target->width; rect.height = target->height; } pixmap = _render_to_pixmap (target, &pattern->base, &rect); } if (unlikely (pixmap->base.status)) return pixmap; _cairo_surface_attach_snapshot (source, &pixmap->base, NULL); if (pattern->base.extend != CAIRO_EXTEND_NONE) { if (extents->x < 0 || extents->y < 0 || extents->x + extents->width > pixmap->width || extents->y + extents->height > pixmap->height) { pixmap->repeat = TRUE; } } pixmap->x0 += tx; pixmap->y0 += ty; return pixmap; }