1 /* cairo - a vector graphics library with display and print output
2 *
3 * Copyright © 2009 Intel Corporation
4 *
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.
12 *
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
18 *
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/
23 *
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.
27 *
28 * The Original Code is the cairo graphics library.
29 *
30 * The Initial Developer of the Original Code is Red Hat, Inc.
31 *
32 * Contributor(s):
33 * Chris Wilson <chris@chris-wilson.co.uk>
34 */
35
36 #include "cairoint.h"
37
38 #include "cairo-composite-rectangles-private.h"
39 #include "cairo-boxes-private.h"
40 #include "cairo-error-private.h"
41 #include "cairo-drm-i915-private.h"
42
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.
47 */
48
49 typedef struct _i915_spans i915_spans_t;
50
51 typedef float *
52 (*i915_get_rectangle_func_t) (i915_spans_t *spans);
53
54 typedef void
55 (*i915_span_func_t) (i915_spans_t *spans,
56 int x0, int x1, int y0, int y1,
57 int alpha);
58
59 struct _i915_spans {
60 cairo_span_renderer_t renderer;
61
62 i915_device_t *device;
63
64 int xmin, xmax;
65 cairo_bool_t is_bounded;
66 const cairo_rectangle_int_t *extents;
67
68 i915_get_rectangle_func_t get_rectangle;
69 i915_span_func_t span;
70 i915_shader_t shader;
71
72 cairo_region_t *clip_region;
73 cairo_bool_t need_clip_surface;
74
75 struct vbo {
76 struct vbo *next;
77 intel_bo_t *bo;
78 unsigned int count;
79 } head, *tail;
80
81 unsigned int vbo_offset;
82 float *vbo_base;
83 };
84
85 static float *
i915_emit_rectangle(i915_spans_t * spans)86 i915_emit_rectangle (i915_spans_t *spans)
87 {
88 return i915_add_rectangle (spans->device);
89 }
90
91 static float *
i915_accumulate_rectangle(i915_spans_t * spans)92 i915_accumulate_rectangle (i915_spans_t *spans)
93 {
94 float *vertices;
95 uint32_t size;
96
97 size = spans->device->rectangle_size;
98 if (unlikely (spans->vbo_offset + size > I915_VBO_SIZE)) {
99 struct vbo *vbo;
100
101 vbo = _cairo_malloc (sizeof (struct vbo));
102 if (unlikely (vbo == NULL)) {
103 /* throw error! */
104 }
105
106 spans->tail->next = vbo;
107 spans->tail = vbo;
108
109 vbo->next = NULL;
110 vbo->bo = intel_bo_create (&spans->device->intel,
111 I915_VBO_SIZE, I915_VBO_SIZE,
112 FALSE, I915_TILING_NONE, 0);
113 vbo->count = 0;
114
115 spans->vbo_offset = 0;
116 spans->vbo_base = intel_bo_map (&spans->device->intel, vbo->bo);
117 }
118
119 vertices = spans->vbo_base + spans->vbo_offset;
120 spans->vbo_offset += size;
121 spans->tail->count += 3;
122
123 return vertices;
124 }
125
126 static void
i915_span_zero(i915_spans_t * spans,int x0,int x1,int y0,int y1,int alpha)127 i915_span_zero (i915_spans_t *spans,
128 int x0, int x1, int y0, int y1,
129 int alpha)
130 {
131 float *vertices;
132
133 vertices = spans->get_rectangle (spans);
134
135 *vertices++ = x1;
136 *vertices++ = y1;
137
138 *vertices++ = x0;
139 *vertices++ = y1;
140
141 *vertices++ = x0;
142 *vertices++ = y0;
143 }
144
145 static void
i915_span_constant(i915_spans_t * spans,int x0,int x1,int y0,int y1,int alpha)146 i915_span_constant (i915_spans_t *spans,
147 int x0, int x1, int y0, int y1,
148 int alpha)
149 {
150 float *vertices;
151 float a = alpha / 255.;
152
153 vertices = spans->get_rectangle (spans);
154
155 *vertices++ = x1;
156 *vertices++ = y1;
157 *vertices++ = a;
158
159 *vertices++ = x0;
160 *vertices++ = y1;
161 *vertices++ = a;
162
163 *vertices++ = x0;
164 *vertices++ = y0;
165 *vertices++ = a;
166 }
167
168 static void
i915_span_linear(i915_spans_t * spans,int x0,int x1,int y0,int y1,int alpha)169 i915_span_linear (i915_spans_t *spans,
170 int x0, int x1, int y0, int y1,
171 int alpha)
172 {
173 float *vertices;
174 float a = alpha / 255.;
175 double s, t;
176
177 vertices = spans->get_rectangle (spans);
178
179 *vertices++ = x1;
180 *vertices++ = y1;
181 s = x0, t = y0;
182 *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
183 *vertices++ = a;
184
185 *vertices++ = x0;
186 *vertices++ = y1;
187 s = x1, t = y0;
188 *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
189 *vertices++ = a;
190
191 *vertices++ = x0;
192 *vertices++ = y0;
193 s = x1, t = y1;
194 *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
195 *vertices++ = a;
196 }
197
198 static void
i915_span_texture(i915_spans_t * spans,int x0,int x1,int y0,int y1,int alpha)199 i915_span_texture (i915_spans_t *spans,
200 int x0, int x1, int y0, int y1,
201 int alpha)
202 {
203 float *vertices;
204 float a = alpha / 255.;
205 double s, t;
206
207 vertices = spans->get_rectangle (spans);
208
209 *vertices++ = x1;
210 *vertices++ = y1;
211 s = x0, t = y0;
212 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
213 *vertices++ = s; *vertices++ = t;
214 *vertices++ = a;
215
216 *vertices++ = x0;
217 *vertices++ = y1;
218 s = x1, t = y0;
219 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
220 *vertices++ = s; *vertices++ = t;
221 *vertices++ = a;
222
223 *vertices++ = x0;
224 *vertices++ = y0;
225 s = x1, t = y1;
226 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
227 *vertices++ = s; *vertices++ = t;
228 *vertices++ = a;
229 }
230
231 static void
i915_span_texture16(i915_spans_t * spans,int x0,int x1,int y0,int y1,int alpha)232 i915_span_texture16 (i915_spans_t *spans,
233 int x0, int x1, int y0, int y1, int alpha)
234 {
235 float *vertices;
236 float a = alpha / 255.;
237 double s, t;
238
239 vertices = spans->get_rectangle (spans);
240
241 *vertices++ = x1;
242 *vertices++ = y1;
243 s = x0, t = y0;
244 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
245 *vertices++ = texcoord_2d_16 (s, t);
246 *vertices++ = a;
247
248 *vertices++ = x0;
249 *vertices++ = y1;
250 s = x1, t = y0;
251 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
252 *vertices++ = texcoord_2d_16 (s, t);
253 *vertices++ = a;
254
255 *vertices++ = x0;
256 *vertices++ = y0;
257 s = x1, t = y1;
258 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
259 *vertices++ = texcoord_2d_16 (s, t);
260 *vertices++ = a;
261 }
262
263 static void
i915_span_generic(i915_spans_t * spans,int x0,int x1,int y0,int y1,int alpha)264 i915_span_generic (i915_spans_t *spans,
265 int x0, int x1, int y0, int y1, int alpha)
266 {
267 double s, t;
268 float *vertices;
269 float a = alpha / 255.;
270
271 /* Each vertex is:
272 * 2 vertex coordinates
273 * [0-2] source texture coordinates
274 * 1 alpha value.
275 * [0,2] clip mask coordinates
276 */
277
278 vertices = spans->get_rectangle (spans);
279
280 /* bottom right */
281 *vertices++ = x1; *vertices++ = y1;
282 s = x1, t = y1;
283 switch (spans->shader.source.type.vertex) {
284 case VS_ZERO:
285 case VS_CONSTANT:
286 break;
287 case VS_LINEAR:
288 *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
289 break;
290 case VS_TEXTURE:
291 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
292 *vertices++ = s; *vertices++ = t;
293 break;
294 case VS_TEXTURE_16:
295 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
296 *vertices++ = texcoord_2d_16 (s, t);
297 break;
298 }
299 *vertices++ = a;
300 if (spans->need_clip_surface) {
301 s = x1, t = y1;
302 cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t);
303 *vertices++ = texcoord_2d_16 (s, t);
304 }
305 if (spans->shader.need_combine) {
306 s = x1, t = y1;
307 cairo_matrix_transform_point (&spans->shader.dst.base.matrix, &s, &t);
308 *vertices++ = texcoord_2d_16 (s, t);
309 }
310
311 /* bottom left */
312 *vertices++ = x0; *vertices++ = y1;
313 s = x0, t = y1;
314 switch (spans->shader.source.type.vertex) {
315 case VS_ZERO:
316 case VS_CONSTANT:
317 break;
318 case VS_LINEAR:
319 *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
320 break;
321 case VS_TEXTURE:
322 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
323 *vertices++ = s; *vertices++ = t;
324 break;
325 case VS_TEXTURE_16:
326 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
327 *vertices++ = texcoord_2d_16 (s, t);
328 break;
329 }
330 *vertices++ = a;
331 if (spans->need_clip_surface) {
332 s = x0, t = y1;
333 cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t);
334 *vertices++ = texcoord_2d_16 (s, t);
335 }
336 if (spans->shader.need_combine) {
337 s = x0, t = y1;
338 cairo_matrix_transform_point (&spans->shader.dst.base.matrix, &s, &t);
339 *vertices++ = texcoord_2d_16 (s, t);
340 }
341
342 /* top left */
343 *vertices++ = x0; *vertices++ = y0;
344 s = x0, t = y0;
345 switch (spans->shader.source.type.vertex) {
346 case VS_ZERO:
347 case VS_CONSTANT:
348 break;
349 case VS_LINEAR:
350 *vertices++ = i915_shader_linear_texcoord (&spans->shader.source.linear, s, t);
351 break;
352 case VS_TEXTURE:
353 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
354 *vertices++ = s; *vertices++ = t;
355 break;
356 case VS_TEXTURE_16:
357 cairo_matrix_transform_point (&spans->shader.source.base.matrix, &s, &t);
358 *vertices++ = texcoord_2d_16 (s, t);
359 break;
360 }
361 *vertices++ = a;
362 if (spans->need_clip_surface) {
363 s = x0, t = y0;
364 cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t);
365 *vertices++ = texcoord_2d_16 (s, t);
366 }
367 if (spans->shader.need_combine) {
368 s = x0, t = y0;
369 cairo_matrix_transform_point (&spans->shader.dst.base.matrix, &s, &t);
370 *vertices++ = texcoord_2d_16 (s, t);
371 }
372 }
373
374 static cairo_status_t
i915_zero_spans_mono(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * half,unsigned num_spans)375 i915_zero_spans_mono (void *abstract_renderer,
376 int y, int height,
377 const cairo_half_open_span_t *half,
378 unsigned num_spans)
379 {
380 i915_spans_t *spans = abstract_renderer;
381 int x0, x1;
382
383 if (num_spans == 0)
384 return CAIRO_STATUS_SUCCESS;
385
386 do {
387 while (num_spans && half[0].coverage < 128)
388 half++, num_spans--;
389 if (num_spans == 0)
390 break;
391
392 x0 = x1 = half[0].x;
393 while (num_spans--) {
394 half++;
395
396 x1 = half[0].x;
397 if (half[0].coverage < 128)
398 break;
399 }
400
401 i915_span_zero (spans,
402 x0, x1,
403 y, y + height,
404 0);
405 } while (num_spans);
406
407 return CAIRO_STATUS_SUCCESS;
408 }
409
410 static cairo_status_t
i915_zero_spans(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * half,unsigned num_spans)411 i915_zero_spans (void *abstract_renderer,
412 int y, int height,
413 const cairo_half_open_span_t *half,
414 unsigned num_spans)
415 {
416 i915_spans_t *spans = abstract_renderer;
417 int x0, x1;
418
419 if (num_spans == 0)
420 return CAIRO_STATUS_SUCCESS;
421
422 do {
423 while (num_spans && half[0].coverage == 0)
424 half++, num_spans--;
425 if (num_spans == 0)
426 break;
427
428 x0 = x1 = half[0].x;
429 while (num_spans--) {
430 half++;
431
432 x1 = half[0].x;
433 if (half[0].coverage == 0)
434 break;
435 }
436
437 i915_span_zero (spans,
438 x0, x1,
439 y, y + height,
440 0);
441 } while (num_spans);
442
443 return CAIRO_STATUS_SUCCESS;
444 }
445
446 static cairo_status_t
i915_bounded_spans_mono(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * half,unsigned num_spans)447 i915_bounded_spans_mono (void *abstract_renderer,
448 int y, int height,
449 const cairo_half_open_span_t *half,
450 unsigned num_spans)
451 {
452 i915_spans_t *spans = abstract_renderer;
453
454 if (num_spans == 0)
455 return CAIRO_STATUS_SUCCESS;
456
457 do {
458 if (half[0].coverage >= 128) {
459 spans->span (spans,
460 half[0].x, half[1].x,
461 y, y + height,
462 255);
463 }
464 half++;
465 } while (--num_spans > 1);
466
467 return CAIRO_STATUS_SUCCESS;
468 }
469
470 static cairo_status_t
i915_bounded_spans(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * half,unsigned num_spans)471 i915_bounded_spans (void *abstract_renderer,
472 int y, int height,
473 const cairo_half_open_span_t *half,
474 unsigned num_spans)
475 {
476 i915_spans_t *spans = abstract_renderer;
477
478 if (num_spans == 0)
479 return CAIRO_STATUS_SUCCESS;
480
481 do {
482 if (half[0].coverage) {
483 spans->span (spans,
484 half[0].x, half[1].x,
485 y, y + height,
486 half[0].coverage);
487 }
488 half++;
489 } while (--num_spans > 1);
490
491 return CAIRO_STATUS_SUCCESS;
492 }
493
494 static cairo_status_t
i915_unbounded_spans(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * half,unsigned num_spans)495 i915_unbounded_spans (void *abstract_renderer,
496 int y, int height,
497 const cairo_half_open_span_t *half,
498 unsigned num_spans)
499 {
500 i915_spans_t *spans = abstract_renderer;
501
502 if (num_spans == 0) {
503 spans->span (spans,
504 spans->xmin, spans->xmax,
505 y, y + height,
506 0);
507 return CAIRO_STATUS_SUCCESS;
508 }
509
510 if (half[0].x != spans->xmin) {
511 spans->span (spans,
512 spans->xmin, half[0].x,
513 y, y + height,
514 0);
515 }
516
517 do {
518 spans->span (spans,
519 half[0].x, half[1].x,
520 y, y + height,
521 half[0].coverage);
522 half++;
523 } while (--num_spans > 1);
524
525 if (half[0].x != spans->xmax) {
526 spans->span (spans,
527 half[0].x, spans->xmax,
528 y, y + height,
529 0);
530 }
531
532 return CAIRO_STATUS_SUCCESS;
533 }
534
535 static cairo_status_t
i915_unbounded_spans_mono(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * half,unsigned num_spans)536 i915_unbounded_spans_mono (void *abstract_renderer,
537 int y, int height,
538 const cairo_half_open_span_t *half,
539 unsigned num_spans)
540 {
541 i915_spans_t *spans = abstract_renderer;
542
543 if (num_spans == 0) {
544 spans->span (spans,
545 spans->xmin, spans->xmax,
546 y, y + height,
547 0);
548 return CAIRO_STATUS_SUCCESS;
549 }
550
551 if (half[0].x != spans->xmin) {
552 spans->span (spans,
553 spans->xmin, half[0].x,
554 y, y + height,
555 0);
556 }
557
558 do {
559 int alpha = 0;
560 if (half[0].coverage >= 128)
561 alpha = 255;
562 spans->span (spans,
563 half[0].x, half[1].x,
564 y, y + height,
565 alpha);
566 half++;
567 } while (--num_spans > 1);
568
569 if (half[0].x != spans->xmax) {
570 spans->span (spans,
571 half[0].x, spans->xmax,
572 y, y + height,
573 0);
574 }
575
576 return CAIRO_STATUS_SUCCESS;
577 }
578
579 static cairo_status_t
i915_spans_init(i915_spans_t * spans,i915_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * pattern,cairo_antialias_t antialias,cairo_clip_t * clip,double opacity,const cairo_composite_rectangles_t * extents)580 i915_spans_init (i915_spans_t *spans,
581 i915_surface_t *dst,
582 cairo_operator_t op,
583 const cairo_pattern_t *pattern,
584 cairo_antialias_t antialias,
585 cairo_clip_t *clip,
586 double opacity,
587 const cairo_composite_rectangles_t *extents)
588 {
589 cairo_status_t status;
590
591 spans->device = (i915_device_t *) dst->intel.drm.base.device;
592
593 spans->is_bounded = extents->is_bounded;
594 if (extents->is_bounded) {
595 if (antialias == CAIRO_ANTIALIAS_NONE)
596 spans->renderer.render_rows = i915_bounded_spans_mono;
597 else
598 spans->renderer.render_rows = i915_bounded_spans;
599
600 spans->extents = &extents->bounded;
601 } else {
602 if (antialias == CAIRO_ANTIALIAS_NONE)
603 spans->renderer.render_rows = i915_unbounded_spans_mono;
604 else
605 spans->renderer.render_rows = i915_unbounded_spans;
606
607 spans->extents = &extents->unbounded;
608 }
609 spans->xmin = spans->extents->x;
610 spans->xmax = spans->extents->x + spans->extents->width;
611
612 spans->clip_region = NULL;
613 spans->need_clip_surface = FALSE;
614 if (clip != NULL) {
615 cairo_region_t *clip_region = NULL;
616
617 status = _cairo_clip_get_region (clip, &clip_region);
618 assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED);
619
620 if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
621 clip_region = NULL;
622
623 spans->clip_region = clip_region;
624 spans->need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
625 }
626
627 spans->head.next = NULL;
628 spans->head.bo = NULL;
629 spans->head.count = 0;
630 spans->tail = &spans->head;
631
632 if (spans->clip_region == NULL) {
633 spans->get_rectangle = i915_emit_rectangle;
634 } else {
635 assert (! extents->is_bounded);
636 spans->get_rectangle = i915_accumulate_rectangle;
637 spans->head.bo = intel_bo_create (&spans->device->intel,
638 I915_VBO_SIZE, I915_VBO_SIZE,
639 FALSE, I915_TILING_NONE, 0);
640 if (unlikely (spans->head.bo == NULL))
641 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
642
643 spans->vbo_base = intel_bo_map (&spans->device->intel, spans->head.bo);
644 }
645 spans->vbo_offset = 0;
646
647 i915_shader_init (&spans->shader, dst, op, opacity);
648 if (spans->need_clip_surface)
649 i915_shader_set_clip (&spans->shader, clip);
650
651 status = i915_shader_acquire_pattern (&spans->shader, &spans->shader.source,
652 pattern, &extents->bounded);
653 if (unlikely (status))
654 return status;
655
656 return CAIRO_STATUS_SUCCESS;
657 }
658
659 static void
i915_spans_fini(i915_spans_t * spans)660 i915_spans_fini (i915_spans_t *spans)
661 {
662 i915_shader_fini (&spans->shader);
663
664 if (spans->head.bo != NULL) {
665 struct vbo *vbo, *next;
666
667 intel_bo_destroy (&spans->device->intel, spans->head.bo);
668 for (vbo = spans->head.next; vbo != NULL; vbo = next) {
669 next = vbo->next;
670 intel_bo_destroy (&spans->device->intel, vbo->bo);
671 free (vbo);
672 }
673 }
674 }
675
676 cairo_status_t
i915_clip_and_composite_spans(i915_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * pattern,cairo_antialias_t antialias,i915_spans_func_t draw_func,void * draw_closure,const cairo_composite_rectangles_t * extents,cairo_clip_t * clip,double opacity)677 i915_clip_and_composite_spans (i915_surface_t *dst,
678 cairo_operator_t op,
679 const cairo_pattern_t *pattern,
680 cairo_antialias_t antialias,
681 i915_spans_func_t draw_func,
682 void *draw_closure,
683 const cairo_composite_rectangles_t*extents,
684 cairo_clip_t *clip,
685 double opacity)
686 {
687 i915_spans_t spans;
688 i915_device_t *device;
689 cairo_status_t status;
690 struct vbo *vbo;
691
692 if (i915_surface_needs_tiling (dst)) {
693 ASSERT_NOT_REACHED;
694 return CAIRO_INT_STATUS_UNSUPPORTED;
695 }
696
697 if (op == CAIRO_OPERATOR_CLEAR) {
698 pattern = &_cairo_pattern_white.base;
699 op = CAIRO_OPERATOR_DEST_OUT;
700 }
701
702 status = i915_spans_init (&spans, dst, op, pattern, antialias, clip, opacity, extents);
703 if (unlikely (status))
704 return status;
705
706 spans.shader.mask.base.texfmt = TEXCOORDFMT_1D;
707 spans.shader.mask.base.content = CAIRO_CONTENT_ALPHA;
708 spans.shader.mask.type.fragment = FS_SPANS;
709
710 status = cairo_device_acquire (dst->intel.drm.base.device);
711 if (unlikely (status))
712 goto CLEANUP_SPANS;
713
714 if (dst->deferred_clear) {
715 status = i915_surface_clear (dst);
716 if (unlikely (status))
717 goto CLEANUP_SPANS;
718 }
719
720 device = i915_device (dst);
721 status = i915_shader_commit (&spans.shader, device);
722 if (unlikely (status))
723 goto CLEANUP_DEVICE;
724
725 if (! spans.shader.need_combine && ! spans.need_clip_surface) {
726 switch (spans.shader.source.type.vertex) {
727 case VS_ZERO:
728 spans.span = i915_span_zero;
729 if (extents->is_bounded) {
730 if (antialias == CAIRO_ANTIALIAS_NONE)
731 spans.renderer.render_rows = i915_zero_spans_mono;
732 else
733 spans.renderer.render_rows = i915_zero_spans;
734 }
735 break;
736 case VS_CONSTANT:
737 spans.span = i915_span_constant;
738 break;
739 case VS_LINEAR:
740 spans.span = i915_span_linear;
741 break;
742 case VS_TEXTURE:
743 spans.span = i915_span_texture;
744 break;
745 case VS_TEXTURE_16:
746 spans.span = i915_span_texture16;
747 break;
748 default:
749 spans.span = i915_span_generic;
750 break;
751 }
752 } else {
753 spans.span = i915_span_generic;
754 }
755
756 status = draw_func (draw_closure, &spans.renderer, spans.extents);
757 if (spans.clip_region != NULL && status == CAIRO_STATUS_SUCCESS) {
758 i915_vbo_finish (device);
759
760 OUT_DWORD (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT);
761 for (vbo = &spans.head; vbo != NULL; vbo = vbo->next) {
762 int i, num_rectangles;
763
764 /* XXX require_space & batch_flush */
765
766 OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S (0) | I1_LOAD_S (1) | 1);
767 i915_batch_emit_reloc (device, vbo->bo, 0,
768 I915_GEM_DOMAIN_VERTEX, 0,
769 FALSE);
770 OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
771 (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT) |
772 vbo->count);
773
774 num_rectangles = cairo_region_num_rectangles (spans.clip_region);
775 for (i = 0; i < num_rectangles; i++) {
776 cairo_rectangle_int_t rect;
777
778 cairo_region_get_rectangle (spans.clip_region, i, &rect);
779
780 OUT_DWORD (_3DSTATE_SCISSOR_RECT_0_CMD);
781 OUT_DWORD (SCISSOR_RECT_0_XMIN (rect.x) |
782 SCISSOR_RECT_0_YMIN (rect.y));
783 OUT_DWORD (SCISSOR_RECT_0_XMAX (rect.x + rect.width) |
784 SCISSOR_RECT_0_YMAX (rect.y + rect.height));
785
786 OUT_DWORD (PRIM3D_RECTLIST | PRIM3D_INDIRECT_SEQUENTIAL | vbo->count);
787 OUT_DWORD (0);
788 }
789 }
790 OUT_DWORD (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
791 }
792
793 CLEANUP_DEVICE:
794 cairo_device_release (dst->intel.drm.base.device);
795 CLEANUP_SPANS:
796 i915_spans_fini (&spans);
797
798 return status;
799 }
800