71061a0e927797fddaacb60592a84b77c1ed69af
[framework/graphics/cairo.git] / src / drm / cairo-drm-i965-surface.c
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Kristian Høgsberg
4  * Copyright © 2009 Chris Wilson
5  * Copyright © 2009 Intel Corporation
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is Kristian Høgsberg.
33  *
34  * Based on the xf86-intel-driver i965 render acceleration code,
35  * authored by:
36  *    Wang Zhenyu <zhenyu.z.wang@intel.com>
37  *    Eric Anholt <eric@anholt.net>
38  *    Carl Worth <cworth@redhat.com>
39  *    Keith Packard <keithp@keithp.com>
40  */
41
42 /* XXX
43  *
44  * FIXME: Use brw_PLN for [DevCTG-B+]
45  *
46  */
47
48 #include "cairoint.h"
49
50 #include "cairo-drm-private.h"
51 #include "cairo-drm-ioctl-private.h"
52 #include "cairo-drm-intel-private.h"
53 #include "cairo-drm-intel-command-private.h"
54 #include "cairo-drm-intel-ioctl-private.h"
55 #include "cairo-drm-i965-private.h"
56
57 #include "cairo-boxes-private.h"
58 #include "cairo-composite-rectangles-private.h"
59 #include "cairo-default-context-private.h"
60 #include "cairo-error-private.h"
61 #include "cairo-region-private.h"
62 #include "cairo-surface-offset-private.h"
63
64 #include <sys/ioctl.h>
65 #include <errno.h>
66
67 #define I965_MAX_SIZE 8192
68
69 static const cairo_surface_backend_t i965_surface_backend;
70
71 static void
72 i965_stream_init (i965_stream_t *stream,
73                   uint8_t *data, uint32_t size,
74                   struct i965_pending_relocation *pending, int max_pending,
75                   struct drm_i915_gem_relocation_entry *relocations, int max_relocations)
76
77 {
78     stream->used = stream->committed = 0;
79     stream->data = data;
80     stream->size = size;
81     stream->serial = 1;
82
83     stream->num_pending_relocations = 0;
84     stream->max_pending_relocations = max_pending;
85     stream->pending_relocations = pending;
86
87     stream->num_relocations = 0;
88     stream->max_relocations = max_relocations;
89     stream->relocations = relocations;
90 }
91
92 static void
93 i965_add_relocation (i965_device_t *device,
94                      intel_bo_t *bo,
95                      uint32_t read_domains,
96                      uint32_t write_domain)
97 {
98     if (bo->exec == NULL) {
99         int i;
100
101         device->exec.gtt_size += bo->base.size;
102
103         i = device->exec.count++;
104         assert (i < ARRAY_LENGTH (device->exec.exec));
105
106         device->exec.exec[i].handle = bo->base.handle;
107         device->exec.exec[i].relocation_count = 0;
108         device->exec.exec[i].relocs_ptr = 0;
109         device->exec.exec[i].alignment  = 0;
110         device->exec.exec[i].offset = 0;
111         device->exec.exec[i].flags  = 0;
112         device->exec.exec[i].rsvd1  = 0;
113         device->exec.exec[i].rsvd2  = 0;
114
115         device->exec.bo[i] = intel_bo_reference (bo);
116         bo->exec = &device->exec.exec[i];
117     }
118
119     if (cairo_list_is_empty (&bo->link))
120         cairo_list_add_tail (&device->flush, &bo->link);
121
122     assert (write_domain == 0 || bo->batch_write_domain == 0 || bo->batch_write_domain == write_domain);
123     bo->batch_read_domains |= read_domains;
124     bo->batch_write_domain |= write_domain;
125 }
126
127 void
128 i965_emit_relocation (i965_device_t *device,
129                       i965_stream_t *stream,
130                       intel_bo_t *target,
131                       uint32_t target_offset,
132                       uint32_t read_domains,
133                       uint32_t write_domain,
134                       uint32_t offset)
135 {
136     int n;
137
138     assert (target_offset < target->base.size);
139
140     i965_add_relocation (device, target, read_domains, write_domain);
141
142     n = stream->num_relocations++;
143     assert (n < stream->max_relocations);
144
145     stream->relocations[n].offset = offset;
146     stream->relocations[n].delta  = target_offset;
147     stream->relocations[n].target_handle   = target->base.handle;
148     stream->relocations[n].read_domains    = read_domains;
149     stream->relocations[n].write_domain    = write_domain;
150     stream->relocations[n].presumed_offset = target->offset;
151 }
152
153 static void
154 i965_stream_reset (i965_stream_t *stream)
155 {
156     stream->used = stream->committed = 0;
157     stream->num_relocations = 0;
158     stream->num_pending_relocations = 0;
159     if (++stream->serial == 0)
160         stream->serial = 1;
161 }
162
163 void
164 i965_stream_commit (i965_device_t *device,
165                     i965_stream_t *stream)
166 {
167     intel_bo_t *bo;
168     int n;
169
170     assert (stream->used);
171
172     bo = intel_bo_create (&device->intel,
173                           stream->used, stream->used,
174                           FALSE, I915_TILING_NONE, 0);
175
176     /* apply pending relocations */
177     for (n = 0; n < stream->num_pending_relocations; n++) {
178         struct i965_pending_relocation *p = &stream->pending_relocations[n];
179
180         i965_emit_relocation (device, &device->batch, bo,
181                               p->delta,
182                               p->read_domains,
183                               p->write_domain,
184                               p->offset);
185         if (bo->offset)
186             *(uint32_t *) (device->batch.data + p->offset) = bo->offset + p->delta;
187     }
188
189     intel_bo_write (&device->intel, bo, 0, stream->used, stream->data);
190
191     if (stream->num_relocations) {
192         assert (bo->exec != NULL);
193         bo->exec->relocs_ptr = (uintptr_t) stream->relocations;
194         bo->exec->relocation_count = stream->num_relocations;
195     }
196
197     intel_bo_destroy (&device->intel, bo);
198
199     i965_stream_reset (stream);
200 }
201
202 static void
203 sf_states_pluck (void *entry, void *closure)
204 {
205     i965_device_t *device = closure;
206
207     _cairo_hash_table_remove (device->sf_states, entry);
208     _cairo_freelist_free (&device->sf_freelist, entry);
209 }
210
211 static void
212 cc_offsets_pluck (void *entry, void *closure)
213 {
214     i965_device_t *device = closure;
215
216     _cairo_hash_table_remove (device->cc_states, entry);
217     _cairo_freelist_free (&device->cc_freelist, entry);
218 }
219
220 static void
221 wm_kernels_pluck (void *entry, void *closure)
222 {
223     i965_device_t *device = closure;
224
225     _cairo_hash_table_remove (device->wm_kernels, entry);
226     _cairo_freelist_free (&device->wm_kernel_freelist, entry);
227 }
228
229 static void
230 wm_states_pluck (void *entry, void *closure)
231 {
232     i965_device_t *device = closure;
233
234     _cairo_hash_table_remove (device->wm_states, entry);
235     _cairo_freelist_free (&device->wm_state_freelist, entry);
236 }
237
238 static void
239 wm_bindings_pluck (void *entry, void *closure)
240 {
241     i965_device_t *device = closure;
242
243     _cairo_hash_table_remove (device->wm_bindings, entry);
244     _cairo_freelist_free (&device->wm_binding_freelist, entry);
245 }
246
247 static void
248 samplers_pluck (void *entry, void *closure)
249 {
250     i965_device_t *device = closure;
251
252     _cairo_hash_table_remove (device->samplers, entry);
253     _cairo_freelist_free (&device->sampler_freelist, entry);
254 }
255
256 void
257 i965_general_state_reset (i965_device_t *device)
258 {
259     _cairo_hash_table_foreach (device->sf_states,
260                                sf_states_pluck,
261                                device);
262
263     _cairo_hash_table_foreach (device->cc_states,
264                                cc_offsets_pluck,
265                                device);
266
267     _cairo_hash_table_foreach (device->wm_kernels,
268                                wm_kernels_pluck,
269                                device);
270
271     _cairo_hash_table_foreach (device->wm_states,
272                                wm_states_pluck,
273                                device);
274
275     _cairo_hash_table_foreach (device->wm_bindings,
276                                wm_bindings_pluck,
277                                device);
278
279     _cairo_hash_table_foreach (device->samplers,
280                                samplers_pluck,
281                                device);
282
283     device->vs_offset = (uint32_t) -1;
284     device->border_color_offset = (uint32_t) -1;
285
286     if (device->general_state != NULL) {
287         intel_bo_destroy (&device->intel, device->general_state);
288         device->general_state = NULL;
289     }
290 }
291
292 static void
293 i965_device_reset (i965_device_t *device)
294 {
295     device->exec.count = 0;
296     device->exec.gtt_size = I965_VERTEX_SIZE +
297                             I965_SURFACE_SIZE +
298                             I965_GENERAL_SIZE +
299                             I965_BATCH_SIZE;
300
301     device->sf_state.entry.hash = (uint32_t) -1;
302     device->wm_state.entry.hash = (uint32_t) -1;
303     device->wm_binding.entry.hash = (uint32_t) -1;
304     device->cc_state.entry.hash = (uint32_t) -1;
305
306     device->target = NULL;
307     device->source = NULL;
308     device->mask = NULL;
309     device->clip = NULL;
310
311     device->draw_rectangle = (uint32_t) -1;
312
313     device->vertex_type = (uint32_t) -1;
314     device->vertex_size = 0;
315     device->rectangle_size   = 0;
316     device->last_vertex_size = 0;
317
318     device->constants = NULL;
319     device->constants_size = 0;
320
321     device->have_urb_fences = FALSE;
322 }
323
324 static cairo_status_t
325 i965_exec (i965_device_t *device, uint32_t offset)
326 {
327     struct drm_i915_gem_execbuffer2 execbuf;
328     cairo_status_t status = CAIRO_STATUS_SUCCESS;
329     int ret, i;
330
331     execbuf.buffers_ptr = (uintptr_t) device->exec.exec;
332     execbuf.buffer_count = device->exec.count;
333     execbuf.batch_start_offset = offset;
334     execbuf.batch_len = device->batch.used;
335     execbuf.DR1 = 0;
336     execbuf.DR4 = 0;
337     execbuf.num_cliprects = 0;
338     execbuf.cliprects_ptr = 0;
339     execbuf.flags = I915_GEM_3D_PIPELINE;
340     execbuf.rsvd1 = 0;
341     execbuf.rsvd2 = 0;
342
343 #if 0
344     printf ("exec: offset=%d, length=%d, buffers=%d\n",
345             offset, device->batch.used, device->exec.count);
346     intel_dump_batchbuffer ((uint32_t *) device->batch.data,
347                             device->batch.used,
348                             device->intel.base.chip_id);
349 #endif
350
351     ret = 0;
352     do {
353         ret = ioctl (device->intel.base.fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
354     } while (ret != 0 && errno == EINTR);
355     if (unlikely (ret)) {
356         if (errno == ENOMEM)
357             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
358         else
359             status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
360
361         fprintf (stderr, "Batch submission failed: %d\n", errno);
362         fprintf (stderr, "   gtt size: %zd/%zd\n",
363                  device->exec.gtt_size, device->intel.gtt_avail_size);
364
365         fprintf (stderr, "   %d buffers:\n",
366                  device->exec.count);
367         for (i = 0; i < device->exec.count; i++) {
368             fprintf (stderr, "     exec[%d] = %d\n",
369                      i, device->exec.bo[i]->base.size);
370         }
371
372         intel_dump_batchbuffer ((uint32_t *) device->batch.data,
373                                 device->batch.used,
374                                 device->intel.base.chip_id);
375     }
376
377     /* XXX any write target within the batch should now be in error */
378     for (i = 0; i < device->exec.count; i++) {
379         intel_bo_t *bo = device->exec.bo[i];
380         cairo_bool_t ret;
381
382         bo->offset = device->exec.exec[i].offset;
383         bo->exec = NULL;
384         bo->batch_read_domains = 0;
385         bo->batch_write_domain = 0;
386
387         if (bo->virtual)
388             intel_bo_unmap (bo);
389         bo->cpu = FALSE;
390
391         if (bo->purgeable)
392             ret = intel_bo_madvise (&device->intel, bo, I915_MADV_DONTNEED);
393             /* ignore immediate notification of purging */
394
395         cairo_list_del (&bo->cache_list);
396         cairo_list_init (&bo->link);
397         intel_bo_destroy (&device->intel, bo);
398     }
399     cairo_list_init (&device->flush);
400
401     device->exec.count = 0;
402
403     return status;
404 }
405
406 static inline uint32_t
407 next_bo_size (uint32_t v)
408 {
409     v = (v + 8191) / 8192;
410
411     v--;
412     v |= v >> 1;
413     v |= v >> 2;
414     v |= v >> 4;
415     v |= v >> 8;
416     v |= v >> 16;
417     v++;
418
419     return v * 8192;
420 }
421
422 static void
423 _copy_to_bo_and_apply_relocations (i965_device_t *device,
424                                    intel_bo_t *bo,
425                                    i965_stream_t *stream,
426                                    uint32_t offset)
427 {
428     int n;
429
430     intel_bo_write (&device->intel, bo,
431                     offset, stream->used,
432                     stream->data);
433
434     for (n = 0; n < stream->num_pending_relocations; n++) {
435         struct i965_pending_relocation *p = &stream->pending_relocations[n];
436
437         i965_emit_relocation (device, &device->batch, bo,
438                               p->delta + offset,
439                               p->read_domains,
440                               p->write_domain,
441                               p->offset);
442
443         if (bo->offset) {
444             *(uint32_t *) (device->batch.data + p->offset) =
445                 bo->offset + p->delta + offset;
446         }
447     }
448 }
449
450 cairo_status_t
451 i965_device_flush (i965_device_t *device)
452 {
453     cairo_status_t status;
454     uint32_t aligned, max;
455     intel_bo_t *bo;
456     int n;
457
458     if (device->batch.used == 0)
459         return CAIRO_STATUS_SUCCESS;
460
461     i965_flush_vertices (device);
462
463     OUT_BATCH (MI_BATCH_BUFFER_END);
464     /* Emit a padding dword if we aren't going to be quad-word aligned. */
465     if (device->batch.used & 4)
466         OUT_BATCH (MI_NOOP);
467
468 #if 0
469     printf ("device flush: vertex=%d, constant=%d, surface=%d, general=%d, batch=%d\n",
470             device->vertex.used,
471             device->constant.used,
472             device->surface.used,
473             device->general.used,
474             device->batch.used);
475 #endif
476
477     /* can we pack the surface state into the tail of the general state? */
478     if (device->general.used == device->general.committed) {
479         if (device->general.used) {
480             assert (device->general.num_pending_relocations == 1);
481             assert (device->general_state != NULL);
482             i965_emit_relocation (device, &device->batch,
483                                   device->general_state,
484                                   device->general.pending_relocations[0].delta,
485                                   device->general.pending_relocations[0].read_domains,
486                                   device->general.pending_relocations[0].write_domain,
487                                   device->general.pending_relocations[0].offset);
488
489             if (device->general_state->offset) {
490                 *(uint32_t *) (device->batch.data +
491                                device->general.pending_relocations[0].offset) =
492                     device->general_state->offset +
493                     device->general.pending_relocations[0].delta;
494             }
495         }
496     } else {
497         assert (device->general.num_pending_relocations == 1);
498         if (device->general_state != NULL) {
499             intel_bo_destroy (&device->intel, device->general_state);
500             device->general_state = NULL;
501         }
502
503         bo = intel_bo_create (&device->intel,
504                               device->general.used,
505                               device->general.used,
506                               FALSE, I915_TILING_NONE, 0);
507         if (unlikely (bo == NULL))
508             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
509
510         aligned = (device->general.used + 31) & -32;
511         if (device->surface.used &&
512             aligned + device->surface.used <= bo->base.size)
513         {
514             _copy_to_bo_and_apply_relocations (device, bo, &device->general, 0);
515             _copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned);
516
517             if (device->surface.num_relocations) {
518                 for (n = 0; n < device->surface.num_relocations; n++)
519                     device->surface.relocations[n].offset += aligned;
520
521                 assert (bo->exec != NULL);
522                 bo->exec->relocs_ptr = (uintptr_t) device->surface.relocations;
523                 bo->exec->relocation_count = device->surface.num_relocations;
524             }
525
526             i965_stream_reset (&device->surface);
527         }
528         else
529         {
530             _copy_to_bo_and_apply_relocations (device, bo, &device->general, 0);
531         }
532
533         /* Note we don't reset the general state, just mark what data we've committed. */
534         device->general.committed = device->general.used;
535         device->general_state = bo;
536     }
537     device->general.num_pending_relocations = 0;
538
539     /* Combine vertex+constant+surface+batch streams? */
540     max = aligned = device->vertex.used;
541     if (device->surface.used) {
542         aligned = (aligned + 63) & -64;
543         aligned += device->surface.used;
544         if (device->surface.used > max)
545             max = device->surface.used;
546     }
547     aligned = (aligned + 63) & -64;
548     aligned += device->batch.used;
549     if (device->batch.used > max)
550         max = device->batch.used;
551     if (aligned <= next_bo_size (max)) {
552         int batch_num_relocations;
553
554         if (aligned <= 8192)
555             max = aligned;
556
557         bo = intel_bo_create (&device->intel,
558                               max, max,
559                               FALSE, I915_TILING_NONE, 0);
560         if (unlikely (bo == NULL))
561             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
562
563         assert (aligned <= bo->base.size);
564
565         if (device->vertex.used)
566             _copy_to_bo_and_apply_relocations (device, bo, &device->vertex, 0);
567
568         aligned = device->vertex.used;
569
570         batch_num_relocations = device->batch.num_relocations;
571         if (device->surface.used) {
572             aligned = (aligned + 63) & -64;
573             _copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned);
574
575             batch_num_relocations = device->batch.num_relocations;
576             if (device->surface.num_relocations) {
577                 assert (device->batch.num_relocations + device->surface.num_relocations < device->batch.max_relocations);
578
579                 memcpy (device->batch.relocations + device->batch.num_relocations,
580                         device->surface.relocations,
581                         sizeof (device->surface.relocations[0]) * device->surface.num_relocations);
582
583                 for (n = 0; n < device->surface.num_relocations; n++)
584                     device->batch.relocations[device->batch.num_relocations + n].offset += aligned;
585
586                 device->batch.num_relocations += device->surface.num_relocations;
587             }
588
589             aligned += device->surface.used;
590         }
591
592         aligned = (aligned + 63) & -64;
593         intel_bo_write (&device->intel, bo,
594                         aligned, device->batch.used,
595                         device->batch.data);
596
597         for (n = 0; n < batch_num_relocations; n++)
598             device->batch.relocations[n].offset += aligned;
599
600         if (device->exec.bo[device->exec.count-1] == bo) {
601             assert (bo->exec == &device->exec.exec[device->exec.count-1]);
602
603             bo->exec->relocation_count = device->batch.num_relocations;
604             bo->exec->relocs_ptr = (uintptr_t) device->batch.relocations;
605             intel_bo_destroy (&device->intel, bo);
606         } else {
607             assert (bo->exec ==  NULL);
608
609             n = device->exec.count++;
610             device->exec.exec[n].handle = bo->base.handle;
611             device->exec.exec[n].relocation_count = device->batch.num_relocations;
612             device->exec.exec[n].relocs_ptr = (uintptr_t) device->batch.relocations;
613             device->exec.exec[n].alignment = 0;
614             device->exec.exec[n].offset = 0;
615             device->exec.exec[n].flags = 0;
616             device->exec.exec[n].rsvd1 = 0;
617             device->exec.exec[n].rsvd2 = 0;
618
619             /* transfer ownership to the exec */
620             device->exec.bo[n] = bo;
621         }
622     } else {
623         i965_stream_commit (device, &device->vertex);
624         if (device->surface.used)
625             i965_stream_commit (device, &device->surface);
626
627         bo = intel_bo_create (&device->intel,
628                               device->batch.used, device->batch.used,
629                               FALSE, I915_TILING_NONE, 0);
630         if (unlikely (bo == NULL))
631             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
632
633         intel_bo_write (&device->intel, bo,
634                         0, device->batch.used,
635                         device->batch.data);
636
637         n = device->exec.count++;
638         device->exec.exec[n].handle = bo->base.handle;
639         device->exec.exec[n].relocation_count = device->batch.num_relocations;
640         device->exec.exec[n].relocs_ptr = (uintptr_t) device->batch.relocations;
641         device->exec.exec[n].alignment = 0;
642         device->exec.exec[n].offset = 0;
643         device->exec.exec[n].flags = 0;
644         device->exec.exec[n].rsvd1 = 0;
645         device->exec.exec[n].rsvd2 = 0;
646
647         /* transfer ownership to the exec */
648         device->exec.bo[n] = bo;
649         aligned = 0;
650     }
651
652     status = i965_exec (device, aligned);
653
654     i965_stream_reset (&device->vertex);
655     i965_stream_reset (&device->surface);
656     i965_stream_reset (&device->batch);
657
658     intel_glyph_cache_unpin (&device->intel);
659     intel_snapshot_cache_thaw (&device->intel);
660
661     i965_device_reset (device);
662
663     return status;
664 }
665
666 static cairo_surface_t *
667 i965_surface_create_similar (void *abstract_other,
668                              cairo_content_t content,
669                              int width, int height)
670 {
671     i965_surface_t *other;
672     cairo_format_t format;
673
674     if (width > 8192 || height > 8192)
675         return NULL;
676
677     other = abstract_other;
678     if (content == other->intel.drm.base.content)
679         format = other->intel.drm.format;
680     else
681         format = _cairo_format_from_content (content);
682
683     return i965_surface_create_internal ((cairo_drm_device_t *) other->intel.drm.base.device,
684                                          format,
685                                          width, height,
686                                          I965_TILING_DEFAULT, TRUE);
687 }
688
689 static cairo_status_t
690 i965_surface_finish (void *abstract_surface)
691 {
692     i965_surface_t *surface = abstract_surface;
693
694     return intel_surface_finish (&surface->intel);
695 }
696
697 static cairo_status_t
698 i965_surface_flush (void *abstract_surface)
699 {
700     i965_surface_t *surface = abstract_surface;
701     cairo_status_t status = CAIRO_STATUS_SUCCESS;
702
703     if (surface->intel.drm.fallback != NULL)
704         return intel_surface_flush (abstract_surface);
705
706     /* Forgo flushing on finish as the user cannot access the surface directly. */
707     if (! surface->intel.drm.base.finished &&
708         to_intel_bo (surface->intel.drm.bo)->exec != NULL)
709     {
710         status = cairo_device_acquire (surface->intel.drm.base.device);
711         if (likely (status == CAIRO_STATUS_SUCCESS)) {
712             i965_device_t *device;
713
714             device = i965_device (surface);
715             status = i965_device_flush (device);
716             cairo_device_release (&device->intel.base.base);
717         }
718     }
719
720     return status;
721 }
722
723 /* rasterisation */
724
725 static cairo_status_t
726 _composite_boxes_spans (void                            *closure,
727                         cairo_span_renderer_t           *renderer,
728                         const cairo_rectangle_int_t     *extents)
729 {
730     cairo_boxes_t *boxes = closure;
731     cairo_rectangular_scan_converter_t converter;
732     struct _cairo_boxes_chunk *chunk;
733     cairo_status_t status;
734
735     _cairo_rectangular_scan_converter_init (&converter, extents);
736     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
737         cairo_box_t *box = chunk->base;
738         int i;
739
740         for (i = 0; i < chunk->count; i++) {
741             status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
742             if (unlikely (status))
743                 goto CLEANUP;
744         }
745     }
746
747     status = converter.base.generate (&converter.base, renderer);
748
749   CLEANUP:
750     converter.base.destroy (&converter.base);
751     return status;
752 }
753
754 cairo_status_t
755 i965_fixup_unbounded (i965_surface_t *dst,
756                       const cairo_composite_rectangles_t *extents,
757                       cairo_clip_t *clip)
758 {
759     i965_shader_t shader;
760     i965_device_t *device;
761     cairo_status_t status;
762
763     i965_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR);
764
765     if (clip != NULL) {
766         cairo_region_t *clip_region = NULL;
767
768         status = _cairo_clip_get_region (clip, &clip_region);
769         assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
770         assert (clip_region == NULL);
771
772         if (status == CAIRO_INT_STATUS_UNSUPPORTED)
773             i965_shader_set_clip (&shader, clip);
774     } else {
775         if (extents->bounded.width  == extents->unbounded.width &&
776             extents->bounded.height == extents->unbounded.height)
777         {
778             return CAIRO_STATUS_SUCCESS;
779         }
780     }
781
782     status = i965_shader_acquire_pattern (&shader,
783                                           &shader.source,
784                                           &_cairo_pattern_clear.base,
785                                           &extents->unbounded);
786     if (unlikely (status)) {
787         i965_shader_fini (&shader);
788         return status;
789     }
790
791     device = i965_device (dst);
792     status = cairo_device_acquire (&device->intel.base.base);
793     if (unlikely (status))
794         return status;
795
796     status = i965_shader_commit (&shader, device);
797     if (unlikely (status)) {
798         goto BAIL;
799     }
800
801     if (extents->bounded.width == 0 || extents->bounded.height == 0) {
802         i965_shader_add_rectangle (&shader,
803                                    extents->unbounded.x,
804                                    extents->unbounded.y,
805                                    extents->unbounded.width,
806                                    extents->unbounded.height);
807     } else { /* top */
808         if (extents->bounded.y != extents->unbounded.y) {
809             cairo_rectangle_int_t rect;
810
811             rect.x = extents->unbounded.x;
812             rect.y = extents->unbounded.y;
813             rect.width  = extents->unbounded.width;
814             rect.height = extents->bounded.y - rect.y;
815
816             i965_shader_add_rectangle (&shader,
817                                        rect.x, rect.y,
818                                        rect.width, rect.height);
819         }
820
821         /* left */
822         if (extents->bounded.x != extents->unbounded.x) {
823             cairo_rectangle_int_t rect;
824
825             rect.x = extents->unbounded.x;
826             rect.y = extents->bounded.y;
827             rect.width  = extents->bounded.x - extents->unbounded.x;
828             rect.height = extents->bounded.height;
829
830             i965_shader_add_rectangle (&shader,
831                                        rect.x, rect.y,
832                                        rect.width, rect.height);
833         }
834
835         /* right */
836         if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
837             cairo_rectangle_int_t rect;
838
839             rect.x = extents->bounded.x + extents->bounded.width;
840             rect.y = extents->bounded.y;
841             rect.width  = extents->unbounded.x + extents->unbounded.width - rect.x;
842             rect.height = extents->bounded.height;
843
844             i965_shader_add_rectangle (&shader,
845                                        rect.x, rect.y,
846                                        rect.width, rect.height);
847         }
848
849         /* bottom */
850         if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
851             cairo_rectangle_int_t rect;
852
853             rect.x = extents->unbounded.x;
854             rect.y = extents->bounded.y + extents->bounded.height;
855             rect.width  = extents->unbounded.width;
856             rect.height = extents->unbounded.y + extents->unbounded.height - rect.y;
857
858             i965_shader_add_rectangle (&shader,
859                                        rect.x, rect.y,
860                                        rect.width, rect.height);
861         }
862     }
863
864     i965_shader_fini (&shader);
865   BAIL:
866     cairo_device_release (&device->intel.base.base);
867     return status;
868 }
869
870 static cairo_status_t
871 i965_fixup_unbounded_boxes (i965_surface_t *dst,
872                             const cairo_composite_rectangles_t *extents,
873                             cairo_clip_t *clip,
874                             cairo_boxes_t *boxes)
875 {
876     cairo_boxes_t clear;
877     cairo_box_t box;
878     cairo_region_t *clip_region = NULL;
879     cairo_status_t status;
880     struct _cairo_boxes_chunk *chunk;
881     i965_shader_t shader;
882     int i;
883
884     if (boxes->num_boxes <= 1)
885         return i965_fixup_unbounded (dst, extents, clip);
886
887     i965_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR);
888     if (clip != NULL) {
889         status = _cairo_clip_get_region (clip, &clip_region);
890         assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
891         if (status == CAIRO_INT_STATUS_UNSUPPORTED)
892             i965_shader_set_clip (&shader, clip);
893     }
894
895     status = i965_shader_acquire_pattern (&shader,
896                                           &shader.source,
897                                           &_cairo_pattern_clear.base,
898                                           &extents->unbounded);
899     if (unlikely (status)) {
900         i965_shader_fini (&shader);
901         return status;
902     }
903
904     _cairo_boxes_init (&clear);
905
906     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
907     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
908     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
909     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
910
911     if (clip_region == NULL) {
912         cairo_boxes_t tmp;
913
914         _cairo_boxes_init (&tmp);
915
916         status = _cairo_boxes_add (&tmp, &box);
917         assert (status == CAIRO_STATUS_SUCCESS);
918
919         tmp.chunks.next = &boxes->chunks;
920         tmp.num_boxes += boxes->num_boxes;
921
922         status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
923                                                           CAIRO_FILL_RULE_WINDING,
924                                                           &clear);
925
926         tmp.chunks.next = NULL;
927     } else {
928         pixman_box32_t *pbox;
929
930         pbox = pixman_region32_rectangles (&clip_region->rgn, &i);
931         _cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i);
932
933         status = _cairo_boxes_add (&clear, &box);
934         assert (status == CAIRO_STATUS_SUCCESS);
935
936         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
937             for (i = 0; i < chunk->count; i++) {
938                 status = _cairo_boxes_add (&clear, &chunk->base[i]);
939                 if (unlikely (status)) {
940                     _cairo_boxes_fini (&clear);
941                     return status;
942                 }
943             }
944         }
945
946         status = _cairo_bentley_ottmann_tessellate_boxes (&clear,
947                                                           CAIRO_FILL_RULE_WINDING,
948                                                           &clear);
949     }
950
951     if (likely (status == CAIRO_STATUS_SUCCESS && clear.num_boxes)) {
952         i965_device_t *device;
953
954         device = i965_device (dst);
955         status = cairo_device_acquire (&device->intel.base.base);
956         if (unlikely (status))
957             goto err_shader;
958
959         status = i965_shader_commit (&shader, device);
960         if (unlikely (status))
961             goto err_device;
962
963         for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) {
964             for (i = 0; i < chunk->count; i++) {
965                 int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
966                 int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
967                 int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
968                 int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
969
970                 i965_shader_add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
971             }
972         }
973
974 err_device:
975         cairo_device_release (&device->intel.base.base);
976 err_shader:
977         i965_shader_fini (&shader);
978     }
979
980     _cairo_boxes_fini (&clear);
981
982     return status;
983 }
984
985 static cairo_status_t
986 _composite_boxes (i965_surface_t *dst,
987                   cairo_operator_t op,
988                   const cairo_pattern_t *pattern,
989                   cairo_boxes_t *boxes,
990                   cairo_antialias_t antialias,
991                   cairo_clip_t *clip,
992                   const cairo_composite_rectangles_t *extents)
993 {
994     cairo_bool_t need_clip_surface = FALSE;
995     cairo_region_t *clip_region = NULL;
996     const struct _cairo_boxes_chunk *chunk;
997     cairo_status_t status;
998     i965_shader_t shader;
999     i965_device_t *device;
1000     int i;
1001
1002     /* If the boxes are not pixel-aligned, we will need to compute a real mask */
1003     if (antialias != CAIRO_ANTIALIAS_NONE) {
1004         if (! boxes->is_pixel_aligned)
1005             return CAIRO_INT_STATUS_UNSUPPORTED;
1006     }
1007
1008     i965_shader_init (&shader, dst, op);
1009
1010     status = i965_shader_acquire_pattern (&shader,
1011                                           &shader.source,
1012                                           pattern,
1013                                           &extents->bounded);
1014     if (unlikely (status))
1015         return status;
1016
1017     if (clip != NULL) {
1018         status = _cairo_clip_get_region (clip, &clip_region);
1019         assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
1020         need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
1021         if (need_clip_surface)
1022             i965_shader_set_clip (&shader, clip);
1023     }
1024
1025     device = i965_device (dst);
1026     status = cairo_device_acquire (&device->intel.base.base);
1027     if (unlikely (status))
1028         goto err_shader;
1029
1030     status = i965_shader_commit (&shader, i965_device (dst));
1031     if (unlikely (status))
1032         goto err_device;
1033
1034     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1035         cairo_box_t *box = chunk->base;
1036         for (i = 0; i < chunk->count; i++) {
1037             int x1 = _cairo_fixed_integer_round (box[i].p1.x);
1038             int y1 = _cairo_fixed_integer_round (box[i].p1.y);
1039             int x2 = _cairo_fixed_integer_round (box[i].p2.x);
1040             int y2 = _cairo_fixed_integer_round (box[i].p2.y);
1041
1042             if (x2 > x1 && y2 > y1)
1043                 i965_shader_add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
1044         }
1045     }
1046
1047     if (! extents->is_bounded)
1048         status = i965_fixup_unbounded_boxes (dst, extents, clip, boxes);
1049
1050   err_device:
1051     cairo_device_release (&device->intel.base.base);
1052   err_shader:
1053     i965_shader_fini (&shader);
1054
1055     return status;
1056 }
1057
1058 static cairo_status_t
1059 _clip_and_composite_boxes (i965_surface_t *dst,
1060                            cairo_operator_t op,
1061                            const cairo_pattern_t *src,
1062                            cairo_boxes_t *boxes,
1063                            cairo_antialias_t antialias,
1064                            const cairo_composite_rectangles_t *extents,
1065                            cairo_clip_t *clip)
1066 {
1067     cairo_status_t status;
1068
1069     if (boxes->num_boxes == 0) {
1070         if (extents->is_bounded)
1071             return CAIRO_STATUS_SUCCESS;
1072
1073         return i965_fixup_unbounded (dst, extents, clip);
1074     }
1075
1076     /* Use a fast path if the boxes are pixel aligned */
1077     status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
1078     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1079         return status;
1080
1081     /* Otherwise render the boxes via an implicit mask and composite in the usual
1082      * fashion.
1083      */
1084     return i965_clip_and_composite_spans (dst, op, src, antialias,
1085                                           _composite_boxes_spans, boxes,
1086                                           extents, clip);
1087 }
1088
1089 static cairo_int_status_t
1090 i965_surface_paint (void                        *abstract_dst,
1091                     cairo_operator_t             op,
1092                     const cairo_pattern_t       *source,
1093                     cairo_clip_t                *clip)
1094 {
1095     i965_surface_t *dst = abstract_dst;
1096     cairo_composite_rectangles_t extents;
1097     cairo_boxes_t boxes;
1098     cairo_box_t *clip_boxes = boxes.boxes_embedded;
1099     cairo_clip_t local_clip;
1100     cairo_bool_t have_clip = FALSE;
1101     int num_boxes = ARRAY_LENGTH (boxes.boxes_embedded);
1102     cairo_status_t status;
1103
1104     /* XXX unsupported operators? use pixel shader blending, eventually */
1105
1106     status = _cairo_composite_rectangles_init_for_paint (&extents,
1107                                                          dst->intel.drm.width,
1108                                                          dst->intel.drm.height,
1109                                                          op, source,
1110                                                          clip);
1111     if (unlikely (status))
1112         return status;
1113
1114     if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
1115         clip = NULL;
1116
1117     if (clip != NULL) {
1118         clip = _cairo_clip_init_copy (&local_clip, clip);
1119         have_clip = TRUE;
1120     }
1121
1122     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
1123     if (unlikely (status)) {
1124         if (have_clip)
1125             _cairo_clip_fini (&local_clip);
1126
1127         return status;
1128     }
1129
1130     _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
1131     status = _clip_and_composite_boxes (dst, op, source,
1132                                         &boxes, CAIRO_ANTIALIAS_DEFAULT,
1133                                         &extents, clip);
1134     if (clip_boxes != boxes.boxes_embedded)
1135         free (clip_boxes);
1136
1137     if (have_clip)
1138         _cairo_clip_fini (&local_clip);
1139
1140     return status;
1141 }
1142
1143 static cairo_int_status_t
1144 i965_surface_mask (void                         *abstract_dst,
1145                    cairo_operator_t              op,
1146                    const cairo_pattern_t        *source,
1147                    const cairo_pattern_t        *mask,
1148                    cairo_clip_t                 *clip)
1149 {
1150     i965_surface_t *dst = abstract_dst;
1151     cairo_composite_rectangles_t extents;
1152     i965_shader_t shader;
1153     i965_device_t *device;
1154     cairo_clip_t local_clip;
1155     cairo_region_t *clip_region = NULL;
1156     cairo_bool_t need_clip_surface = FALSE;
1157     cairo_bool_t have_clip = FALSE;
1158     cairo_status_t status;
1159
1160     status = _cairo_composite_rectangles_init_for_mask (&extents,
1161                                                         dst->intel.drm.width,
1162                                                         dst->intel.drm.height,
1163                                                         op, source, mask, clip);
1164     if (unlikely (status))
1165         return status;
1166
1167     if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
1168         clip = NULL;
1169
1170     if (clip != NULL && extents.is_bounded) {
1171         clip = _cairo_clip_init_copy (&local_clip, clip);
1172         status = _cairo_clip_rectangle (clip, &extents.bounded);
1173         if (unlikely (status)) {
1174             _cairo_clip_fini (&local_clip);
1175             return status;
1176         }
1177
1178         have_clip = TRUE;
1179     }
1180
1181     i965_shader_init (&shader, dst, op);
1182
1183     status = i965_shader_acquire_pattern (&shader,
1184                                           &shader.source,
1185                                           source,
1186                                           &extents.bounded);
1187     if (unlikely (status))
1188         goto err_shader;
1189
1190     status = i965_shader_acquire_pattern (&shader,
1191                                           &shader.mask,
1192                                           mask,
1193                                           &extents.bounded);
1194     if (unlikely (status))
1195         goto err_shader;
1196
1197     if (clip != NULL) {
1198         status = _cairo_clip_get_region (clip, &clip_region);
1199         assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
1200         need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
1201         if (need_clip_surface)
1202             i965_shader_set_clip (&shader, clip);
1203     }
1204
1205     device = i965_device (dst);
1206     status = cairo_device_acquire (&device->intel.base.base);
1207     if (unlikely (status))
1208         goto err_shader;
1209
1210     status = i965_shader_commit (&shader, device);
1211     if (unlikely (status))
1212         goto err_device;
1213
1214     if (clip_region != NULL) {
1215         unsigned int n, num_rectangles;
1216
1217         num_rectangles = cairo_region_num_rectangles (clip_region);
1218         for (n = 0; n < num_rectangles; n++) {
1219             cairo_rectangle_int_t rect;
1220
1221             cairo_region_get_rectangle (clip_region, n, &rect);
1222
1223             i965_shader_add_rectangle (&shader,
1224                                        rect.x, rect.y,
1225                                        rect.width, rect.height);
1226         }
1227     } else {
1228         i965_shader_add_rectangle (&shader,
1229                                    extents.bounded.x,
1230                                    extents.bounded.y,
1231                                    extents.bounded.width,
1232                                    extents.bounded.height);
1233     }
1234
1235     if (! extents.is_bounded)
1236         status = i965_fixup_unbounded (dst, &extents, clip);
1237
1238   err_device:
1239     cairo_device_release (&device->intel.base.base);
1240   err_shader:
1241     i965_shader_fini (&shader);
1242     if (have_clip)
1243         _cairo_clip_fini (&local_clip);
1244
1245     return status;
1246 }
1247
1248 typedef struct {
1249     cairo_polygon_t             polygon;
1250     cairo_fill_rule_t            fill_rule;
1251     cairo_antialias_t            antialias;
1252 } composite_polygon_info_t;
1253
1254 static cairo_status_t
1255 _composite_polygon_spans (void                          *closure,
1256                           cairo_span_renderer_t         *renderer,
1257                           const cairo_rectangle_int_t   *extents)
1258 {
1259     composite_polygon_info_t *info = closure;
1260     cairo_botor_scan_converter_t converter;
1261     cairo_status_t status;
1262     cairo_box_t box;
1263
1264     box.p1.x = _cairo_fixed_from_int (extents->x);
1265     box.p1.y = _cairo_fixed_from_int (extents->y);
1266     box.p2.x = _cairo_fixed_from_int (extents->x + extents->width);
1267     box.p2.y = _cairo_fixed_from_int (extents->y + extents->height);
1268
1269     _cairo_botor_scan_converter_init (&converter, &box, info->fill_rule);
1270
1271     status = converter.base.add_polygon (&converter.base, &info->polygon);
1272     if (likely (status == CAIRO_STATUS_SUCCESS))
1273         status = converter.base.generate (&converter.base, renderer);
1274
1275     converter.base.destroy (&converter.base);
1276
1277     return status;
1278 }
1279
1280 static cairo_int_status_t
1281 i965_surface_stroke (void                       *abstract_dst,
1282                      cairo_operator_t            op,
1283                      const cairo_pattern_t      *source,
1284                      cairo_path_fixed_t         *path,
1285                      const cairo_stroke_style_t *stroke_style,
1286                      const cairo_matrix_t       *ctm,
1287                      const cairo_matrix_t       *ctm_inverse,
1288                      double                      tolerance,
1289                      cairo_antialias_t           antialias,
1290                      cairo_clip_t               *clip)
1291 {
1292     i965_surface_t *dst = abstract_dst;
1293     cairo_composite_rectangles_t extents;
1294     composite_polygon_info_t info;
1295     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
1296     int num_boxes = ARRAY_LENGTH (boxes_stack);
1297     cairo_clip_t local_clip;
1298     cairo_bool_t have_clip = FALSE;
1299     cairo_status_t status;
1300
1301     status = _cairo_composite_rectangles_init_for_stroke (&extents,
1302                                                           dst->intel.drm.width,
1303                                                           dst->intel.drm.height,
1304                                                           op, source,
1305                                                           path, stroke_style, ctm,
1306                                                           clip);
1307     if (unlikely (status))
1308         return status;
1309
1310     if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
1311         clip = NULL;
1312
1313     if (clip != NULL) {
1314         clip = _cairo_clip_init_copy (&local_clip, clip);
1315         have_clip = TRUE;
1316     }
1317
1318     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
1319     if (unlikely (status)) {
1320         if (have_clip)
1321             _cairo_clip_fini (&local_clip);
1322
1323         return status;
1324     }
1325
1326     if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
1327         cairo_boxes_t boxes;
1328
1329         _cairo_boxes_init (&boxes);
1330         _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
1331         status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
1332                                                                 stroke_style,
1333                                                                 ctm,
1334                                                                 &boxes);
1335         if (likely (status == CAIRO_STATUS_SUCCESS)) {
1336             status = _clip_and_composite_boxes (dst, op, source,
1337                                                 &boxes, antialias,
1338                                                 &extents, clip);
1339         }
1340
1341         _cairo_boxes_fini (&boxes);
1342
1343         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1344             goto CLEANUP_BOXES;
1345     }
1346
1347     _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes);
1348
1349     status = _cairo_path_fixed_stroke_to_polygon (path,
1350                                                   stroke_style,
1351                                                   ctm, ctm_inverse,
1352                                                   tolerance,
1353                                                   &info.polygon);
1354     if (unlikely (status))
1355         goto CLEANUP_POLYGON;
1356
1357     if (extents.is_bounded) {
1358         cairo_rectangle_int_t rect;
1359
1360         _cairo_box_round_to_rectangle (&info.polygon.extents, &rect);
1361         if (! _cairo_rectangle_intersect (&extents.bounded, &rect))
1362             goto CLEANUP_POLYGON;
1363     }
1364
1365     if (info.polygon.num_edges == 0) {
1366         if (! extents.is_bounded)
1367             status = i965_fixup_unbounded (dst, &extents, clip);
1368     } else {
1369         info.fill_rule = CAIRO_FILL_RULE_WINDING;
1370         info.antialias = antialias;
1371         status = i965_clip_and_composite_spans (dst, op, source, antialias,
1372                                                 _composite_polygon_spans, &info,
1373                                                 &extents, clip);
1374     }
1375
1376 CLEANUP_POLYGON:
1377     _cairo_polygon_fini (&info.polygon);
1378
1379 CLEANUP_BOXES:
1380     if (clip_boxes != boxes_stack)
1381         free (clip_boxes);
1382
1383     if (have_clip)
1384         _cairo_clip_fini (&local_clip);
1385
1386     return status;
1387 }
1388
1389 static cairo_int_status_t
1390 i965_surface_fill (void                 *abstract_dst,
1391                    cairo_operator_t      op,
1392                    const cairo_pattern_t*source,
1393                    cairo_path_fixed_t   *path,
1394                    cairo_fill_rule_t     fill_rule,
1395                    double                tolerance,
1396                    cairo_antialias_t     antialias,
1397                    cairo_clip_t         *clip)
1398 {
1399     i965_surface_t *dst = abstract_dst;
1400     cairo_composite_rectangles_t extents;
1401     composite_polygon_info_t info;
1402     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
1403     cairo_clip_t local_clip;
1404     cairo_bool_t have_clip = FALSE;
1405     int num_boxes = ARRAY_LENGTH (boxes_stack);
1406     cairo_status_t status;
1407
1408     status = _cairo_composite_rectangles_init_for_fill (&extents,
1409                                                         dst->intel.drm.width,
1410                                                         dst->intel.drm.height,
1411                                                         op, source, path,
1412                                                         clip);
1413     if (unlikely (status))
1414         return status;
1415
1416     if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
1417         clip = NULL;
1418
1419     if (clip != NULL) {
1420         clip = _cairo_clip_init_copy (&local_clip, clip);
1421         have_clip = TRUE;
1422     }
1423
1424     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
1425     if (unlikely (status)) {
1426         if (have_clip)
1427             _cairo_clip_fini (&local_clip);
1428
1429         return status;
1430     }
1431
1432     assert (! _cairo_path_fixed_fill_is_empty (path));
1433
1434     if (_cairo_path_fixed_fill_is_rectilinear (path)) {
1435         cairo_boxes_t boxes;
1436
1437         _cairo_boxes_init (&boxes);
1438         _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
1439         status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
1440                                                               fill_rule,
1441                                                               &boxes);
1442         if (likely (status == CAIRO_STATUS_SUCCESS)) {
1443             status = _clip_and_composite_boxes (dst, op, source,
1444                                                 &boxes, antialias,
1445                                                 &extents, clip);
1446         }
1447
1448         _cairo_boxes_fini (&boxes);
1449
1450         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1451             goto CLEANUP_BOXES;
1452     }
1453
1454     _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes);
1455
1456     status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &info.polygon);
1457     if (unlikely (status))
1458         goto CLEANUP_POLYGON;
1459
1460     if (extents.is_bounded) {
1461         cairo_rectangle_int_t rect;
1462
1463         _cairo_box_round_to_rectangle (&info.polygon.extents, &rect);
1464         if (! _cairo_rectangle_intersect (&extents.bounded, &rect))
1465             goto CLEANUP_POLYGON;
1466     }
1467
1468     if (info.polygon.num_edges == 0) {
1469         if (! extents.is_bounded)
1470             status = i965_fixup_unbounded (dst, &extents, clip);
1471     } else {
1472         info.fill_rule = fill_rule;
1473         info.antialias = antialias;
1474         status = i965_clip_and_composite_spans (dst, op, source, antialias,
1475                                                 _composite_polygon_spans, &info,
1476                                                 &extents, clip);
1477     }
1478
1479 CLEANUP_POLYGON:
1480     _cairo_polygon_fini (&info.polygon);
1481
1482 CLEANUP_BOXES:
1483     if (clip_boxes != boxes_stack)
1484         free (clip_boxes);
1485
1486     if (have_clip)
1487         _cairo_clip_fini (&local_clip);
1488
1489     return status;
1490 }
1491
1492 static const cairo_surface_backend_t i965_surface_backend = {
1493     CAIRO_SURFACE_TYPE_DRM,
1494     _cairo_default_context_create,
1495
1496     i965_surface_create_similar,
1497     i965_surface_finish,
1498     intel_surface_acquire_source_image,
1499     intel_surface_release_source_image,
1500
1501     NULL, NULL, NULL,
1502     NULL, /* composite */
1503     NULL, /* fill */
1504     NULL, /* trapezoids */
1505     NULL, /* span */
1506     NULL, /* check-span */
1507
1508     NULL, /* copy_page */
1509     NULL, /* show_page */
1510     _cairo_drm_surface_get_extents,
1511     NULL, /* old-glyphs */
1512     _cairo_drm_surface_get_font_options,
1513
1514     i965_surface_flush,
1515     NULL, /* mark_dirty */
1516     intel_scaled_font_fini,
1517     intel_scaled_glyph_fini,
1518
1519     i965_surface_paint,
1520     i965_surface_mask,
1521     i965_surface_stroke,
1522     i965_surface_fill,
1523     i965_surface_glyphs,
1524 };
1525
1526 static void
1527 i965_surface_init (i965_surface_t *surface,
1528                    cairo_drm_device_t *device,
1529                    cairo_format_t format,
1530                    int width, int height)
1531 {
1532     intel_surface_init (&surface->intel, &i965_surface_backend, device,
1533                         format, width, height);
1534     surface->stream = 0;
1535 }
1536
1537 static inline int cairo_const
1538 i965_tiling_stride (uint32_t tiling, int stride)
1539 {
1540     if (tiling == I915_TILING_NONE)
1541         return stride;
1542
1543     return (stride + 127) & -128;
1544 }
1545
1546 static inline int cairo_const
1547 i965_tiling_height (uint32_t tiling, int height)
1548 {
1549     switch (tiling) {
1550     default:
1551     case I915_TILING_NONE: return (height + 1) & -2;
1552     case I915_TILING_X: return (height + 7) & -8;
1553     case I915_TILING_Y: return (height + 31) & -32;
1554     }
1555 }
1556
1557 cairo_surface_t *
1558 i965_surface_create_internal (cairo_drm_device_t *base_dev,
1559                               cairo_format_t format,
1560                               int width, int height,
1561                               uint32_t tiling,
1562                               cairo_bool_t gpu_target)
1563 {
1564     i965_surface_t *surface;
1565     cairo_status_t status_ignored;
1566
1567     surface = malloc (sizeof (i965_surface_t));
1568     if (unlikely (surface == NULL))
1569         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1570
1571     i965_surface_init (surface, base_dev, format, width, height);
1572
1573     if (width && height) {
1574         uint32_t size, stride;
1575         intel_bo_t *bo;
1576
1577         width = (width + 3) & -4;
1578         stride = cairo_format_stride_for_width (surface->intel.drm.format, width);
1579         stride = (stride + 63) & ~63;
1580         stride = i965_tiling_stride (tiling, stride);
1581         surface->intel.drm.stride = stride;
1582
1583         height = i965_tiling_height (tiling, height);
1584         assert (height <= I965_MAX_SIZE);
1585
1586         size = stride * height;
1587         bo = intel_bo_create (to_intel_device (&base_dev->base),
1588                               size, size,
1589                               gpu_target, tiling, stride);
1590         if (bo == NULL) {
1591             status_ignored = _cairo_drm_surface_finish (&surface->intel.drm);
1592             free (surface);
1593             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1594         }
1595
1596         bo->tiling = tiling;
1597         bo->stride = stride;
1598         surface->intel.drm.bo = &bo->base;
1599
1600         assert (bo->base.size >= (size_t) stride*height);
1601     }
1602
1603     return &surface->intel.drm.base;
1604 }
1605
1606 static cairo_surface_t *
1607 i965_surface_create (cairo_drm_device_t *device,
1608                      cairo_format_t format, int width, int height)
1609 {
1610     switch (format) {
1611     case CAIRO_FORMAT_ARGB32:
1612     case CAIRO_FORMAT_RGB16_565:
1613     case CAIRO_FORMAT_RGB24:
1614     case CAIRO_FORMAT_A8:
1615         break;
1616     case CAIRO_FORMAT_INVALID:
1617     default:
1618     case CAIRO_FORMAT_A1:
1619         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1620     }
1621
1622     return i965_surface_create_internal (device, format, width, height,
1623                                          I965_TILING_DEFAULT, TRUE);
1624 }
1625
1626 static cairo_surface_t *
1627 i965_surface_create_for_name (cairo_drm_device_t *base_dev,
1628                               unsigned int name,
1629                               cairo_format_t format,
1630                               int width, int height, int stride)
1631 {
1632     i965_device_t *device;
1633     i965_surface_t *surface;
1634     cairo_status_t status_ignored;
1635     int min_stride;
1636
1637     min_stride = cairo_format_stride_for_width (format, (width + 3) & -4);
1638     if (stride < min_stride || stride & 63)
1639         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
1640
1641     if (format == CAIRO_FORMAT_A1)
1642         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1643
1644     switch (format) {
1645     case CAIRO_FORMAT_ARGB32:
1646     case CAIRO_FORMAT_RGB16_565:
1647     case CAIRO_FORMAT_RGB24:
1648     case CAIRO_FORMAT_A8:
1649         break;
1650     case CAIRO_FORMAT_INVALID:
1651     default:
1652     case CAIRO_FORMAT_A1:
1653         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1654     }
1655
1656     surface = malloc (sizeof (i965_surface_t));
1657     if (unlikely (surface == NULL))
1658         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1659
1660     i965_surface_init (surface, base_dev, format, width, height);
1661
1662     device = (i965_device_t *) base_dev;
1663     surface->intel.drm.bo = &intel_bo_create_for_name (&device->intel, name)->base;
1664     if (unlikely (surface->intel.drm.bo == NULL)) {
1665         status_ignored = _cairo_drm_surface_finish (&surface->intel.drm);
1666         free (surface);
1667         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1668     }
1669
1670     surface->intel.drm.stride = stride;
1671
1672     return &surface->intel.drm.base;
1673 }
1674
1675 static cairo_status_t
1676 i965_surface_enable_scan_out (void *abstract_surface)
1677 {
1678     i965_surface_t *surface = abstract_surface;
1679     intel_bo_t *bo;
1680
1681     if (unlikely (surface->intel.drm.bo == NULL))
1682         return _cairo_error (CAIRO_STATUS_INVALID_SIZE);
1683
1684     bo = to_intel_bo (surface->intel.drm.bo);
1685     if (bo->tiling != I915_TILING_X) {
1686         i965_device_t *device = i965_device (surface);
1687         cairo_surface_pattern_t pattern;
1688         cairo_surface_t *clone;
1689         cairo_status_t status;
1690
1691         clone = i965_surface_create_internal (&device->intel.base,
1692                                               surface->intel.drm.base.content,
1693                                               surface->intel.drm.width,
1694                                               surface->intel.drm.height,
1695                                               I915_TILING_X,
1696                                               TRUE);
1697         if (unlikely (clone->status))
1698             return clone->status;
1699
1700         /* 2D blit? */
1701         _cairo_pattern_init_for_surface (&pattern, &surface->intel.drm.base);
1702         pattern.base.filter = CAIRO_FILTER_NEAREST;
1703
1704         status = _cairo_surface_paint (clone,
1705                                        CAIRO_OPERATOR_SOURCE,
1706                                        &pattern.base,
1707                                        NULL);
1708
1709         _cairo_pattern_fini (&pattern.base);
1710
1711         if (unlikely (status)) {
1712             cairo_surface_destroy (clone);
1713             return status;
1714         }
1715
1716         /* swap buffer objects */
1717         surface->intel.drm.bo = ((cairo_drm_surface_t *) clone)->bo;
1718         ((cairo_drm_surface_t *) clone)->bo = &bo->base;
1719         bo = to_intel_bo (surface->intel.drm.bo);
1720
1721         cairo_surface_destroy (clone);
1722     }
1723
1724     if (unlikely (bo->tiling == I915_TILING_Y))
1725         return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
1726
1727     return CAIRO_STATUS_SUCCESS;
1728 }
1729
1730 static cairo_int_status_t
1731 _i965_device_flush (cairo_drm_device_t *device)
1732 {
1733     cairo_status_t status;
1734
1735     if (unlikely (device->base.finished))
1736         return CAIRO_STATUS_SUCCESS;
1737
1738     status = cairo_device_acquire (&device->base);
1739     if (likely (status == CAIRO_STATUS_SUCCESS))
1740         status = i965_device_flush ((i965_device_t *) device);
1741
1742     cairo_device_release (&device->base);
1743
1744     return status;
1745 }
1746
1747 static cairo_int_status_t
1748 _i965_device_throttle (cairo_drm_device_t *device)
1749 {
1750     cairo_status_t status;
1751
1752     status = cairo_device_acquire (&device->base);
1753     if (unlikely (status))
1754         return status;
1755
1756     status = i965_device_flush ((i965_device_t *) device);
1757     intel_throttle ((intel_device_t *) device);
1758
1759     cairo_device_release (&device->base);
1760
1761     return status;
1762 }
1763
1764 static void
1765 _i965_device_destroy (void *base)
1766 {
1767     i965_device_t *device = base;
1768
1769     i965_device_reset (device);
1770     i965_general_state_reset (device);
1771
1772     _cairo_hash_table_destroy (device->sf_states);
1773     _cairo_hash_table_destroy (device->samplers);
1774     _cairo_hash_table_destroy (device->cc_states);
1775     _cairo_hash_table_destroy (device->wm_kernels);
1776     _cairo_hash_table_destroy (device->wm_states);
1777     _cairo_hash_table_destroy (device->wm_bindings);
1778
1779     _cairo_freelist_fini (&device->sf_freelist);
1780     _cairo_freelist_fini (&device->cc_freelist);
1781     _cairo_freelist_fini (&device->wm_kernel_freelist);
1782     _cairo_freelist_fini (&device->wm_state_freelist);
1783     _cairo_freelist_fini (&device->wm_binding_freelist);
1784     _cairo_freelist_fini (&device->sampler_freelist);
1785
1786     intel_device_fini (&device->intel);
1787     free (device);
1788 }
1789
1790 static cairo_bool_t
1791 hash_equal (const void *A, const void *B)
1792 {
1793     const cairo_hash_entry_t *a = A, *b = B;
1794     return a->hash == b->hash;
1795 }
1796
1797 cairo_drm_device_t *
1798 _cairo_drm_i965_device_create (int fd, dev_t dev, int vendor_id, int chip_id)
1799 {
1800     i965_device_t *device;
1801     uint64_t gtt_size;
1802     cairo_status_t status;
1803
1804     if (! intel_info (fd, &gtt_size))
1805         return  NULL;
1806
1807     device = malloc (sizeof (i965_device_t));
1808     if (unlikely (device == NULL))
1809         return (cairo_drm_device_t *) _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
1810
1811     status = intel_device_init (&device->intel, fd);
1812     if (unlikely (status))
1813         goto CLEANUP;
1814
1815     device->is_g4x = IS_G4X (chip_id);
1816     //device->is_g5x = IS_G5X (chip_id);
1817
1818     device->intel.base.surface.create = i965_surface_create;
1819     device->intel.base.surface.create_for_name = i965_surface_create_for_name;
1820     device->intel.base.surface.create_from_cacheable_image = NULL;
1821     device->intel.base.surface.enable_scan_out = i965_surface_enable_scan_out;
1822
1823     device->intel.base.device.flush = _i965_device_flush;
1824     device->intel.base.device.throttle = _i965_device_throttle;
1825     device->intel.base.device.destroy = _i965_device_destroy;
1826
1827     device->sf_states = _cairo_hash_table_create (i965_sf_state_equal);
1828     if (unlikely (device->sf_states == NULL))
1829         goto CLEANUP_INTEL;
1830
1831     _cairo_freelist_init (&device->sf_freelist,
1832                           sizeof (struct i965_sf_state));
1833
1834
1835     device->cc_states = _cairo_hash_table_create (i965_cc_state_equal);
1836     if (unlikely (device->cc_states == NULL))
1837         goto CLEANUP_SF;
1838
1839     _cairo_freelist_init (&device->cc_freelist,
1840                           sizeof (struct i965_cc_state));
1841
1842
1843     device->wm_kernels = _cairo_hash_table_create (hash_equal);
1844     if (unlikely (device->wm_kernels == NULL))
1845         goto CLEANUP_CC;
1846
1847     _cairo_freelist_init (&device->wm_kernel_freelist,
1848                           sizeof (struct i965_wm_kernel));
1849
1850     device->wm_states = _cairo_hash_table_create (i965_wm_state_equal);
1851     if (unlikely (device->wm_states == NULL))
1852         goto CLEANUP_WM_KERNEL;
1853
1854     _cairo_freelist_init (&device->wm_state_freelist,
1855                           sizeof (struct i965_wm_state));
1856
1857
1858     device->wm_bindings = _cairo_hash_table_create (i965_wm_binding_equal);
1859     if (unlikely (device->wm_bindings == NULL))
1860         goto CLEANUP_WM_STATE;
1861
1862     _cairo_freelist_init (&device->wm_binding_freelist,
1863                           sizeof (struct i965_wm_binding));
1864
1865     device->samplers = _cairo_hash_table_create (hash_equal);
1866     if (unlikely (device->samplers == NULL))
1867         goto CLEANUP_WM_BINDING;
1868
1869     _cairo_freelist_init (&device->sampler_freelist,
1870                           sizeof (struct i965_sampler));
1871
1872     i965_stream_init (&device->batch,
1873                       device->batch_base, sizeof (device->batch_base),
1874                       NULL, 0,
1875                       device->batch_relocations,
1876                       ARRAY_LENGTH (device->batch_relocations));
1877
1878     i965_stream_init (&device->surface,
1879                       device->surface_base, sizeof (device->surface_base),
1880                       device->surface_pending_relocations,
1881                       ARRAY_LENGTH (device->surface_pending_relocations),
1882                       device->surface_relocations,
1883                       ARRAY_LENGTH (device->surface_relocations));
1884
1885     i965_stream_init (&device->general,
1886                       device->general_base, sizeof (device->general_base),
1887                       device->general_pending_relocations,
1888                       ARRAY_LENGTH (device->general_pending_relocations),
1889                       NULL, 0);
1890
1891     i965_stream_init (&device->vertex,
1892                       device->vertex_base, sizeof (device->vertex_base),
1893                       device->vertex_pending_relocations,
1894                       ARRAY_LENGTH (device->vertex_pending_relocations),
1895                       NULL, 0);
1896
1897     cairo_list_init (&device->flush);
1898     i965_device_reset (device);
1899     device->vs_offset = (uint32_t) -1;
1900     device->border_color_offset = (uint32_t) -1;
1901     device->general_state = NULL;
1902
1903     return _cairo_drm_device_init (&device->intel.base,
1904                                    fd, dev, vendor_id, chip_id,
1905                                    I965_MAX_SIZE);
1906
1907   CLEANUP_WM_BINDING:
1908     _cairo_hash_table_destroy (device->wm_bindings);
1909   CLEANUP_WM_STATE:
1910     _cairo_hash_table_destroy (device->wm_states);
1911   CLEANUP_WM_KERNEL:
1912     _cairo_hash_table_destroy (device->wm_kernels);
1913   CLEANUP_CC:
1914     _cairo_hash_table_destroy (device->cc_states);
1915   CLEANUP_SF:
1916     _cairo_hash_table_destroy (device->sf_states);
1917   CLEANUP_INTEL:
1918     intel_device_fini (&device->intel);
1919   CLEANUP:
1920     free (device);
1921     return (cairo_drm_device_t *) _cairo_device_create_in_error (status);
1922 }