static cairo_int_status_t set_clip_region (cairo_composite_rectangles_t *extents) { cairo_image_surface_t *dst = (cairo_image_surface_t *) extents->surface; cairo_region_t *region = _cairo_clip_get_region (extents->clip); pixman_region32_t *rgn = region ? ®ion->rgn : NULL; if (! pixman_image_set_clip_region32 (dst->pixman_image, rgn)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); return CAIRO_STATUS_SUCCESS; }
static cairo_int_status_t _cairo_qt_surface_set_clip (cairo_qt_surface_t *qs, const cairo_clip_t *clip) { cairo_int_status_t status; D(fprintf(stderr, "q[%p] intersect_clip_path %s\n", abstract_surface, path ? "(path)" : "(clear)")); if (clip == NULL) { _cairo_surface_clipper_reset (&qs->clipper); // How the clip path is reset depends on whether we own p or not if (qs->pixmap || qs->image) { // we own p qs->p->setClipping (false); } else { qs->p->restore (); qs->p->save (); } return CAIRO_INT_STATUS_SUCCESS; } #if ENABLE_FAST_CLIP // Qt will implicitly enable clipping, and will use ReplaceClip // instead of IntersectClip if clipping was disabled before // Note: Qt is really bad at dealing with clip paths. It doesn't // seem to usefully recognize rectangular paths, instead going down // extremely slow paths whenever a clip path is set. So, // we do a bunch of work here to try to get rectangles or regions // down to Qt for clipping. cairo_region_t *clip_region = NULL; status = _cairo_clip_get_region (clip, &clip_region); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { // We weren't able to extract a region from the traps. // Just hand the path down to QPainter. status = (cairo_int_status_t) _cairo_surface_clipper_set_clip (&qs->clipper, clip); } else if (status == CAIRO_INT_STATUS_SUCCESS) { _cairo_qt_surface_set_clip_region (qs, clip_region); status = CAIRO_INT_STATUS_SUCCESS; } #else status = (cairo_int_status_t) _cairo_surface_clipper_set_clip (&qs->clipper, clip); #endif return status; }
cairo_status_t _cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface, cairo_clip_t *clip) { char stack[512]; cairo_rectangle_int_t extents; int num_rects; RGNDATA *data; size_t data_size; RECT *rects; int i; HRGN gdi_region; cairo_status_t status; cairo_region_t *region; /* The semantics we want is that any clip set by cairo combines * is intersected with the clip on device context that the * surface was created for. To implement this, we need to * save the original clip when first setting a clip on surface. */ assert (_cairo_clip_is_region (clip)); region = _cairo_clip_get_region (clip); if (region == NULL) return CAIRO_STATUS_SUCCESS; cairo_region_get_extents (region, &extents); num_rects = cairo_region_num_rectangles (region); /* XXX see notes in _cairo_win32_save_initial_clip -- * this code will interact badly with a HDC which had an initial * world transform -- we should probably manually transform the * region rects, because SelectClipRgn takes device units, not * logical units (unlike IntersectClipRect). */ data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT); if (data_size > sizeof (stack)) { data = malloc (data_size); if (!data) return _cairo_error(CAIRO_STATUS_NO_MEMORY); } else data = (RGNDATA *)stack; data->rdh.dwSize = sizeof (RGNDATAHEADER); data->rdh.iType = RDH_RECTANGLES; data->rdh.nCount = num_rects; data->rdh.nRgnSize = num_rects * sizeof (RECT); data->rdh.rcBound.left = extents.x; data->rdh.rcBound.top = extents.y; data->rdh.rcBound.right = extents.x + extents.width; data->rdh.rcBound.bottom = extents.y + extents.height; rects = (RECT *)data->Buffer; for (i = 0; i < num_rects; i++) { cairo_rectangle_int_t rect; cairo_region_get_rectangle (region, i, &rect); rects[i].left = rect.x; rects[i].top = rect.y; rects[i].right = rect.x + rect.width; rects[i].bottom = rect.y + rect.height; } gdi_region = ExtCreateRegion (NULL, data_size, data); if ((char *)data != stack) free (data); if (!gdi_region) return _cairo_error (CAIRO_STATUS_NO_MEMORY); /* AND the new region into our DC */ status = CAIRO_STATUS_SUCCESS; if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR) status = _cairo_win32_print_gdi_error (__FUNCTION__); DeleteObject (gdi_region); return status; }
cairo_span_renderer_t * _cairo_gl_surface_create_span_renderer (cairo_operator_t op, const cairo_pattern_t *src, void *abstract_dst, cairo_antialias_t antialias, const cairo_composite_rectangles_t *rects) { cairo_gl_surface_t *dst = abstract_dst; cairo_gl_surface_span_renderer_t *renderer; cairo_status_t status; const cairo_rectangle_int_t *extents; status = _cairo_gl_surface_deferred_clear (dst); if (unlikely (status)) return _cairo_span_renderer_create_in_error (status); renderer = calloc (1, sizeof (*renderer)); if (unlikely (renderer == NULL)) return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY); renderer->base.destroy = _cairo_gl_surface_span_renderer_destroy; if (rects->is_bounded) { renderer->base.render_rows = _cairo_gl_render_bounded_spans; renderer->base.finish = _cairo_gl_finish_bounded_spans; extents = &rects->bounded; } else { renderer->base.render_rows = _cairo_gl_render_unbounded_spans; renderer->base.finish = _cairo_gl_finish_unbounded_spans; extents = &rects->unbounded; } renderer->xmin = extents->x; renderer->xmax = extents->x + extents->width; renderer->ymin = extents->y; renderer->ymax = extents->y + extents->height; status = _cairo_gl_composite_init (&renderer->setup, op, dst, FALSE, extents); if (unlikely (status)) goto FAIL; status = _cairo_gl_composite_set_source (&renderer->setup, src, extents->x, extents->y, extents->x, extents->y, extents->width, extents->height); if (unlikely (status)) goto FAIL; _cairo_gl_composite_set_spans (&renderer->setup); _cairo_gl_composite_set_clip_region (&renderer->setup, _cairo_clip_get_region (rects->clip)); status = _cairo_gl_composite_begin (&renderer->setup, &renderer->ctx); if (unlikely (status)) goto FAIL; return &renderer->base; FAIL: _cairo_gl_composite_fini (&renderer->setup); free (renderer); return _cairo_span_renderer_create_in_error (status); }
static cairo_status_t i965_spans_init (i965_spans_t *spans, i965_surface_t *dst, cairo_operator_t op, const cairo_pattern_t *pattern, cairo_antialias_t antialias, cairo_clip_t *clip, const cairo_composite_rectangles_t *extents) { cairo_status_t status; spans->device = i965_device (dst); i965_shader_init (&spans->shader, dst, op); spans->is_bounded = extents->is_bounded; if (extents->is_bounded) { if (antialias == CAIRO_ANTIALIAS_NONE) spans->renderer.render_rows = i965_bounded_spans_mono; else spans->renderer.render_rows = i965_bounded_spans; spans->extents = &extents->bounded; } else { if (antialias == CAIRO_ANTIALIAS_NONE) spans->renderer.render_rows = i965_unbounded_spans_mono; else spans->renderer.render_rows = i965_unbounded_spans; spans->extents = &extents->unbounded; } spans->xmin = spans->extents->x; spans->xmax = spans->extents->x + spans->extents->width; spans->clip_region = NULL; if (clip != NULL) { cairo_region_t *clip_region = NULL; status = _cairo_clip_get_region (clip, &clip_region); assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) clip_region = NULL; spans->clip_region = clip_region; if (status == CAIRO_INT_STATUS_UNSUPPORTED) i965_shader_set_clip (&spans->shader, clip); } spans->head.next = NULL; spans->head.bo = NULL; spans->head.count = 0; spans->tail = &spans->head; if (spans->clip_region == NULL) { spans->get_rectangle = i965_spans_emit_rectangle; } else { spans->get_rectangle = i965_spans_accumulate_rectangle; spans->head.bo = intel_bo_create (&spans->device->intel, I965_VERTEX_SIZE, I965_VERTEX_SIZE, FALSE, I915_TILING_NONE, 0); if (unlikely (spans->head.bo == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); spans->vbo_base = intel_bo_map (&spans->device->intel, spans->head.bo); } spans->vbo_offset = 0; return i965_shader_acquire_pattern (&spans->shader, &spans->shader.source, pattern, &extents->bounded); }
cairo_int_status_t _cairo_gl_surface_show_glyphs (void *abstract_dst, cairo_operator_t op, const cairo_pattern_t *source, cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, cairo_clip_t *clip, int *remaining_glyphs) { cairo_gl_surface_t *dst = abstract_dst; cairo_rectangle_int_t surface_extents; cairo_rectangle_int_t extents; cairo_region_t *clip_region = NULL; cairo_solid_pattern_t solid_pattern; cairo_bool_t overlap, use_mask = FALSE; cairo_status_t status; if (! GLEW_ARB_vertex_buffer_object) return UNSUPPORTED ("requires ARB_vertex_buffer_object"); if (! _cairo_gl_operator_is_supported (op)) return UNSUPPORTED ("unsupported operator"); if (! _cairo_operator_bounded_by_mask (op)) use_mask |= TRUE; /* For CLEAR, cairo's rendering equation (quoting Owen's description in: * http://lists.cairographics.org/archives/cairo/2005-August/004992.html) * is: * mask IN clip ? src OP dest : dest * or more simply: * mask IN CLIP ? 0 : dest * * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C). * * The model we use in _cairo_gl_set_operator() is Render's: * src IN mask IN clip OP dest * which would boil down to: * 0 (bounded by the extents of the drawing). * * However, we can do a Render operation using an opaque source * and DEST_OUT to produce: * 1 IN mask IN clip DEST_OUT dest * which is * mask IN clip ? 0 : dest */ if (op == CAIRO_OPERATOR_CLEAR) { _cairo_pattern_init_solid (&solid_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR); source = &solid_pattern.base; op = CAIRO_OPERATOR_DEST_OUT; } /* For SOURCE, cairo's rendering equation is: * (mask IN clip) ? src OP dest : dest * or more simply: * (mask IN clip) ? src : dest. * * If we just used the Render equation, we would get: * (src IN mask IN clip) OP dest * or: * (src IN mask IN clip) bounded by extents of the drawing. * * The trick is that for GL blending, we only get our 4 source values * into the blender, and since we need all 4 components of source, we * can't also get the mask IN clip into the blender. But if we did * two passes we could make it work: * dest = (mask IN clip) DEST_OUT dest * dest = src IN mask IN clip ADD dest * * But for now, composite via an intermediate mask. */ if (op == CAIRO_OPERATOR_SOURCE) use_mask |= TRUE; /* XXX we don't need ownership of the font as we use a global * glyph cache -- but we do need scaled_glyph eviction notification. :-( */ if (! _cairo_gl_surface_owns_font (dst, scaled_font)) return UNSUPPORTED ("do not control font"); /* If the glyphs overlap, we need to build an intermediate mask rather * then perform the compositing directly. */ status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, &extents, &overlap); if (unlikely (status)) return status; use_mask |= overlap; if (clip != NULL) { status = _cairo_clip_get_region (clip, &clip_region); /* the empty clip should never be propagated this far */ assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO); if (unlikely (_cairo_status_is_error (status))) return status; use_mask |= status == CAIRO_INT_STATUS_UNSUPPORTED; if (! _cairo_rectangle_intersect (&extents, _cairo_clip_get_extents (clip))) goto EMPTY; } surface_extents.x = surface_extents.y = 0; surface_extents.width = dst->width; surface_extents.height = dst->height; if (! _cairo_rectangle_intersect (&extents, &surface_extents)) goto EMPTY; if (use_mask) { return _cairo_gl_surface_show_glyphs_via_mask (dst, op, source, glyphs, num_glyphs, &extents, scaled_font, clip, remaining_glyphs); } return _render_glyphs (dst, extents.x, extents.y, op, source, glyphs, num_glyphs, &extents, scaled_font, clip_region, remaining_glyphs); EMPTY: *remaining_glyphs = 0; if (! _cairo_operator_bounded_by_mask (op)) return _cairo_surface_paint (&dst->base, op, source, clip); else return CAIRO_STATUS_SUCCESS; }
cairo_rectangle_list_t * _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) { #define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S)) cairo_rectangle_list_t *list; cairo_rectangle_t *rectangles = NULL; cairo_region_t *region = NULL; cairo_int_status_t status; int n_rects = 0; int i; if (clip->all_clipped) goto DONE; if (!clip->path) return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); status = _cairo_clip_get_region (clip, ®ion); if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { goto DONE; } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); } else if (unlikely (status)) { return ERROR_LIST (status); } n_rects = cairo_region_num_rectangles (region); if (n_rects) { rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t)); if (unlikely (rectangles == NULL)) { return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); } for (i = 0; i < n_rects; ++i) { cairo_rectangle_int_t clip_rect; cairo_region_get_rectangle (region, i, &clip_rect); if (! _cairo_clip_int_rect_to_user (gstate, &clip_rect, &rectangles[i])) { free (rectangles); return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); } } } DONE: list = malloc (sizeof (cairo_rectangle_list_t)); if (unlikely (list == NULL)) { free (rectangles); return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); } list->status = CAIRO_STATUS_SUCCESS; list->rectangles = rectangles; list->num_rectangles = n_rects; return list; #undef ERROR_LIST }
cairo_int_status_t i965_surface_glyphs (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_glyph_t *g, int num_glyphs, cairo_scaled_font_t *scaled_font, cairo_clip_t *clip, int *num_remaining) { i965_surface_t *surface = abstract_surface; i965_surface_t *mask = NULL; i965_device_t *device; i965_glyphs_t glyphs; cairo_composite_rectangles_t extents; cairo_clip_t local_clip; cairo_bool_t have_clip = FALSE; cairo_bool_t overlap; cairo_region_t *clip_region = NULL; intel_bo_t *last_bo = NULL; cairo_scaled_glyph_t *glyph_cache[64]; cairo_status_t status; int mask_x = 0, mask_y = 0; int i = 0; *num_remaining = 0; status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface->intel.drm.width, surface->intel.drm.height, op, source, scaled_font, g, num_glyphs, clip, &overlap); if (unlikely (status)) return status; if (clip != NULL && _cairo_clip_contains_rectangle (clip, &extents.mask)) clip = NULL; if (clip != NULL && extents.is_bounded) { clip = _cairo_clip_init_copy (&local_clip, clip); status = _cairo_clip_rectangle (clip, &extents.bounded); if (unlikely (status)) return status; have_clip = TRUE; } if (overlap || ! extents.is_bounded) { cairo_format_t format; format = CAIRO_FORMAT_A8; if (scaled_font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL) format = CAIRO_FORMAT_ARGB32; mask = (i965_surface_t *) i965_surface_create_internal (&i965_device (surface)->intel.base, format, extents.bounded.width, extents.bounded.height, I965_TILING_DEFAULT, TRUE); if (unlikely (mask->intel.drm.base.status)) return mask->intel.drm.base.status; status = _cairo_surface_paint (&mask->intel.drm.base, CAIRO_OPERATOR_CLEAR, &_cairo_pattern_clear.base, NULL); if (unlikely (status)) { cairo_surface_destroy (&mask->intel.drm.base); return status; } i965_shader_init (&glyphs.shader, mask, CAIRO_OPERATOR_ADD); status = i965_shader_acquire_pattern (&glyphs.shader, &glyphs.shader.source, &_cairo_pattern_white.base, &extents.bounded); if (unlikely (status)) { cairo_surface_destroy (&mask->intel.drm.base); return status; } mask_x = -extents.bounded.x; mask_y = -extents.bounded.y; } else { i965_shader_init (&glyphs.shader, surface, op); status = i965_shader_acquire_pattern (&glyphs.shader, &glyphs.shader.source, source, &extents.bounded); if (unlikely (status)) return status; if (clip != NULL) { status = _cairo_clip_get_region (clip, &clip_region); assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); if (status == CAIRO_INT_STATUS_UNSUPPORTED) i965_shader_set_clip (&glyphs.shader, clip); } } glyphs.head.next = NULL; glyphs.head.bo = NULL; glyphs.head.count = 0; glyphs.tail = &glyphs.head; device = i965_device (surface); if (mask != NULL || clip_region == NULL) { glyphs.get_rectangle = i965_glyphs_emit_rectangle; } else { glyphs.get_rectangle = i965_glyphs_accumulate_rectangle; glyphs.head.bo = intel_bo_create (&device->intel, I965_VERTEX_SIZE, I965_VERTEX_SIZE, FALSE, I915_TILING_NONE, 0); if (unlikely (glyphs.head.bo == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); glyphs.vbo_base = intel_bo_map (&device->intel, glyphs.head.bo); } glyphs.vbo_offset = 0; status = cairo_device_acquire (&device->intel.base.base); if (unlikely (status)) goto CLEANUP_GLYPHS; _cairo_scaled_font_freeze_cache (scaled_font); //private = _cairo_scaled_font_get_device (scaled_font, device); if (scaled_font->surface_private == NULL) { scaled_font->surface_private = device; scaled_font->surface_backend = surface->intel.drm.base.backend; cairo_list_add (&scaled_font->link, &device->intel.fonts); } memset (glyph_cache, 0, sizeof (glyph_cache)); for (i = 0; i < num_glyphs; i++) { cairo_scaled_glyph_t *scaled_glyph; int x, y, x1, x2, y1, y2; int cache_index = g[i].index % ARRAY_LENGTH (glyph_cache); intel_glyph_t *glyph; scaled_glyph = glyph_cache[cache_index]; if (scaled_glyph == NULL || _cairo_scaled_glyph_index (scaled_glyph) != g[i].index) { status = _cairo_scaled_glyph_lookup (scaled_font, g[i].index, CAIRO_SCALED_GLYPH_INFO_METRICS, &scaled_glyph); if (unlikely (status)) goto FINISH; glyph_cache[cache_index] = scaled_glyph; } if (unlikely (scaled_glyph->metrics.width == 0 || scaled_glyph->metrics.height == 0)) { continue; } /* XXX glyph images are snapped to pixel locations */ x = _cairo_lround (g[i].x); y = _cairo_lround (g[i].y); x1 = x + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); y1 = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); x2 = x + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); y2 = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); if (x2 < extents.bounded.x || y2 < extents.bounded.y || x1 > extents.bounded.x + extents.bounded.width || y1 > extents.bounded.y + extents.bounded.height) { continue; } if (scaled_glyph->surface_private == NULL) { status = intel_get_glyph (&device->intel, scaled_font, scaled_glyph); if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO)) { status = CAIRO_STATUS_SUCCESS; continue; } if (unlikely (status)) goto FINISH; } glyph = intel_glyph_pin (scaled_glyph->surface_private); if (glyph->cache->buffer.bo != last_bo) { intel_buffer_cache_t *cache = glyph->cache; glyphs.shader.mask.type.vertex = VS_GLYPHS; glyphs.shader.mask.type.fragment = FS_GLYPHS; glyphs.shader.mask.type.pattern = PATTERN_BASE; glyphs.shader.mask.base.bo = cache->buffer.bo; glyphs.shader.mask.base.format = cache->buffer.format; glyphs.shader.mask.base.width = cache->buffer.width; glyphs.shader.mask.base.height = cache->buffer.height; glyphs.shader.mask.base.stride = cache->buffer.stride; glyphs.shader.mask.base.filter = i965_filter (CAIRO_FILTER_NEAREST); glyphs.shader.mask.base.extend = i965_extend (CAIRO_EXTEND_NONE); glyphs.shader.mask.base.content = CAIRO_CONTENT_ALPHA; /* XXX */ glyphs.shader.committed = FALSE; status = i965_shader_commit (&glyphs.shader, device); if (unlikely (status)) goto FINISH; last_bo = cache->buffer.bo; } x2 = x1 + glyph->width; y2 = y1 + glyph->height; if (mask_x) x1 += mask_x, x2 += mask_x; if (mask_y) y1 += mask_y, y2 += mask_y; i965_add_glyph_rectangle (&glyphs, x1, y1, x2, y2, glyph); } if (mask != NULL && clip_region != NULL) i965_clipped_vertices (device, &glyphs.head, clip_region); status = CAIRO_STATUS_SUCCESS; FINISH: _cairo_scaled_font_thaw_cache (scaled_font); cairo_device_release (surface->intel.drm.base.device); CLEANUP_GLYPHS: i965_shader_fini (&glyphs.shader); if (glyphs.head.bo != NULL) { struct i965_vbo *vbo, *next; intel_bo_destroy (&device->intel, glyphs.head.bo); for (vbo = glyphs.head.next; vbo != NULL; vbo = next) { next = vbo->next; intel_bo_destroy (&device->intel, vbo->bo); free (vbo); } } if (unlikely (status == CAIRO_INT_STATUS_UNSUPPORTED)) { cairo_path_fixed_t path; _cairo_path_fixed_init (&path); status = _cairo_scaled_font_glyph_path (scaled_font, g + i, num_glyphs - i, &path); if (mask_x | mask_y) { _cairo_path_fixed_translate (&path, _cairo_fixed_from_int (mask_x), _cairo_fixed_from_int (mask_y)); } if (likely (status == CAIRO_STATUS_SUCCESS)) { status = surface->intel.drm.base.backend->fill (glyphs.shader.target, glyphs.shader.op, mask != NULL ? &_cairo_pattern_white.base : source, &path, CAIRO_FILL_RULE_WINDING, 0, scaled_font->options.antialias, clip); } _cairo_path_fixed_fini (&path); } if (mask != NULL) { if (likely (status == CAIRO_STATUS_SUCCESS)) { status = i965_surface_mask_internal (surface, op, source, mask, clip, &extents); } cairo_surface_finish (&mask->intel.drm.base); cairo_surface_destroy (&mask->intel.drm.base); } if (have_clip) _cairo_clip_fini (&local_clip); return status; }
static cairo_status_t i965_surface_mask_internal (i965_surface_t *dst, cairo_operator_t op, const cairo_pattern_t *source, i965_surface_t *mask, cairo_clip_t *clip, const cairo_composite_rectangles_t *extents) { i965_device_t *device; i965_shader_t shader; cairo_region_t *clip_region = NULL; cairo_status_t status; i965_shader_init (&shader, dst, op); status = i965_shader_acquire_pattern (&shader, &shader.source, source, &extents->bounded); if (unlikely (status)) return status; shader.mask.type.vertex = VS_NONE; shader.mask.type.fragment = FS_SURFACE; shader.mask.base.content = mask->intel.drm.base.content; shader.mask.base.filter = i965_filter (CAIRO_FILTER_NEAREST); shader.mask.base.extend = i965_extend (CAIRO_EXTEND_NONE); cairo_matrix_init_translate (&shader.mask.base.matrix, -extents->bounded.x, -extents->bounded.y); cairo_matrix_scale (&shader.mask.base.matrix, 1. / mask->intel.drm.width, 1. / mask->intel.drm.height); shader.mask.base.bo = to_intel_bo (mask->intel.drm.bo); shader.mask.base.format = mask->intel.drm.format; shader.mask.base.width = mask->intel.drm.width; shader.mask.base.height = mask->intel.drm.height; shader.mask.base.stride = mask->intel.drm.stride; if (clip != NULL) { status = _cairo_clip_get_region (clip, &clip_region); assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED); if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) clip_region = NULL; if (status == CAIRO_INT_STATUS_UNSUPPORTED) i965_shader_set_clip (&shader, clip); } status = cairo_device_acquire (dst->intel.drm.base.device); if (unlikely (status)) goto CLEANUP_SHADER; device = i965_device (dst); status = i965_shader_commit (&shader, device); if (unlikely (status)) goto CLEANUP_DEVICE; if (clip_region != NULL) { unsigned int n, num_rectangles; num_rectangles = cairo_region_num_rectangles (clip_region); for (n = 0; n < num_rectangles; n++) { cairo_rectangle_int_t rect; cairo_region_get_rectangle (clip_region, n, &rect); i965_shader_add_rectangle (&shader, rect.x, rect.y, rect.width, rect.height); } } else { i965_shader_add_rectangle (&shader, extents->bounded.x, extents->bounded.y, extents->bounded.width, extents->bounded.height); } if (! extents->is_bounded) status = i965_fixup_unbounded (dst, extents, clip); CLEANUP_DEVICE: cairo_device_release (&device->intel.base.base); CLEANUP_SHADER: i965_shader_fini (&shader); return status; }