1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Intel Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Red Hat, Inc.
33 * Chris Wilson <chris@chris-wilson.co.uk>
38 #include "cairo-composite-rectangles-private.h"
39 #include "cairo-boxes-private.h"
40 #include "cairo-error-private.h"
41 #include "cairo-drm-i965-private.h"
43 /* Operates in either immediate or retained mode.
44 * When given a clip region we record the sequence of vbo and then
45 * replay them for each clip rectangle, otherwise we simply emit
46 * the vbo straight into the command stream.
49 typedef struct _i965_spans i965_spans_t;
52 (*i965_get_rectangle_func_t) (i965_spans_t *spans);
55 cairo_span_renderer_t renderer;
57 i965_device_t *device;
60 cairo_bool_t is_bounded;
61 const cairo_rectangle_int_t *extents;
63 i965_get_rectangle_func_t get_rectangle;
66 cairo_region_t *clip_region;
68 struct i965_vbo head, *tail;
70 unsigned int vbo_offset;
75 i965_spans_emit_rectangle (i965_spans_t *spans)
77 return i965_add_rectangle (spans->device);
81 i965_spans_accumulate_rectangle (i965_spans_t *spans)
86 size = spans->device->rectangle_size;
87 if (unlikely (spans->vbo_offset + size > I965_VERTEX_SIZE)) {
90 vbo = malloc (sizeof (struct i965_vbo));
91 if (unlikely (vbo == NULL)) {
95 spans->tail->next = vbo;
99 vbo->bo = intel_bo_create (&spans->device->intel,
100 I965_VERTEX_SIZE, I965_VERTEX_SIZE,
101 FALSE, I915_TILING_NONE, 0);
104 spans->vbo_offset = 0;
105 spans->vbo_base = intel_bo_map (&spans->device->intel, vbo->bo);
108 vertices = spans->vbo_base + spans->vbo_offset;
109 spans->vbo_offset += size;
110 spans->tail->count += 3;
116 i965_span_rectangle (i965_spans_t *spans,
117 int x0, int x1, int y0, int y1,
121 float a = alpha / 255.;
123 vertices = spans->get_rectangle (spans);
138 static cairo_status_t
139 i965_bounded_spans_mono (void *abstract_renderer,
141 const cairo_half_open_span_t *half,
144 i965_spans_t *spans = abstract_renderer;
147 return CAIRO_STATUS_SUCCESS;
150 if (half[0].coverage >= 128) {
151 i965_span_rectangle (spans,
152 half[0].x, half[1].x,
157 } while (--num_spans > 1);
159 return CAIRO_STATUS_SUCCESS;
162 static cairo_status_t
163 i965_bounded_spans (void *abstract_renderer,
165 const cairo_half_open_span_t *half,
168 i965_spans_t *spans = abstract_renderer;
171 return CAIRO_STATUS_SUCCESS;
174 if (half[0].coverage) {
175 i965_span_rectangle (spans,
176 half[0].x, half[1].x,
181 } while (--num_spans > 1);
183 return CAIRO_STATUS_SUCCESS;
186 static cairo_status_t
187 i965_unbounded_spans (void *abstract_renderer,
189 const cairo_half_open_span_t *half,
192 i965_spans_t *spans = abstract_renderer;
194 if (num_spans == 0) {
195 i965_span_rectangle (spans,
196 spans->xmin, spans->xmax,
199 return CAIRO_STATUS_SUCCESS;
202 if (half[0].x != spans->xmin) {
203 i965_span_rectangle (spans,
204 spans->xmin, half[0].x,
210 i965_span_rectangle (spans,
211 half[0].x, half[1].x,
215 } while (--num_spans > 1);
217 if (half[0].x != spans->xmax) {
218 i965_span_rectangle (spans,
219 half[0].x, spans->xmax,
224 return CAIRO_STATUS_SUCCESS;
227 static cairo_status_t
228 i965_unbounded_spans_mono (void *abstract_renderer,
230 const cairo_half_open_span_t *half,
233 i965_spans_t *spans = abstract_renderer;
235 if (num_spans == 0) {
236 i965_span_rectangle (spans,
237 spans->xmin, spans->xmax,
240 return CAIRO_STATUS_SUCCESS;
243 if (half[0].x != spans->xmin) {
244 i965_span_rectangle (spans,
245 spans->xmin, half[0].x,
252 if (half[0].coverage >= 128)
254 i965_span_rectangle (spans,
255 half[0].x, half[1].x,
259 } while (--num_spans > 1);
261 if (half[0].x != spans->xmax) {
262 i965_span_rectangle (spans,
263 half[0].x, spans->xmax,
268 return CAIRO_STATUS_SUCCESS;
271 static cairo_status_t
272 i965_spans_init (i965_spans_t *spans,
275 const cairo_pattern_t *pattern,
276 cairo_antialias_t antialias,
278 const cairo_composite_rectangles_t *extents)
280 cairo_status_t status;
282 spans->device = i965_device (dst);
283 i965_shader_init (&spans->shader, dst, op);
285 spans->is_bounded = extents->is_bounded;
286 if (extents->is_bounded) {
287 if (antialias == CAIRO_ANTIALIAS_NONE)
288 spans->renderer.render_rows = i965_bounded_spans_mono;
290 spans->renderer.render_rows = i965_bounded_spans;
292 spans->extents = &extents->bounded;
294 if (antialias == CAIRO_ANTIALIAS_NONE)
295 spans->renderer.render_rows = i965_unbounded_spans_mono;
297 spans->renderer.render_rows = i965_unbounded_spans;
299 spans->extents = &extents->unbounded;
301 spans->xmin = spans->extents->x;
302 spans->xmax = spans->extents->x + spans->extents->width;
304 spans->clip_region = NULL;
306 cairo_region_t *clip_region = NULL;
308 status = _cairo_clip_get_region (clip, &clip_region);
309 assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED);
311 if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
314 spans->clip_region = clip_region;
315 if (status == CAIRO_INT_STATUS_UNSUPPORTED)
316 i965_shader_set_clip (&spans->shader, clip);
319 spans->head.next = NULL;
320 spans->head.bo = NULL;
321 spans->head.count = 0;
322 spans->tail = &spans->head;
324 if (spans->clip_region == NULL) {
325 spans->get_rectangle = i965_spans_emit_rectangle;
327 spans->get_rectangle = i965_spans_accumulate_rectangle;
328 spans->head.bo = intel_bo_create (&spans->device->intel,
329 I965_VERTEX_SIZE, I965_VERTEX_SIZE,
330 FALSE, I915_TILING_NONE, 0);
331 if (unlikely (spans->head.bo == NULL))
332 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
334 spans->vbo_base = intel_bo_map (&spans->device->intel, spans->head.bo);
336 spans->vbo_offset = 0;
338 return i965_shader_acquire_pattern (&spans->shader,
339 &spans->shader.source,
340 pattern, &extents->bounded);
344 i965_spans_fini (i965_spans_t *spans)
346 i965_shader_fini (&spans->shader);
348 if (spans->head.bo != NULL) {
349 struct i965_vbo *vbo, *next;
351 intel_bo_destroy (&spans->device->intel, spans->head.bo);
352 for (vbo = spans->head.next; vbo != NULL; vbo = next) {
354 intel_bo_destroy (&spans->device->intel, vbo->bo);
361 i965_clip_and_composite_spans (i965_surface_t *dst,
363 const cairo_pattern_t *pattern,
364 cairo_antialias_t antialias,
365 i965_spans_func_t draw_func,
367 const cairo_composite_rectangles_t*extents,
371 i965_device_t *device;
372 cairo_status_t status;
374 if (op == CAIRO_OPERATOR_CLEAR) {
375 pattern = &_cairo_pattern_white.base;
376 op = CAIRO_OPERATOR_DEST_OUT;
379 status = i965_spans_init (&spans, dst, op, pattern, antialias, clip, extents);
380 if (unlikely (status))
383 spans.shader.mask.base.content = CAIRO_CONTENT_ALPHA;
384 spans.shader.mask.type.fragment = FS_SPANS;
385 spans.shader.mask.type.vertex = VS_SPANS;
386 spans.shader.mask.type.pattern = PATTERN_BASE;
388 status = cairo_device_acquire (dst->intel.drm.base.device);
389 if (unlikely (status))
392 device = i965_device (dst);
393 status = i965_shader_commit (&spans.shader, device);
394 if (unlikely (status))
397 status = draw_func (draw_closure, &spans.renderer, spans.extents);
398 if (spans.clip_region != NULL && status == CAIRO_STATUS_SUCCESS)
399 i965_clipped_vertices (device, &spans.head, spans.clip_region);
402 cairo_device_release (dst->intel.drm.base.device);
404 i965_spans_fini (&spans);