Upload Tizen2.0 source
[framework/graphics/cairo.git] / src / drm / cairo-drm-i915-surface.c
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Chris Wilson
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  * **************************************************************************
29  * This work was initially based upon xf86-video-intel/src/i915_render.c:
30  * Copyright © 2006 Intel Corporation
31  *
32  * Permission is hereby granted, free of charge, to any person obtaining a
33  * copy of this software and associated documentation files (the "Software"),
34  * to deal in the Software without restriction, including without limitation
35  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
36  * and/or sell copies of the Software, and to permit persons to whom the
37  * Software is furnished to do so, subject to the following conditions:
38  *
39  * The above copyright notice and this permission notice (including the next
40  * paragraph) shall be included in all copies or substantial portions of the
41  * Software.
42  *
43  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
46  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
49  * SOFTWARE.
50  *
51  * Authors:
52  *    Wang Zhenyu <zhenyu.z.wang@intel.com>
53  *    Eric Anholt <eric@anholt.net>
54  *
55  * **************************************************************************
56  * and also upon libdrm/intel/intel_bufmgr_gem.c:
57  * Copyright © 2007 Red Hat Inc.
58  * Copyright © 2007 Intel Corporation
59  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
60  * All Rights Reserved.
61  *
62  * Permission is hereby granted, free of charge, to any person obtaining a
63  * copy of this software and associated documentation files (the
64  * "Software"), to deal in the Software without restriction, including
65  * without limitation the rights to use, copy, modify, merge, publish,
66  * distribute, sub license, and/or sell copies of the Software, and to
67  * permit persons to whom the Software is furnished to do so, subject to
68  * the following conditions:
69  *
70  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
73  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
74  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
75  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
76  * USE OR OTHER DEALINGS IN THE SOFTWARE.
77  *
78  * The above copyright notice and this permission notice (including the
79  * next paragraph) shall be included in all copies or substantial portions
80  * of the Software.
81  *
82  * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
83  *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
84  *          Eric Anholt <eric@anholt.net>
85  *          Dave Airlie <airlied@linux.ie>
86  */
87
88 /* XXX
89  *
90  * - Per thread context? Would it actually avoid many locks?
91  *
92  */
93
94 #include "cairoint.h"
95
96 #include "cairo-drm-private.h"
97 #include "cairo-drm-ioctl-private.h"
98 #include "cairo-drm-intel-private.h"
99 #include "cairo-drm-intel-command-private.h"
100 #include "cairo-drm-intel-ioctl-private.h"
101 #include "cairo-drm-i915-private.h"
102
103 #include "cairo-boxes-private.h"
104 #include "cairo-cache-private.h"
105 #include "cairo-composite-rectangles-private.h"
106 #include "cairo-default-context-private.h"
107 #include "cairo-error-private.h"
108 #include "cairo-freelist-private.h"
109 #include "cairo-list-private.h"
110 #include "cairo-path-fixed-private.h"
111 #include "cairo-region-private.h"
112 #include "cairo-surface-offset-private.h"
113
114 #include <sys/ioctl.h>
115 #include <sys/mman.h>
116 #include <errno.h>
117
118 static const uint32_t i915_batch_setup[] = {
119     /* Disable line anti-aliasing */
120     _3DSTATE_AA_CMD,
121
122     /* Disable independent alpha blend */
123     _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
124         IAB_MODIFY_ENABLE |
125         IAB_MODIFY_FUNC | (BLENDFUNC_ADD << IAB_FUNC_SHIFT) |
126         IAB_MODIFY_SRC_FACTOR | (BLENDFACT_ONE << IAB_SRC_FACTOR_SHIFT) |
127         IAB_MODIFY_DST_FACTOR | (BLENDFACT_ZERO << IAB_DST_FACTOR_SHIFT),
128
129     /* Disable texture crossbar */
130     _3DSTATE_COORD_SET_BINDINGS |
131         CSB_TCB (0, 0) |
132         CSB_TCB (1, 1) |
133         CSB_TCB (2, 2) |
134         CSB_TCB (3, 3) |
135         CSB_TCB (4, 4) |
136         CSB_TCB (5, 5) |
137         CSB_TCB (6, 6) |
138         CSB_TCB (7, 7),
139
140     _3DSTATE_MODES_4_CMD | ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC (LOGICOP_COPY),
141
142     _3DSTATE_LOAD_STATE_IMMEDIATE_1 |
143         I1_LOAD_S (2) |
144         I1_LOAD_S (3) |
145         I1_LOAD_S (4) |
146         I1_LOAD_S (5) |
147         I1_LOAD_S (6) |
148         4,
149     S2_TEXCOORD_NONE,
150     0, /* Disable texture coordinate wrap-shortest */
151     (1 << S4_POINT_WIDTH_SHIFT) |
152         S4_LINE_WIDTH_ONE |
153         S4_FLATSHADE_ALPHA |
154         S4_FLATSHADE_FOG |
155         S4_FLATSHADE_SPECULAR |
156         S4_FLATSHADE_COLOR |
157         S4_CULLMODE_NONE |
158         S4_VFMT_XY,
159     0, /* Disable stencil buffer */
160     S6_COLOR_WRITE_ENABLE,
161
162     _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT,
163
164     /* disable indirect state */
165     _3DSTATE_LOAD_INDIRECT,
166     0,
167 };
168
169 static const cairo_surface_backend_t i915_surface_backend;
170
171 static cairo_surface_t *
172 i915_surface_create_from_cacheable_image (cairo_drm_device_t *base_dev,
173                                            cairo_surface_t *source);
174
175 static cairo_status_t
176 i915_bo_exec (i915_device_t *device, intel_bo_t *bo, uint32_t offset)
177 {
178     struct drm_i915_gem_execbuffer2 execbuf;
179     int ret, cnt, i;
180
181     /* Add the batch buffer to the validation list.  */
182     cnt = device->batch.exec_count;
183     if (cnt > 0 && bo->base.handle == device->batch.exec[cnt-1].handle)
184         i = cnt - 1;
185     else
186         i = device->batch.exec_count++;
187     device->batch.exec[i].handle = bo->base.handle;
188     device->batch.exec[i].relocation_count = device->batch.reloc_count;
189     device->batch.exec[i].relocs_ptr = (uintptr_t) device->batch.reloc;
190     device->batch.exec[i].alignment = 0;
191     device->batch.exec[i].offset = 0;
192     device->batch.exec[i].flags = 0;
193     device->batch.exec[i].rsvd1 = 0;
194     device->batch.exec[i].rsvd2 = 0;
195
196     execbuf.buffers_ptr = (uintptr_t) device->batch.exec;
197     execbuf.buffer_count = device->batch.exec_count;
198     execbuf.batch_start_offset = offset;
199     execbuf.batch_len = (device->batch.used << 2) + sizeof (device->batch_header);
200     execbuf.DR1 = 0;
201     execbuf.DR4 = 0;
202     execbuf.num_cliprects = 0;
203     execbuf.cliprects_ptr = 0;
204     execbuf.flags = 0;
205     execbuf.rsvd1 = 0;
206     execbuf.rsvd2 = 0;
207
208     do {
209         ret = ioctl (device->intel.base.fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
210     } while (ret != 0 && errno == EINTR);
211
212     if (device->debug & I915_DEBUG_SYNC && ret == 0)
213         ret = ! intel_bo_wait (&device->intel, bo);
214
215     if (0 && ret) {
216         int n, m;
217
218         fprintf (stderr, "Batch submission failed: %d\n", errno);
219         fprintf (stderr, "   relocation entries: %d/%d\n",
220                  device->batch.reloc_count, I915_MAX_RELOCS);
221         fprintf (stderr, "   gtt size: (%zd/%zd), (%zd/%zd)\n",
222                  device->batch.est_gtt_size, device->batch.gtt_avail_size,
223                  device->batch.total_gtt_size, device->intel.gtt_avail_size);
224
225         fprintf (stderr, "   buffers:\n");
226         for (n = 0; n < device->batch.exec_count; n++) {
227             fprintf (stderr, "  exec[%d] = %d, %d/%d bytes, gtt = %qx\n",
228                     n,
229                     device->batch.exec[n].handle,
230                     n == device->batch.exec_count - 1 ? bo->base.size : device->batch.target_bo[n]->base.size,
231                     n == device->batch.exec_count - 1 ? bo->full_size : device->batch.target_bo[n]->full_size,
232                     device->batch.exec[n].offset);
233         }
234         for (n = 0; n < device->batch.reloc_count; n++) {
235             for (m = 0; m < device->batch.exec_count; m++)
236                 if (device->batch.exec[m].handle == device->batch.reloc[n].target_handle)
237                     break;
238
239             fprintf (stderr, "  reloc[%d] = %d @ %qx -> %qx + %qx\n", n,
240                      device->batch.reloc[n].target_handle,
241                      device->batch.reloc[n].offset,
242                      (unsigned long long) device->batch.exec[m].offset,
243                      (unsigned long long) device->batch.reloc[n].delta);
244
245             device->batch_base[(device->batch.reloc[n].offset - sizeof (device->batch_header)) / 4] =
246                 device->batch.exec[m].offset + device->batch.reloc[n].delta;
247         }
248
249         intel_dump_batchbuffer (device->batch_header,
250                                 execbuf.batch_len,
251                                 device->intel.base.chip_id);
252     }
253     assert (ret == 0);
254
255     VG (VALGRIND_MAKE_MEM_DEFINED (device->batch.exec, sizeof (device->batch.exec[0]) * i));
256
257     bo->offset = device->batch.exec[i].offset;
258     bo->busy = TRUE;
259     if (bo->virtual)
260         intel_bo_unmap (bo);
261     bo->cpu = FALSE;
262
263     while (cnt--) {
264         intel_bo_t *bo = device->batch.target_bo[cnt];
265
266         bo->offset = device->batch.exec[cnt].offset;
267         bo->exec = NULL;
268         bo->busy = TRUE;
269         bo->batch_read_domains = 0;
270         bo->batch_write_domain = 0;
271         cairo_list_del (&bo->cache_list);
272
273         if (bo->virtual)
274             intel_bo_unmap (bo);
275         bo->cpu = FALSE;
276
277         intel_bo_destroy (&device->intel, bo);
278     }
279     assert (cairo_list_is_empty (&device->intel.bo_in_flight));
280
281     device->batch.exec_count = 0;
282     device->batch.reloc_count = 0;
283     device->batch.fences = 0;
284
285     device->batch.est_gtt_size = I915_BATCH_SIZE;
286     device->batch.total_gtt_size = I915_BATCH_SIZE;
287
288     return ret == 0 ? CAIRO_STATUS_SUCCESS : _cairo_error (CAIRO_STATUS_NO_MEMORY);
289 }
290
291 void
292 i915_batch_add_reloc (i915_device_t *device,
293                       uint32_t pos,
294                       intel_bo_t *bo,
295                       uint32_t offset,
296                       uint32_t read_domains,
297                       uint32_t write_domain,
298                       cairo_bool_t needs_fence)
299 {
300     int index;
301
302     assert (offset < bo->base.size);
303
304     if (bo->exec == NULL) {
305         device->batch.total_gtt_size += bo->base.size;
306
307         if (! bo->busy)
308             device->batch.est_gtt_size += bo->base.size;
309
310         assert (device->batch.exec_count < ARRAY_LENGTH (device->batch.exec));
311
312         index = device->batch.exec_count++;
313         device->batch.exec[index].handle = bo->base.handle;
314         device->batch.exec[index].relocation_count = 0;
315         device->batch.exec[index].relocs_ptr = 0;
316         device->batch.exec[index].alignment = 0;
317         device->batch.exec[index].offset = 0;
318         device->batch.exec[index].flags = 0;
319         device->batch.exec[index].rsvd1 = 0;
320         device->batch.exec[index].rsvd2 = 0;
321
322         device->batch.target_bo[index] = intel_bo_reference (bo);
323
324         bo->exec = &device->batch.exec[index];
325     }
326
327     if (bo->tiling != I915_TILING_NONE) {
328         uint32_t alignment;
329
330 #if 0
331         /* We presume that we will want to use a fence with X tiled objects... */
332         if (needs_fence || bo->tiling == I915_TILING_X)
333             alignment = bo->full_size;
334         else
335             alignment = 2*((bo->stride + 4095) & -4096);
336 #else
337         alignment = bo->full_size;
338 #endif
339         if (bo->exec->alignment < alignment)
340             bo->exec->alignment = alignment;
341
342         if (needs_fence && (bo->exec->flags & EXEC_OBJECT_NEEDS_FENCE) == 0) {
343             bo->exec->flags |= EXEC_OBJECT_NEEDS_FENCE;
344             device->batch.fences++;
345
346             intel_bo_set_tiling (&device->intel, bo);
347         }
348     }
349
350     assert (device->batch.reloc_count < ARRAY_LENGTH (device->batch.reloc));
351
352     index = device->batch.reloc_count++;
353     device->batch.reloc[index].offset = (pos << 2) + sizeof (device->batch_header);
354     device->batch.reloc[index].delta = offset;
355     device->batch.reloc[index].target_handle = bo->base.handle;
356     device->batch.reloc[index].read_domains = read_domains;
357     device->batch.reloc[index].write_domain = write_domain;
358     device->batch.reloc[index].presumed_offset = bo->offset;
359
360     assert (write_domain == 0 || bo->batch_write_domain == 0 || bo->batch_write_domain == write_domain);
361     bo->batch_read_domains |= read_domains;
362     bo->batch_write_domain |= write_domain;
363 }
364
365 void
366 i915_vbo_finish (i915_device_t *device)
367 {
368     intel_bo_t *vbo;
369
370     assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex));
371     assert (device->vbo_used);
372
373     if (device->vertex_count) {
374         if (device->vbo == 0) {
375             OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
376                        I1_LOAD_S (0) |
377                        I1_LOAD_S (1) |
378                        1);
379             device->vbo = device->batch.used++;
380             device->vbo_max_index = device->batch.used;
381             OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
382                        (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
383         }
384
385         OUT_DWORD (PRIM3D_RECTLIST |
386                    PRIM3D_INDIRECT_SEQUENTIAL |
387                    device->vertex_count);
388         OUT_DWORD (device->vertex_index);
389     }
390
391     if (device->last_vbo != NULL) {
392         intel_bo_in_flight_add (&device->intel, device->last_vbo);
393         intel_bo_destroy (&device->intel, device->last_vbo);
394     }
395
396     device->batch_base[device->vbo_max_index] |= device->vertex_index + device->vertex_count;
397
398     /* will include a few bytes of inter-array padding */
399     vbo = intel_bo_create (&device->intel,
400                            device->vbo_used, device->vbo_used,
401                            FALSE, I915_TILING_NONE, 0);
402     i915_batch_fill_reloc (device, device->vbo, vbo, 0,
403                            I915_GEM_DOMAIN_VERTEX, 0);
404     intel_bo_write (&device->intel, vbo, 0, device->vbo_used, device->vbo_base);
405     device->last_vbo = vbo;
406     device->last_vbo_offset = (device->vbo_used+7)&-8;
407     device->last_vbo_space = vbo->base.size - device->last_vbo_offset;
408
409     device->vbo = 0;
410
411     device->vbo_used = device->vbo_offset = 0;
412     device->vertex_index = device->vertex_count = 0;
413
414     if (! i915_check_aperture_size (device, 1, I915_VBO_SIZE, I915_VBO_SIZE)) {
415         cairo_status_t status;
416
417         status = i915_batch_flush (device);
418         if (unlikely (status))
419             longjmp (device->shader->unwind, status);
420
421         status = i915_shader_commit (device->shader, device);
422         if (unlikely (status))
423             longjmp (device->shader->unwind, status);
424     }
425 }
426
427 /* XXX improve state tracker/difference and flush state on vertex emission */
428 static void
429 i915_device_reset (i915_device_t *device)
430 {
431     if (device->current_source != NULL)
432         *device->current_source = 0;
433     if (device->current_mask != NULL)
434         *device->current_mask = 0;
435     if (device->current_clip != NULL)
436         *device->current_clip = 0;
437
438     device->current_target = NULL;
439     device->current_size = 0;
440     device->current_source = NULL;
441     device->current_mask = NULL;
442     device->current_clip = NULL;
443     device->current_texcoords = ~0;
444     device->current_blend = 0;
445     device->current_n_constants = 0;
446     device->current_n_samplers = 0;
447     device->current_n_maps = 0;
448     device->current_colorbuf = 0;
449     device->current_diffuse = 0;
450     device->current_program = ~0;
451     device->clear_alpha = ~0;
452
453     device->last_source_fragment = ~0;
454 }
455
456 static void
457 i915_batch_cleanup (i915_device_t *device)
458 {
459     int i;
460
461     for (i = 0; i < device->batch.exec_count; i++) {
462         intel_bo_t *bo = device->batch.target_bo[i];
463
464         bo->exec = NULL;
465         bo->batch_read_domains = 0;
466         bo->batch_write_domain = 0;
467         cairo_list_del (&bo->cache_list);
468
469         intel_bo_destroy (&device->intel, bo);
470     }
471
472     device->batch.exec_count = 0;
473     device->batch.reloc_count = 0;
474 }
475
476 static void
477 i915_batch_vbo_finish (i915_device_t *device)
478 {
479     assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex));
480
481     if (device->vbo || i915_batch_space (device) < (int32_t) device->vbo_used) {
482         intel_bo_t *vbo;
483
484         if (device->vertex_count) {
485             if (device->vbo == 0) {
486                 OUT_DWORD (_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
487                            I1_LOAD_S (0) |
488                            I1_LOAD_S (1) |
489                            1);
490                 device->vbo = device->batch.used++;
491                 device->vbo_max_index = device->batch.used;
492                 OUT_DWORD ((device->floats_per_vertex << S1_VERTEX_WIDTH_SHIFT) |
493                         (device->floats_per_vertex << S1_VERTEX_PITCH_SHIFT));
494             }
495
496             OUT_DWORD (PRIM3D_RECTLIST |
497                        PRIM3D_INDIRECT_SEQUENTIAL |
498                        device->vertex_count);
499             OUT_DWORD (device->vertex_index);
500         }
501
502         if (device->last_vbo != NULL)
503             intel_bo_destroy (&device->intel, device->last_vbo);
504
505         device->batch_base[device->vbo_max_index] |= device->vertex_index + device->vertex_count;
506
507         /* will include a few bytes of inter-array padding */
508         vbo = intel_bo_create (&device->intel,
509                                device->vbo_used, device->vbo_used,
510                                FALSE, I915_TILING_NONE, 0);
511         i915_batch_fill_reloc (device, device->vbo,
512                                vbo, 0,
513                                I915_GEM_DOMAIN_VERTEX, 0);
514         intel_bo_write (&device->intel, vbo, 0, device->vbo_used, device->vbo_base);
515         device->last_vbo = vbo;
516         device->last_vbo_offset = (device->vbo_used+7)&-8;
517         device->last_vbo_space = vbo->base.size - device->last_vbo_offset;
518
519         device->vbo = 0;
520     }
521     else
522     {
523         /* Only a single rectlist in this batch, and no active vertex buffer. */
524         OUT_DWORD (PRIM3D_RECTLIST | (device->vbo_used / 4 - 1));
525
526         memcpy (BATCH_PTR (device), device->vbo_base, device->vbo_used);
527         device->batch.used += device->vbo_used >> 2;
528     }
529
530     device->vbo_used = device->vbo_offset = 0;
531     device->vertex_index = device->vertex_count = 0;
532 }
533
534 cairo_status_t
535 i915_batch_flush (i915_device_t *device)
536 {
537     intel_bo_t *batch;
538     cairo_status_t status;
539     uint32_t length, offset;
540     int n;
541
542     assert (CAIRO_MUTEX_IS_LOCKED (device->intel.base.base.mutex));
543
544     if (device->vbo_used)
545         i915_batch_vbo_finish (device);
546
547     if (device->batch.used == 0)
548         return CAIRO_STATUS_SUCCESS;
549
550     i915_batch_emit_dword (device, MI_BATCH_BUFFER_END);
551     if ((device->batch.used & 1) != ((sizeof (device->batch_header)>>2) & 1))
552         i915_batch_emit_dword (device, MI_NOOP);
553
554     length = (device->batch.used << 2) + sizeof (device->batch_header);
555
556     /* NB: it is faster to copy the data then map/unmap the batch,
557      * presumably because we frequently only use a small part of the buffer.
558      */
559     batch = NULL;
560     if (device->last_vbo) {
561         if (length <= device->last_vbo_space) {
562             batch = device->last_vbo;
563             offset = device->last_vbo_offset;
564
565             /* fixup the relocations */
566             for (n = 0; n < device->batch.reloc_count; n++)
567                 device->batch.reloc[n].offset += offset;
568         } else
569             intel_bo_destroy (&device->intel, device->last_vbo);
570         device->last_vbo = NULL;
571     }
572     if (batch == NULL) {
573         batch = intel_bo_create (&device->intel,
574                                  length, length,
575                                  FALSE, I915_TILING_NONE, 0);
576         if (unlikely (batch == NULL)) {
577             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
578             i915_batch_cleanup (device);
579             goto BAIL;
580         }
581
582         offset = 0;
583     }
584     intel_bo_write (&device->intel, batch, offset, length, device->batch_header);
585     status = i915_bo_exec (device, batch, offset);
586     intel_bo_destroy (&device->intel, batch);
587
588 BAIL:
589     device->batch.used = 0;
590
591     intel_glyph_cache_unpin (&device->intel);
592     intel_snapshot_cache_thaw (&device->intel);
593
594     i915_device_reset (device);
595
596     return status;
597 }
598
599 #if 0
600 static float *
601 i915_add_rectangles (i915_device_t *device, int num_rects, int *count)
602 {
603     float *vertices;
604     uint32_t size;
605     int cnt;
606
607     assert (device->floats_per_vertex);
608
609     size = device->rectangle_size;
610     if (unlikely (device->vbo_offset + size > I915_VBO_SIZE))
611         i915_vbo_finish (device);
612
613     vertices = (float *) (device->vbo_base + device->vbo_offset);
614     cnt = (I915_VBO_SIZE - device->vbo_offset) / size;
615     if (cnt > num_rects)
616         cnt = num_rects;
617     device->vbo_used = device->vbo_offset += size * cnt;
618     device->vertex_count += 3 * cnt;
619     *count = cnt;
620     return vertices;
621 }
622 #endif
623
624 static cairo_surface_t *
625 i915_surface_create_similar (void *abstract_other,
626                              cairo_content_t content,
627                              int width, int height)
628 {
629     i915_surface_t *other;
630     cairo_format_t format;
631     uint32_t tiling = I915_TILING_DEFAULT;
632
633     other = abstract_other;
634     if (content == other->intel.drm.base.content)
635         format = other->intel.drm.format;
636     else
637         format = _cairo_format_from_content (content);
638
639     if (width * _cairo_format_bits_per_pixel (format) > 8 * 32*1024 || height > 64*1024)
640         return NULL;
641
642     /* we presume that a similar surface will be used for blitting */
643     if (i915_surface_needs_tiling (other))
644         tiling = I915_TILING_X;
645
646     return i915_surface_create_internal ((cairo_drm_device_t *) other->intel.drm.base.device,
647                                          format,
648                                          width, height,
649                                          tiling, TRUE);
650 }
651
652 static cairo_status_t
653 i915_surface_finish (void *abstract_surface)
654 {
655     i915_surface_t *surface = abstract_surface;
656     i915_device_t *device = i915_device (surface);
657
658     if (surface->stencil != NULL) {
659         intel_bo_in_flight_add (&device->intel, surface->stencil);
660         intel_bo_destroy (&device->intel, surface->stencil);
661     }
662
663     if (surface->is_current_texture) {
664         if (surface->is_current_texture & CURRENT_SOURCE)
665             device->current_source = NULL;
666         if (surface->is_current_texture & CURRENT_MASK)
667             device->current_mask = NULL;
668         if (surface->is_current_texture & CURRENT_CLIP)
669             device->current_clip = NULL;
670         device->current_n_samplers = 0;
671     }
672
673     if (surface == device->current_target)
674         device->current_target = NULL;
675
676     if (surface->cache != NULL) {
677         i915_image_private_t *node = surface->cache;
678         intel_buffer_cache_t *cache = node->container;
679
680         if (--cache->ref_count == 0) {
681             intel_bo_in_flight_add (&device->intel, cache->buffer.bo);
682             intel_bo_destroy (&device->intel, cache->buffer.bo);
683             _cairo_rtree_fini (&cache->rtree);
684             cairo_list_del (&cache->link);
685             free (cache);
686         } else {
687             node->node.state = CAIRO_RTREE_NODE_AVAILABLE;
688             cairo_list_move (&node->node.link, &cache->rtree.available);
689             _cairo_rtree_node_collapse (&cache->rtree, node->node.parent);
690         }
691     }
692
693     return intel_surface_finish (&surface->intel);
694 }
695
696 static cairo_status_t
697 i915_surface_batch_flush (i915_surface_t *surface)
698 {
699     cairo_status_t status;
700     intel_bo_t *bo;
701
702     assert (surface->intel.drm.fallback == NULL);
703
704     bo = to_intel_bo (surface->intel.drm.bo);
705     if (bo == NULL || bo->batch_write_domain == 0)
706         return CAIRO_STATUS_SUCCESS;
707
708     status = cairo_device_acquire (surface->intel.drm.base.device);
709     if (unlikely (status))
710         return status;
711
712     status = i915_batch_flush (i915_device (surface));
713     cairo_device_release (surface->intel.drm.base.device);
714
715     return status;
716 }
717
718 static cairo_status_t
719 i915_surface_flush (void *abstract_surface)
720 {
721     i915_surface_t *surface = abstract_surface;
722     cairo_status_t status;
723
724     if (surface->intel.drm.fallback == NULL) {
725         if (surface->intel.drm.base.finished) {
726             /* Forgo flushing on finish as the user cannot access the surface directly. */
727             return CAIRO_STATUS_SUCCESS;
728         }
729
730         if (surface->deferred_clear) {
731             status = i915_surface_clear (surface);
732             if (unlikely (status))
733                 return status;
734         }
735
736         return i915_surface_batch_flush (surface);
737     }
738
739     return intel_surface_flush (abstract_surface);
740 }
741
742 /* rasterisation */
743
744 static cairo_status_t
745 _composite_boxes_spans (void                    *closure,
746                         cairo_span_renderer_t   *renderer,
747                         const cairo_rectangle_int_t     *extents)
748 {
749     cairo_boxes_t *boxes = closure;
750     cairo_rectangular_scan_converter_t converter;
751     struct _cairo_boxes_chunk *chunk;
752     cairo_status_t status;
753     int i;
754
755     _cairo_rectangular_scan_converter_init (&converter, extents);
756     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
757         cairo_box_t *box = chunk->base;
758         for (i = 0; i < chunk->count; i++) {
759             status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
760             if (unlikely (status))
761                 goto CLEANUP;
762         }
763     }
764
765     status = converter.base.generate (&converter.base, renderer);
766
767 CLEANUP:
768     converter.base.destroy (&converter.base);
769     return status;
770 }
771
772 cairo_status_t
773 i915_fixup_unbounded (i915_surface_t *dst,
774                       const cairo_composite_rectangles_t *extents,
775                       cairo_clip_t *clip)
776 {
777     i915_shader_t shader;
778     i915_device_t *device;
779     cairo_status_t status;
780
781     if (clip != NULL) {
782         cairo_region_t *clip_region = NULL;
783
784         status = _cairo_clip_get_region (clip, &clip_region);
785         assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED);
786         assert (clip_region == NULL);
787
788         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
789             clip = NULL;
790     } else {
791         if (extents->bounded.width == extents->unbounded.width &&
792             extents->bounded.height == extents->unbounded.height)
793         {
794             return CAIRO_STATUS_SUCCESS;
795         }
796     }
797
798     if (clip != NULL) {
799         i915_shader_init (&shader, dst, CAIRO_OPERATOR_DEST_OVER, 1.);
800         i915_shader_set_clip (&shader, clip);
801         status = i915_shader_acquire_pattern (&shader,
802                                               &shader.source,
803                                               &_cairo_pattern_white.base,
804                                               &extents->unbounded);
805         assert (status == CAIRO_STATUS_SUCCESS);
806     } else {
807         i915_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR, 1.);
808         status = i915_shader_acquire_pattern (&shader,
809                                               &shader.source,
810                                               &_cairo_pattern_clear.base,
811                                               &extents->unbounded);
812         assert (status == CAIRO_STATUS_SUCCESS);
813     }
814
815     device = i915_device (dst);
816     status = cairo_device_acquire (&device->intel.base.base);
817     if (unlikely (status))
818         return status;
819
820     status = i915_shader_commit (&shader, device);
821     if (unlikely (status))
822         goto BAIL;
823
824     if (extents->bounded.width == 0 || extents->bounded.height == 0) {
825         shader.add_rectangle (&shader,
826                               extents->unbounded.x,
827                               extents->unbounded.y,
828                               extents->unbounded.width,
829                               extents->unbounded.height);
830     } else {
831         /* top */
832         if (extents->bounded.y != extents->unbounded.y) {
833             shader.add_rectangle (&shader,
834                                   extents->unbounded.x,
835                                   extents->unbounded.y,
836                                   extents->unbounded.width,
837                                   extents->bounded.y - extents->unbounded.y);
838         }
839
840         /* left */
841         if (extents->bounded.x != extents->unbounded.x) {
842             shader.add_rectangle (&shader,
843                                   extents->unbounded.x,
844                                   extents->bounded.y,
845                                   extents->bounded.x - extents->unbounded.x,
846                                   extents->bounded.height);
847         }
848
849         /* right */
850         if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
851             shader.add_rectangle (&shader,
852                                   extents->bounded.x + extents->bounded.width,
853                                   extents->bounded.y,
854                                   extents->unbounded.x + extents->unbounded.width - (extents->bounded.x + extents->bounded.width),
855                                   extents->bounded.height);
856         }
857
858         /* bottom */
859         if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
860             shader.add_rectangle (&shader,
861                                   extents->unbounded.x,
862                                   extents->bounded.y + extents->bounded.height,
863                                   extents->unbounded.width,
864                                   extents->unbounded.y + extents->unbounded.height - (extents->bounded.y + extents->bounded.height));
865         }
866     }
867
868     i915_shader_fini (&shader);
869   BAIL:
870     cairo_device_release (&device->intel.base.base);
871     return status;
872 }
873
874 static cairo_status_t
875 i915_fixup_unbounded_boxes (i915_surface_t *dst,
876                             const cairo_composite_rectangles_t *extents,
877                             cairo_clip_t *clip,
878                             cairo_boxes_t *boxes)
879 {
880     cairo_boxes_t clear;
881     cairo_box_t box;
882     cairo_region_t *clip_region = NULL;
883     cairo_status_t status;
884     struct _cairo_boxes_chunk *chunk;
885     int i;
886
887     if (boxes->num_boxes <= 1)
888         return i915_fixup_unbounded (dst, extents, clip);
889
890     _cairo_boxes_init (&clear);
891
892     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
893     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
894     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
895     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
896
897     if (clip != NULL) {
898         status = _cairo_clip_get_region (clip, &clip_region);
899         assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED);
900         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
901             clip = NULL;
902     }
903
904     if (clip_region == NULL) {
905         cairo_boxes_t tmp;
906
907         _cairo_boxes_init (&tmp);
908
909         status = _cairo_boxes_add (&tmp, &box);
910         assert (status == CAIRO_STATUS_SUCCESS);
911
912         tmp.chunks.next = &boxes->chunks;
913         tmp.num_boxes += boxes->num_boxes;
914
915         status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
916                                                           CAIRO_FILL_RULE_WINDING,
917                                                           &clear);
918
919         tmp.chunks.next = NULL;
920     } else {
921         pixman_box32_t *pbox;
922
923         pbox = pixman_region32_rectangles (&clip_region->rgn, &i);
924         _cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i);
925
926         status = _cairo_boxes_add (&clear, &box);
927         assert (status == CAIRO_STATUS_SUCCESS);
928
929         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
930             for (i = 0; i < chunk->count; i++) {
931                 status = _cairo_boxes_add (&clear, &chunk->base[i]);
932                 if (unlikely (status)) {
933                     _cairo_boxes_fini (&clear);
934                     return status;
935                 }
936             }
937         }
938
939         status = _cairo_bentley_ottmann_tessellate_boxes (&clear,
940                                                           CAIRO_FILL_RULE_WINDING,
941                                                           &clear);
942     }
943
944     if (likely (status == CAIRO_STATUS_SUCCESS && clear.num_boxes)) {
945         i915_shader_t shader;
946         i915_device_t *device;
947
948         if (clip != NULL) {
949             i915_shader_init (&shader, dst, CAIRO_OPERATOR_DEST_OVER, 1.);
950             i915_shader_set_clip (&shader, clip);
951             status = i915_shader_acquire_pattern (&shader,
952                                                   &shader.source,
953                                                   &_cairo_pattern_white.base,
954                                                   &extents->unbounded);
955             assert (status == CAIRO_STATUS_SUCCESS);
956         } else {
957             i915_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR, 1.);
958             status = i915_shader_acquire_pattern (&shader,
959                                                   &shader.source,
960                                                   &_cairo_pattern_clear.base,
961                                                   &extents->unbounded);
962             assert (status == CAIRO_STATUS_SUCCESS);
963         }
964
965         device = i915_device (dst);
966         status = cairo_device_acquire (&device->intel.base.base);
967         if (unlikely (status))
968             goto err_shader;
969
970         status = i915_shader_commit (&shader, device);
971         if (unlikely (status))
972             goto err_device;
973
974         for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) {
975             for (i = 0; i < chunk->count; i++) {
976                 int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
977                 int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
978                 int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
979                 int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
980
981                 shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
982             }
983         }
984 err_device:
985         cairo_device_release (&device->intel.base.base);
986 err_shader:
987         i915_shader_fini (&shader);
988     }
989
990     _cairo_boxes_fini (&clear);
991
992     return status;
993 }
994
995 static cairo_bool_t
996 i915_can_blt (i915_surface_t *dst,
997               const cairo_pattern_t *pattern)
998 {
999     const cairo_surface_pattern_t *spattern;
1000     i915_surface_t *src;
1001
1002     spattern = (const cairo_surface_pattern_t *) pattern;
1003     src = (i915_surface_t *) spattern->surface;
1004
1005     if (src->intel.drm.base.device != dst->intel.drm.base.device)
1006         return FALSE;
1007
1008     if (! i915_surface_needs_tiling (dst))
1009         return FALSE;
1010
1011     if (! _cairo_matrix_is_translation (&pattern->matrix))
1012         return FALSE;
1013
1014     if (! (pattern->filter == CAIRO_FILTER_NEAREST ||
1015            pattern->filter == CAIRO_FILTER_FAST))
1016     {
1017         if (! _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->matrix.x0)) ||
1018             ! _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->matrix.y0)))
1019         {
1020             return FALSE;
1021         }
1022     }
1023
1024     return _cairo_format_bits_per_pixel (src->intel.drm.format) ==
1025         _cairo_format_bits_per_pixel (dst->intel.drm.format);
1026 }
1027
1028 static cairo_status_t
1029 i915_blt (i915_surface_t *src,
1030           i915_surface_t *dst,
1031           int src_x, int src_y,
1032           int width, int height,
1033           int dst_x, int dst_y,
1034           cairo_bool_t flush)
1035 {
1036     i915_device_t *device;
1037     intel_bo_t *bo_array[2];
1038     cairo_status_t status;
1039     int br13, cmd;
1040
1041     bo_array[0] = to_intel_bo (dst->intel.drm.bo);
1042     bo_array[1] = to_intel_bo (src->intel.drm.bo);
1043
1044     status = i915_surface_fallback_flush (src);
1045     if (unlikely (status))
1046         return status;
1047
1048     device = i915_device (dst);
1049     status = cairo_device_acquire (&device->intel.base.base);
1050     if (unlikely (status))
1051         return status;
1052
1053     if (! i915_check_aperture_and_fences (device, bo_array, 2) ||
1054         i915_batch_space (device) < 9)
1055     {
1056         status = i915_batch_flush (device);
1057         if (unlikely (status))
1058             goto CLEANUP;
1059     }
1060
1061     cmd = XY_SRC_COPY_BLT_CMD;
1062     br13 = (0xCC << 16) | dst->intel.drm.stride;
1063     switch (dst->intel.drm.format) {
1064     default:
1065     case CAIRO_FORMAT_INVALID:
1066     case CAIRO_FORMAT_A1:
1067         ASSERT_NOT_REACHED;
1068     case CAIRO_FORMAT_A8:
1069         break;
1070     case CAIRO_FORMAT_RGB16_565:
1071         br13 |= BR13_565;
1072         break;
1073     case CAIRO_FORMAT_RGB24:
1074     case CAIRO_FORMAT_ARGB32:
1075         br13 |= BR13_8888;
1076         cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
1077         break;
1078     }
1079
1080     OUT_DWORD (cmd);
1081     OUT_DWORD (br13);
1082     OUT_DWORD ((dst_y << 16) | dst_x);
1083     OUT_DWORD (((dst_y + height - 1) << 16) | (dst_x + width - 1));
1084     OUT_RELOC_FENCED (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
1085     OUT_DWORD ((src_y << 16) | src_x);
1086     OUT_DWORD (src->intel.drm.stride);
1087     OUT_RELOC_FENCED (src, I915_GEM_DOMAIN_RENDER, 0);
1088     /* require explicit RenderCache flush for 2D -> 3D sampler? */
1089     if (flush)
1090         OUT_DWORD (MI_FLUSH);
1091
1092 CLEANUP:
1093     cairo_device_release (&device->intel.base.base);
1094     return CAIRO_STATUS_SUCCESS;
1095 }
1096
1097 cairo_status_t
1098 i915_surface_copy_subimage (i915_device_t *device,
1099                             i915_surface_t *src,
1100                             const cairo_rectangle_int_t *extents,
1101                             cairo_bool_t flush,
1102                             i915_surface_t **clone_out)
1103 {
1104     i915_surface_t *clone;
1105     cairo_status_t status;
1106
1107     clone = (i915_surface_t *)
1108         i915_surface_create_internal (&device->intel.base,
1109                                       src->intel.drm.format,
1110                                       extents->width,
1111                                       extents->height,
1112                                       I915_TILING_X, TRUE);
1113     if (unlikely (clone->intel.drm.base.status))
1114         return clone->intel.drm.base.status;
1115
1116     status = i915_blt (src, clone,
1117                        extents->x, extents->y,
1118                        extents->width, extents->height,
1119                        0, 0,
1120                        flush);
1121
1122     if (unlikely (status)) {
1123         cairo_surface_destroy (&clone->intel.drm.base);
1124         return status;
1125     }
1126
1127     *clone_out = clone;
1128     return CAIRO_STATUS_SUCCESS;
1129 }
1130
1131 static cairo_status_t
1132 i915_clear_boxes (i915_surface_t *dst,
1133                   const cairo_boxes_t *boxes)
1134 {
1135     i915_device_t *device = i915_device (dst);
1136     const struct _cairo_boxes_chunk *chunk;
1137     cairo_status_t status;
1138     intel_bo_t *bo_array[1] = { to_intel_bo (dst->intel.drm.bo) };
1139     int cmd, br13, clear = 0, i;
1140
1141     cmd = XY_COLOR_BLT_CMD;
1142     br13 = (0xCC << 16) | dst->intel.drm.stride;
1143     switch (dst->intel.drm.format) {
1144     default:
1145     case CAIRO_FORMAT_INVALID:
1146     case CAIRO_FORMAT_A1:
1147         ASSERT_NOT_REACHED;
1148     case CAIRO_FORMAT_A8:
1149         break;
1150     case CAIRO_FORMAT_RGB16_565:
1151         br13 |= BR13_565;
1152         break;
1153     case CAIRO_FORMAT_RGB24:
1154         clear = 0xff000000;
1155     case CAIRO_FORMAT_ARGB32:
1156         br13 |= BR13_8888;
1157         cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
1158         break;
1159     }
1160
1161     status = cairo_device_acquire (&device->intel.base.base);
1162     if (unlikely (status))
1163         return status;
1164
1165     if (! i915_check_aperture_and_fences (device, bo_array, 1) ||
1166         i915_batch_space (device) < 6 * boxes->num_boxes)
1167     {
1168         status = i915_batch_flush (device);
1169         if (unlikely (status))
1170             goto RELEASE;
1171     }
1172
1173     if (device->vertex_count)
1174         i915_vbo_flush (device);
1175
1176     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1177         const cairo_box_t *box = chunk->base;
1178         for (i = 0; i < chunk->count; i++) {
1179             int x1 = _cairo_fixed_integer_round (box[i].p1.x);
1180             int x2 = _cairo_fixed_integer_round (box[i].p2.x);
1181             int y1 = _cairo_fixed_integer_round (box[i].p1.y);
1182             int y2 = _cairo_fixed_integer_round (box[i].p2.y);
1183
1184             if (x2 <= x1 || y2 <= y1)
1185                 continue;
1186
1187             OUT_DWORD (cmd);
1188             OUT_DWORD (br13);
1189             OUT_DWORD ((y1 << 16) | x1);
1190             OUT_DWORD (((y2 - 1) << 16) | (x2 - 1));
1191             OUT_RELOC_FENCED (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
1192             OUT_DWORD (clear);
1193         }
1194     }
1195
1196 RELEASE:
1197     cairo_device_release (&device->intel.base.base);
1198     return status;
1199 }
1200
1201 static cairo_status_t
1202 i915_surface_extract_X_from_Y (i915_device_t *device,
1203                                i915_surface_t *src,
1204                                const cairo_rectangle_int_t *extents,
1205                                i915_surface_t **clone_out)
1206 {
1207     i915_surface_t *clone;
1208     i915_shader_t shader;
1209     cairo_surface_pattern_t pattern;
1210     cairo_rectangle_int_t rect;
1211     cairo_status_t status;
1212
1213     status = i915_surface_fallback_flush (src);
1214     if (unlikely (status))
1215         return status;
1216
1217     clone = (i915_surface_t *)
1218         i915_surface_create_internal (&device->intel.base,
1219                                       src->intel.drm.format,
1220                                       extents->width,
1221                                       extents->height,
1222                                       I915_TILING_X, TRUE);
1223     if (unlikely (clone->intel.drm.base.status))
1224         return clone->intel.drm.base.status;
1225
1226     i915_shader_init (&shader, clone, CAIRO_OPERATOR_SOURCE, 1.);
1227
1228     _cairo_pattern_init_for_surface (&pattern, &src->intel.drm.base);
1229     pattern.base.filter = CAIRO_FILTER_NEAREST;
1230     cairo_matrix_init_translate (&pattern.base.matrix, extents->x, extents->y);
1231
1232     rect.x = rect.y = 0;
1233     rect.width = extents->width;
1234     rect.height = extents->height;
1235     status = i915_shader_acquire_pattern (&shader, &shader.source, &pattern.base, &rect);
1236     _cairo_pattern_fini (&pattern.base);
1237
1238     if (unlikely (status))
1239         goto err_shader;
1240
1241     status = cairo_device_acquire (&device->intel.base.base);
1242     if (unlikely (status))
1243         goto err_shader;
1244
1245     status = i915_shader_commit (&shader, device);
1246     if (unlikely (status))
1247         goto err_device;
1248
1249     shader.add_rectangle (&shader, 0, 0, extents->width, extents->height);
1250
1251     cairo_device_release (&device->intel.base.base);
1252     i915_shader_fini (&shader);
1253
1254     *clone_out = clone;
1255     return CAIRO_STATUS_SUCCESS;
1256
1257 err_device:
1258     cairo_device_release (&device->intel.base.base);
1259 err_shader:
1260     i915_shader_fini (&shader);
1261     cairo_surface_destroy (&clone->intel.drm.base);
1262     return status;
1263 }
1264
1265 static cairo_status_t
1266 i915_blt_boxes (i915_surface_t *dst,
1267                 const cairo_pattern_t *pattern,
1268                 const cairo_rectangle_int_t *extents,
1269                 const cairo_boxes_t *boxes)
1270 {
1271     const cairo_surface_pattern_t *spattern;
1272     i915_device_t *device;
1273     i915_surface_t *src;
1274     cairo_surface_t *free_me = NULL;
1275     const struct _cairo_boxes_chunk *chunk;
1276     cairo_status_t status;
1277     int br13, cmd, tx, ty;
1278     intel_bo_t *bo_array[2];
1279     int i;
1280
1281     if (! i915_can_blt (dst, pattern))
1282         return CAIRO_INT_STATUS_UNSUPPORTED;
1283
1284     spattern = (const cairo_surface_pattern_t *) pattern;
1285     src = (i915_surface_t *) spattern->surface;
1286
1287     if (src->intel.drm.base.is_clear)
1288         return i915_clear_boxes (dst, boxes);
1289
1290     if (pattern->extend != CAIRO_EXTEND_NONE &&
1291         (extents->x + tx < 0 ||
1292          extents->y + ty < 0 ||
1293          extents->x + tx + extents->width  > src->intel.drm.width ||
1294          extents->y + ty + extents->height > src->intel.drm.height))
1295     {
1296         return CAIRO_INT_STATUS_UNSUPPORTED;
1297     }
1298
1299     status = i915_surface_fallback_flush (src);
1300     if (unlikely (status))
1301         return status;
1302
1303     tx = _cairo_lround (pattern->matrix.x0);
1304     ty = _cairo_lround (pattern->matrix.y0);
1305
1306     device = i915_device (dst);
1307     if (to_intel_bo (src->intel.drm.bo)->tiling == I915_TILING_Y) {
1308         cairo_rectangle_int_t extents;
1309
1310         _cairo_boxes_extents (boxes, &extents);
1311         extents.x += tx;
1312         extents.y += ty;
1313
1314         status = i915_surface_extract_X_from_Y (device, src, &extents, &src);
1315         if (unlikely (status))
1316             return status;
1317
1318         free_me = &src->intel.drm.base;
1319         tx = -extents.x;
1320         ty = -extents.y;
1321     }
1322
1323     bo_array[0] = to_intel_bo (dst->intel.drm.bo);
1324     bo_array[1] = to_intel_bo (src->intel.drm.bo);
1325
1326     status = cairo_device_acquire (&device->intel.base.base);
1327     if (unlikely (status))
1328         goto CLEANUP_SURFACE;
1329
1330     if (! i915_check_aperture_and_fences (device, bo_array, 2) ||
1331         i915_batch_space (device) < 8 * boxes->num_boxes)
1332     {
1333         status = i915_batch_flush (device);
1334         if (unlikely (status))
1335             goto CLEANUP_DEVICE;
1336     }
1337
1338     cmd = XY_SRC_COPY_BLT_CMD;
1339     br13 = (0xCC << 16) | dst->intel.drm.stride;
1340     switch (dst->intel.drm.format) {
1341     default:
1342     case CAIRO_FORMAT_INVALID:
1343     case CAIRO_FORMAT_A1:
1344         ASSERT_NOT_REACHED;
1345     case CAIRO_FORMAT_A8:
1346         break;
1347     case CAIRO_FORMAT_RGB16_565:
1348         br13 |= BR13_565;
1349         break;
1350     case CAIRO_FORMAT_RGB24:
1351     case CAIRO_FORMAT_ARGB32:
1352         br13 |= BR13_8888;
1353         cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
1354         break;
1355     }
1356
1357     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1358         const cairo_box_t *box = chunk->base;
1359         for (i = 0; i < chunk->count; i++) {
1360             int x1 = _cairo_fixed_integer_round (box[i].p1.x);
1361             int x2 = _cairo_fixed_integer_round (box[i].p2.x);
1362             int y1 = _cairo_fixed_integer_round (box[i].p1.y);
1363             int y2 = _cairo_fixed_integer_round (box[i].p2.y);
1364
1365             if (x1 + tx < 0)
1366                 x1 = -tx;
1367             if (x2 + tx > src->intel.drm.width)
1368                 x2 = src->intel.drm.width - tx;
1369
1370             if (y1 + ty < 0)
1371                 y1 = -ty;
1372             if (y2 + ty > src->intel.drm.height)
1373                 y2 = src->intel.drm.height - ty;
1374
1375             if (x2 <= x1 || y2 <= y1)
1376                 continue;
1377             if (x2 < 0 || y2 < 0)
1378                 continue;
1379             if (x1 >= dst->intel.drm.width || y2 >= dst->intel.drm.height)
1380                 continue;
1381
1382             OUT_DWORD (cmd);
1383             OUT_DWORD (br13);
1384             OUT_DWORD ((y1 << 16) | x1);
1385             OUT_DWORD (((y2 - 1) << 16) | (x2 - 1));
1386             OUT_RELOC_FENCED (dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
1387             OUT_DWORD (((y1 + ty) << 16) | (x1 + tx));
1388             OUT_DWORD (src->intel.drm.stride);
1389             OUT_RELOC_FENCED (src, I915_GEM_DOMAIN_RENDER, 0);
1390         }
1391     }
1392
1393     /* XXX fixup blank portions */
1394
1395 CLEANUP_DEVICE:
1396     cairo_device_release (&device->intel.base.base);
1397 CLEANUP_SURFACE:
1398     cairo_surface_destroy (free_me);
1399     return status;
1400 }
1401
1402 static cairo_status_t
1403 _upload_image_inplace (i915_surface_t *surface,
1404                        const cairo_pattern_t *source,
1405                        const cairo_rectangle_int_t *extents,
1406                        const cairo_boxes_t *boxes)
1407 {
1408     i915_device_t *device;
1409     const cairo_surface_pattern_t *pattern;
1410     cairo_image_surface_t *image;
1411     const struct _cairo_boxes_chunk *chunk;
1412     intel_bo_t *bo;
1413     int tx, ty, i;
1414
1415     if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
1416         return CAIRO_INT_STATUS_UNSUPPORTED;
1417
1418     pattern = (const cairo_surface_pattern_t *) source;
1419     if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE)
1420         return CAIRO_INT_STATUS_UNSUPPORTED;
1421
1422     if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
1423         return CAIRO_INT_STATUS_UNSUPPORTED;
1424
1425     image = (cairo_image_surface_t *) pattern->surface;
1426     if (source->extend != CAIRO_EXTEND_NONE &&
1427         (extents->x + tx < 0 ||
1428          extents->y + ty < 0 ||
1429          extents->x + tx + extents->width  > image->width ||
1430          extents->y + ty + extents->height > image->height))
1431     {
1432         return CAIRO_INT_STATUS_UNSUPPORTED;
1433     }
1434
1435     device = i915_device (surface);
1436     bo = to_intel_bo (surface->intel.drm.bo);
1437     if (bo->exec != NULL || ! intel_bo_is_inactive (&device->intel, bo)) {
1438         intel_bo_t *new_bo;
1439         cairo_bool_t need_clear = FALSE;
1440
1441         if (boxes->num_boxes != 1 ||
1442             extents->width < surface->intel.drm.width ||
1443             extents->height < surface->intel.drm.height)
1444         {
1445             if (! surface->intel.drm.base.is_clear)
1446                 return CAIRO_INT_STATUS_UNSUPPORTED;
1447
1448             need_clear = TRUE;
1449         }
1450
1451         new_bo = intel_bo_create (&device->intel,
1452                                   bo->full_size, bo->base.size,
1453                                   FALSE, bo->tiling, bo->stride);
1454         if (unlikely (new_bo == NULL))
1455             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1456
1457         intel_bo_in_flight_add (&device->intel, bo);
1458         intel_bo_destroy (&device->intel, bo);
1459
1460         bo = new_bo;
1461         surface->intel.drm.bo = &bo->base;
1462
1463         if (need_clear) {
1464             memset (intel_bo_map (&device->intel, bo), 0,
1465                     bo->stride * surface->intel.drm.height);
1466         }
1467     }
1468
1469     if (image->format == surface->intel.drm.format) {
1470         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1471             cairo_box_t *box = chunk->base;
1472             for (i = 0; i < chunk->count; i++) {
1473                 int x1 = _cairo_fixed_integer_round (box[i].p1.x);
1474                 int x2 = _cairo_fixed_integer_round (box[i].p2.x);
1475                 int y1 = _cairo_fixed_integer_round (box[i].p1.y);
1476                 int y2 = _cairo_fixed_integer_round (box[i].p2.y);
1477                 cairo_status_t status;
1478
1479                 if (x1 + tx < 0)
1480                     x1 = -tx;
1481                 if (x2 + tx > image->width)
1482                     x2 = image->width - tx;
1483
1484                 if (y1 + ty < 0)
1485                     y1 = -ty;
1486                 if (y2 + ty > image->height)
1487                     y2 = image->height - ty;
1488
1489                 if (x2 <= x1 || y2 <= y1)
1490                     continue;
1491                 if (x2 < 0 || y2 < 0)
1492                     continue;
1493                 if (x1 >= surface->intel.drm.width || y2 >= surface->intel.drm.height)
1494                     continue;
1495
1496                 status = intel_bo_put_image (&device->intel,
1497                                              bo,
1498                                              image,
1499                                              x1 + tx, y1 + ty,
1500                                              x2 - x1, y2 - y1,
1501                                              x1, y1);
1502                 if (unlikely (status))
1503                     return status;
1504             }
1505         }
1506     } else {
1507         pixman_image_t *dst;
1508         void *ptr;
1509
1510         ptr = intel_bo_map (&device->intel, bo);
1511         if (unlikely (ptr == NULL))
1512             return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
1513
1514         dst = pixman_image_create_bits (_cairo_format_to_pixman_format_code (surface->intel.drm.format),
1515                                         surface->intel.drm.width,
1516                                         surface->intel.drm.height,
1517                                         ptr,
1518                                         surface->intel.drm.stride);
1519         if (unlikely (dst == NULL))
1520             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1521
1522         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1523             cairo_box_t *box = chunk->base;
1524             for (i = 0; i < chunk->count; i++) {
1525                 int x1 = _cairo_fixed_integer_round (box[i].p1.x);
1526                 int x2 = _cairo_fixed_integer_round (box[i].p2.x);
1527                 int y1 = _cairo_fixed_integer_round (box[i].p1.y);
1528                 int y2 = _cairo_fixed_integer_round (box[i].p2.y);
1529
1530                 if (x1 + tx < 0)
1531                     x1 = -tx;
1532                 if (x2 + tx > image->width)
1533                     x2 = image->width - tx;
1534
1535                 if (y1 + ty < 0)
1536                     y1 = -ty;
1537                 if (y2 + ty > image->height)
1538                     y2 = image->height - ty;
1539
1540                 if (x2 <= x1 || y2 <= y1)
1541                     continue;
1542                 if (x2 < 0 || y2 < 0)
1543                     continue;
1544                 if (x1 >= surface->intel.drm.width || y2 >= surface->intel.drm.height)
1545                     continue;
1546
1547                 pixman_image_composite32 (PIXMAN_OP_SRC,
1548                                           image->pixman_image, NULL, dst,
1549                                           x1 + tx, y1 + ty,
1550                                           0, 0,
1551                                           x1, y1,
1552                                           x2 - x1, y2 - y1);
1553             }
1554         }
1555
1556         pixman_image_unref (dst);
1557     }
1558
1559     return CAIRO_STATUS_SUCCESS;
1560 }
1561
1562 static cairo_status_t
1563 _composite_boxes (i915_surface_t *dst,
1564                   cairo_operator_t op,
1565                   const cairo_pattern_t *pattern,
1566                   cairo_boxes_t *boxes,
1567                   cairo_antialias_t antialias,
1568                   cairo_clip_t *clip,
1569                   double opacity,
1570                   const cairo_composite_rectangles_t *extents)
1571 {
1572     cairo_bool_t need_clip_surface = FALSE;
1573     cairo_region_t *clip_region = NULL;
1574     const struct _cairo_boxes_chunk *chunk;
1575     cairo_status_t status;
1576     i915_shader_t shader;
1577     i915_device_t *device;
1578     int i;
1579
1580     /* If the boxes are not pixel-aligned, we will need to compute a real mask */
1581     if (antialias != CAIRO_ANTIALIAS_NONE) {
1582         if (! boxes->is_pixel_aligned)
1583             return CAIRO_INT_STATUS_UNSUPPORTED;
1584     }
1585
1586     if (clip == NULL && op == CAIRO_OPERATOR_SOURCE && opacity == 1.) {
1587         if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
1588             status = i915_blt_boxes (dst, pattern, &extents->bounded, boxes);
1589             if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1590                 status = _upload_image_inplace (dst, pattern,
1591                                                 &extents->bounded, boxes);
1592             }
1593             if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1594                 return status;
1595         }
1596     }
1597
1598     if (i915_surface_needs_tiling (dst)) {
1599         ASSERT_NOT_REACHED;
1600         return CAIRO_INT_STATUS_UNSUPPORTED;
1601     }
1602
1603     i915_shader_init (&shader, dst, op, opacity);
1604
1605     status = i915_shader_acquire_pattern (&shader,
1606                                           &shader.source,
1607                                           pattern,
1608                                           &extents->bounded);
1609     if (unlikely (status))
1610         return status;
1611
1612     if (clip != NULL) {
1613         status = _cairo_clip_get_region (clip, &clip_region);
1614         assert (status == CAIRO_STATUS_SUCCESS || status == CAIRO_INT_STATUS_UNSUPPORTED);
1615         need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
1616         if (need_clip_surface)
1617             i915_shader_set_clip (&shader, clip);
1618     }
1619
1620     device = i915_device (dst);
1621     status = cairo_device_acquire (&device->intel.base.base);
1622     if (unlikely (status))
1623         goto err_shader;
1624
1625     status = i915_shader_commit (&shader, device);
1626     if (unlikely (status))
1627         goto err_device;
1628
1629     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1630         cairo_box_t *box = chunk->base;
1631         for (i = 0; i < chunk->count; i++) {
1632             int x1 = _cairo_fixed_integer_round (box[i].p1.x);
1633             int y1 = _cairo_fixed_integer_round (box[i].p1.y);
1634             int x2 = _cairo_fixed_integer_round (box[i].p2.x);
1635             int y2 = _cairo_fixed_integer_round (box[i].p2.y);
1636
1637             if (x2 > x1 && y2 > y1)
1638                 shader.add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
1639         }
1640     }
1641
1642     if (! extents->is_bounded)
1643         status = i915_fixup_unbounded_boxes (dst, extents, clip, boxes);
1644
1645   err_device:
1646     cairo_device_release (&device->intel.base.base);
1647   err_shader:
1648     i915_shader_fini (&shader);
1649
1650     return status;
1651 }
1652
1653 cairo_status_t
1654 i915_surface_clear (i915_surface_t *dst)
1655 {
1656     i915_device_t *device;
1657     cairo_status_t status;
1658     intel_bo_t *bo_array[1] = { to_intel_bo (dst->intel.drm.bo) };
1659
1660     device = i915_device (dst);
1661     status = cairo_device_acquire (&device->intel.base.base);
1662     if (unlikely (status))
1663         return status;
1664
1665     if (i915_surface_needs_tiling (dst)) {
1666         int cmd, br13, clear = 0;
1667
1668         if (! i915_check_aperture_and_fences (device, bo_array, 1) ||
1669             i915_batch_space (device) < 6)
1670         {
1671             status = i915_batch_flush (device);
1672             if (unlikely (status)) {
1673                 cairo_device_release (&device->intel.base.base);
1674                 return status;
1675             }
1676         }
1677
1678         if (device->vertex_count)
1679             i915_vbo_flush (device);
1680
1681         cmd = XY_COLOR_BLT_CMD;
1682         br13 = (0xCC << 16) | dst->intel.drm.stride;
1683         switch (dst->intel.drm.format) {
1684         default:
1685         case CAIRO_FORMAT_INVALID:
1686         case CAIRO_FORMAT_A1:
1687             ASSERT_NOT_REACHED;
1688         case CAIRO_FORMAT_A8:
1689             break;
1690         case CAIRO_FORMAT_RGB16_565:
1691             br13 |= BR13_565;
1692             break;
1693         case CAIRO_FORMAT_RGB24:
1694             clear = 0xff000000;
1695         case CAIRO_FORMAT_ARGB32:
1696             br13 |= BR13_8888;
1697             cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
1698             break;
1699         }
1700
1701         OUT_DWORD (cmd);
1702         OUT_DWORD (br13);
1703         OUT_DWORD (0);
1704         OUT_DWORD (((dst->intel.drm.height - 1) << 16) |
1705                    (dst->intel.drm.width - 1));
1706         OUT_RELOC_FENCED (dst,
1707                           I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER);
1708         OUT_DWORD (clear);
1709     } else {
1710         if (! i915_check_aperture (device, bo_array, 1) ||
1711             i915_batch_space (device) < 24)
1712         {
1713             status = i915_batch_flush (device);
1714             if (unlikely (status)) {
1715                 cairo_device_release (&device->intel.base.base);
1716                 return status;
1717             }
1718         }
1719
1720         if (device->vertex_count)
1721             i915_vbo_flush (device);
1722
1723         i915_set_dst (device, dst);
1724
1725         /* set clear parameters */
1726         if (device->clear_alpha != (dst->intel.drm.base.content & CAIRO_CONTENT_ALPHA)) {
1727             device->clear_alpha = dst->intel.drm.base.content & CAIRO_CONTENT_ALPHA;
1728             OUT_DWORD (_3DSTATE_CLEAR_PARAMETERS);
1729             OUT_DWORD (CLEARPARAM_CLEAR_RECT | CLEARPARAM_WRITE_COLOR);
1730             /* ZONE_INIT color */
1731             if (device->clear_alpha) /* XXX depends on pixel format, 16bit needs replication, 8bit? */
1732                 OUT_DWORD (0x00000000);
1733             else
1734                 OUT_DWORD (0xff000000);
1735             OUT_DWORD (0); /* ZONE_INIT depth */
1736             /* CLEAR_RECT color */
1737             if (device->clear_alpha)
1738                 OUT_DWORD (0x00000000);
1739             else
1740                 OUT_DWORD (0xff000000);
1741             OUT_DWORD (0); /* CLEAR_RECT depth */
1742             OUT_DWORD (0); /* CLEAR_RECT stencil */
1743         }
1744
1745         OUT_DWORD (PRIM3D_CLEAR_RECT | 5);
1746         OUT_DWORD (pack_float (dst->intel.drm.width));
1747         OUT_DWORD (pack_float (dst->intel.drm.height));
1748         OUT_DWORD (0);
1749         OUT_DWORD (pack_float (dst->intel.drm.height));
1750         OUT_DWORD (0);
1751         OUT_DWORD (0);
1752     }
1753
1754     cairo_device_release (&device->intel.base.base);
1755
1756     dst->deferred_clear = FALSE;
1757     return status;
1758 }
1759
1760 static cairo_status_t
1761 _clip_and_composite_boxes (i915_surface_t *dst,
1762                            cairo_operator_t op,
1763                            const cairo_pattern_t *src,
1764                            cairo_boxes_t *boxes,
1765                            cairo_antialias_t antialias,
1766                            const cairo_composite_rectangles_t *extents,
1767                            cairo_clip_t *clip,
1768                            double opacity)
1769 {
1770     cairo_status_t status;
1771
1772     if (boxes->num_boxes == 0) {
1773         if (extents->is_bounded)
1774             return CAIRO_STATUS_SUCCESS;
1775
1776         return i915_fixup_unbounded (dst, extents, clip);
1777     }
1778
1779     if (clip == NULL &&
1780         (op == CAIRO_OPERATOR_SOURCE || (op == CAIRO_OPERATOR_OVER && dst->intel.drm.base.is_clear)) &&
1781         opacity == 1. &&
1782         boxes->num_boxes == 1 &&
1783         extents->bounded.width  == dst->intel.drm.width &&
1784         extents->bounded.height == dst->intel.drm.height)
1785     {
1786         op = CAIRO_OPERATOR_SOURCE;
1787         dst->deferred_clear = FALSE;
1788
1789         status = _upload_image_inplace (dst, src,
1790                                         &extents->bounded, boxes);
1791         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1792             return status;
1793     }
1794
1795     if (dst->deferred_clear) {
1796         status = i915_surface_clear (dst);
1797         if (unlikely (status))
1798             return status;
1799     }
1800
1801     /* Use a fast path if the boxes are pixel aligned */
1802     status = _composite_boxes (dst, op, src, boxes, antialias, clip, opacity, extents);
1803     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1804         return status;
1805
1806     /* Otherwise render the boxes via an implicit mask and composite in the usual
1807      * fashion.
1808      */
1809     return i915_clip_and_composite_spans (dst, op, src, antialias,
1810                                           _composite_boxes_spans, boxes,
1811                                           extents, clip, opacity);
1812 }
1813
1814 static cairo_clip_path_t *
1815 _clip_get_solitary_path (cairo_clip_t *clip)
1816 {
1817     cairo_clip_path_t *iter = clip->path;
1818     cairo_clip_path_t *path = NULL;
1819
1820     do {
1821         if ((iter->flags & CAIRO_CLIP_PATH_IS_BOX) == 0) {
1822             if (path != NULL)
1823                 return FALSE;
1824
1825             path = iter;
1826         }
1827         iter = iter->prev;
1828     } while (iter != NULL);
1829
1830     return path;
1831 }
1832
1833 typedef struct {
1834     cairo_polygon_t             polygon;
1835     cairo_fill_rule_t            fill_rule;
1836     cairo_antialias_t            antialias;
1837 } composite_polygon_info_t;
1838
1839 static cairo_status_t
1840 _composite_polygon_spans (void                          *closure,
1841                           cairo_span_renderer_t         *renderer,
1842                           const cairo_rectangle_int_t   *extents)
1843 {
1844     composite_polygon_info_t *info = closure;
1845     cairo_botor_scan_converter_t converter;
1846     cairo_status_t status;
1847     cairo_box_t box;
1848
1849     box.p1.x = _cairo_fixed_from_int (extents->x);
1850     box.p1.y = _cairo_fixed_from_int (extents->y);
1851     box.p2.x = _cairo_fixed_from_int (extents->x + extents->width);
1852     box.p2.y = _cairo_fixed_from_int (extents->y + extents->height);
1853
1854     _cairo_botor_scan_converter_init (&converter, &box, info->fill_rule);
1855
1856     status = converter.base.add_polygon (&converter.base, &info->polygon);
1857     if (likely (status == CAIRO_STATUS_SUCCESS))
1858         status = converter.base.generate (&converter.base, renderer);
1859
1860     converter.base.destroy (&converter.base);
1861
1862     return status;
1863 }
1864
1865 static cairo_int_status_t
1866 i915_surface_fill_with_alpha (void                      *abstract_dst,
1867                               cairo_operator_t           op,
1868                               const cairo_pattern_t     *source,
1869                               cairo_path_fixed_t        *path,
1870                               cairo_fill_rule_t          fill_rule,
1871                               double                     tolerance,
1872                               cairo_antialias_t          antialias,
1873                               cairo_clip_t              *clip,
1874                               double                     opacity)
1875 {
1876     i915_surface_t *dst = abstract_dst;
1877     cairo_composite_rectangles_t extents;
1878     composite_polygon_info_t info;
1879     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
1880     cairo_clip_t local_clip;
1881     cairo_bool_t have_clip = FALSE;
1882     int num_boxes = ARRAY_LENGTH (boxes_stack);
1883     cairo_status_t status;
1884
1885     status = _cairo_composite_rectangles_init_for_fill (&extents,
1886                                                         dst->intel.drm.width,
1887                                                         dst->intel.drm.height,
1888                                                         op, source, path,
1889                                                         clip);
1890     if (unlikely (status))
1891         return status;
1892
1893     if (_cairo_clip_contains_extents (clip, &extents))
1894         clip = NULL;
1895
1896     if (extents.is_bounded && clip != NULL) {
1897         cairo_clip_path_t *clip_path;
1898
1899         if (((clip_path = _clip_get_solitary_path (clip)) != NULL) &&
1900             _cairo_path_fixed_equal (&clip_path->path, path))
1901         {
1902             clip = NULL;
1903         }
1904     }
1905
1906     if (clip != NULL) {
1907         clip = _cairo_clip_init_copy (&local_clip, clip);
1908         have_clip = TRUE;
1909     }
1910
1911     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
1912     if (unlikely (status)) {
1913         if (have_clip)
1914             _cairo_clip_fini (&local_clip);
1915
1916         return status;
1917     }
1918
1919     assert (! _cairo_path_fixed_fill_is_empty (path));
1920
1921     if (_cairo_path_fixed_fill_is_rectilinear (path)) {
1922         cairo_boxes_t boxes;
1923
1924         _cairo_boxes_init (&boxes);
1925         _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
1926         status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
1927                                                               fill_rule,
1928                                                               &boxes);
1929         if (likely (status == CAIRO_STATUS_SUCCESS)) {
1930             status = _clip_and_composite_boxes (dst, op, source,
1931                                                 &boxes, antialias,
1932                                                 &extents, clip,
1933                                                 opacity);
1934         }
1935
1936         _cairo_boxes_fini (&boxes);
1937
1938         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1939             goto CLEANUP_BOXES;
1940     }
1941
1942     _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes);
1943
1944     status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &info.polygon);
1945     if (unlikely (status))
1946         goto CLEANUP_POLYGON;
1947
1948     if (extents.is_bounded) {
1949         cairo_rectangle_int_t rect;
1950
1951         _cairo_box_round_to_rectangle (&info.polygon.extents, &rect);
1952         if (! _cairo_rectangle_intersect (&extents.bounded, &rect))
1953             goto CLEANUP_POLYGON;
1954     }
1955
1956     if (info.polygon.num_edges == 0) {
1957         if (! extents.is_bounded)
1958             status = i915_fixup_unbounded (dst, &extents, clip);
1959
1960         goto CLEANUP_POLYGON;
1961     }
1962
1963     info.fill_rule = fill_rule;
1964     info.antialias = antialias;
1965     status = i915_clip_and_composite_spans (dst, op, source, antialias,
1966                                             _composite_polygon_spans, &info,
1967                                             &extents, clip, opacity);
1968
1969 CLEANUP_POLYGON:
1970     _cairo_polygon_fini (&info.polygon);
1971
1972 CLEANUP_BOXES:
1973     if (clip_boxes != boxes_stack)
1974         free (clip_boxes);
1975
1976     if (have_clip)
1977         _cairo_clip_fini (&local_clip);
1978
1979     return status;
1980 }
1981
1982 static cairo_int_status_t
1983 i915_surface_paint_with_alpha (void                     *abstract_dst,
1984                                cairo_operator_t          op,
1985                                const cairo_pattern_t    *source,
1986                                cairo_clip_t             *clip,
1987                                double                    opacity)
1988 {
1989     i915_surface_t *dst = abstract_dst;
1990     cairo_composite_rectangles_t extents;
1991     cairo_clip_t local_clip;
1992     cairo_bool_t have_clip = FALSE;
1993     cairo_clip_path_t *clip_path;
1994     cairo_boxes_t boxes;
1995     int num_boxes = ARRAY_LENGTH (boxes.boxes_embedded);
1996     cairo_box_t *clip_boxes = boxes.boxes_embedded;
1997     cairo_status_t status;
1998
1999     status = _cairo_composite_rectangles_init_for_paint (&extents,
2000                                                          dst->intel.drm.width,
2001                                                          dst->intel.drm.height,
2002                                                          op, source,
2003                                                          clip);
2004     if (unlikely (status))
2005         return status;
2006
2007     if (_cairo_clip_contains_extents (clip, &extents))
2008         clip = NULL;
2009
2010     if (clip != NULL) {
2011         clip = _cairo_clip_init_copy (&local_clip, clip);
2012         have_clip = TRUE;
2013     }
2014
2015     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
2016     if (unlikely (status)) {
2017         if (have_clip)
2018             _cairo_clip_fini (&local_clip);
2019
2020         return status;
2021     }
2022
2023     /* If the clip cannot be reduced to a set of boxes, we will need to
2024      * use a clipmask. Paint is special as it is the only operation that
2025      * does not implicitly use a mask, so we may be able to reduce this
2026      * operation to a fill...
2027      */
2028     if (clip != NULL &&
2029         extents.is_bounded &&
2030         (clip_path = _clip_get_solitary_path (clip)) != NULL)
2031     {
2032         status = i915_surface_fill_with_alpha (dst, op, source,
2033                                                &clip_path->path,
2034                                                clip_path->fill_rule,
2035                                                clip_path->tolerance,
2036                                                clip_path->antialias,
2037                                                NULL, opacity);
2038     }
2039     else
2040     {
2041         _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
2042         status = _clip_and_composite_boxes (dst, op, source,
2043                                             &boxes, CAIRO_ANTIALIAS_DEFAULT,
2044                                             &extents, clip, opacity);
2045     }
2046     if (clip_boxes != boxes.boxes_embedded)
2047         free (clip_boxes);
2048
2049     if (have_clip)
2050         _cairo_clip_fini (&local_clip);
2051
2052     return status;
2053 }
2054
2055 static cairo_int_status_t
2056 i915_surface_paint (void                        *abstract_dst,
2057                     cairo_operator_t             op,
2058                     const cairo_pattern_t       *source,
2059                     cairo_clip_t                *clip)
2060 {
2061     i915_surface_t *dst = abstract_dst;
2062
2063     /* XXX unsupported operators? use pixel shader blending, eventually */
2064
2065     if (op == CAIRO_OPERATOR_CLEAR && clip == NULL) {
2066         dst->deferred_clear = TRUE;
2067         return CAIRO_STATUS_SUCCESS;
2068     }
2069
2070     return i915_surface_paint_with_alpha (dst, op, source, clip, 1.);
2071 }
2072
2073 static cairo_int_status_t
2074 i915_surface_mask (void                         *abstract_dst,
2075                    cairo_operator_t              op,
2076                    const cairo_pattern_t        *source,
2077                    const cairo_pattern_t        *mask,
2078                    cairo_clip_t                 *clip)
2079 {
2080     i915_surface_t *dst = abstract_dst;
2081     i915_device_t *device;
2082     cairo_composite_rectangles_t extents;
2083     i915_shader_t shader;
2084     cairo_clip_t local_clip;
2085     cairo_region_t *clip_region = NULL;
2086     cairo_bool_t need_clip_surface = FALSE;
2087     cairo_bool_t have_clip = FALSE;
2088     cairo_status_t status;
2089
2090     if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
2091         const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) mask;
2092         return i915_surface_paint_with_alpha (dst, op, source, clip, solid->color.alpha);
2093     }
2094
2095     status = _cairo_composite_rectangles_init_for_mask (&extents,
2096                                                         dst->intel.drm.width,
2097                                                         dst->intel.drm.height,
2098                                                         op, source, mask, clip);
2099     if (unlikely (status))
2100         return status;
2101
2102     if (_cairo_clip_contains_extents (clip, &extents))
2103         clip = NULL;
2104
2105     if (clip != NULL && extents.is_bounded) {
2106         clip = _cairo_clip_init_copy (&local_clip, clip);
2107         status = _cairo_clip_rectangle (clip, &extents.bounded);
2108         if (unlikely (status)) {
2109             _cairo_clip_fini (&local_clip);
2110             return status;
2111         }
2112
2113         have_clip = TRUE;
2114     }
2115
2116     i915_shader_init (&shader, dst, op, 1.);
2117
2118     status = i915_shader_acquire_pattern (&shader,
2119                                           &shader.source,
2120                                           source,
2121                                           &extents.bounded);
2122     if (unlikely (status))
2123         goto err_shader;
2124
2125     status = i915_shader_acquire_pattern (&shader,
2126                                           &shader.mask,
2127                                           mask,
2128                                           &extents.bounded);
2129     if (unlikely (status))
2130         goto err_shader;
2131
2132     if (clip != NULL) {
2133         status = _cairo_clip_get_region (clip, &clip_region);
2134         if (unlikely (_cairo_status_is_error (status) ||
2135                       status == CAIRO_INT_STATUS_NOTHING_TO_DO))
2136         {
2137             goto err_shader;
2138         }
2139
2140         need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
2141         if (need_clip_surface)
2142             i915_shader_set_clip (&shader, clip);
2143
2144         if (clip_region != NULL) {
2145             cairo_rectangle_int_t rect;
2146             cairo_bool_t is_empty;
2147
2148             status = CAIRO_STATUS_SUCCESS;
2149             cairo_region_get_extents (clip_region, &rect);
2150             is_empty = ! _cairo_rectangle_intersect (&extents.unbounded, &rect);
2151             if (unlikely (is_empty))
2152                 goto err_shader;
2153
2154             is_empty = ! _cairo_rectangle_intersect (&extents.bounded, &rect);
2155             if (unlikely (is_empty && extents.is_bounded))
2156                 goto err_shader;
2157
2158             if (cairo_region_num_rectangles (clip_region) == 1)
2159                 clip_region = NULL;
2160         }
2161     }
2162
2163     if (i915_surface_needs_tiling (dst)) {
2164         ASSERT_NOT_REACHED;
2165         return CAIRO_INT_STATUS_UNSUPPORTED;
2166     }
2167
2168     device = i915_device (dst);
2169     status = cairo_device_acquire (&device->intel.base.base);
2170     if (unlikely (status))
2171         goto err_shader;
2172
2173     if (dst->deferred_clear) {
2174         status = i915_surface_clear (dst);
2175         if (unlikely (status))
2176             goto err_shader;
2177     }
2178
2179     status = i915_shader_commit (&shader, device);
2180     if (unlikely (status))
2181         goto err_device;
2182
2183     if (clip_region != NULL) {
2184         unsigned int n, num_rectangles;
2185
2186         num_rectangles = cairo_region_num_rectangles (clip_region);
2187         for (n = 0; n < num_rectangles; n++) {
2188             cairo_rectangle_int_t rect;
2189
2190             cairo_region_get_rectangle (clip_region, n, &rect);
2191
2192             shader.add_rectangle (&shader,
2193                                   rect.x, rect.y,
2194                                   rect.x + rect.width, rect.y + rect.height);
2195         }
2196     } else {
2197         shader.add_rectangle (&shader,
2198                               extents.bounded.x, extents.bounded.y,
2199                               extents.bounded.x + extents.bounded.width,
2200                               extents.bounded.y + extents.bounded.height);
2201     }
2202
2203     if (! extents.is_bounded)
2204         status = i915_fixup_unbounded (dst, &extents, clip);
2205
2206   err_device:
2207     cairo_device_release (&device->intel.base.base);
2208   err_shader:
2209     i915_shader_fini (&shader);
2210     if (have_clip)
2211         _cairo_clip_fini (&local_clip);
2212
2213     return status;
2214 }
2215
2216 static cairo_int_status_t
2217 i915_surface_stroke (void                       *abstract_dst,
2218                      cairo_operator_t            op,
2219                      const cairo_pattern_t      *source,
2220                      cairo_path_fixed_t         *path,
2221                      const cairo_stroke_style_t *stroke_style,
2222                      const cairo_matrix_t       *ctm,
2223                      const cairo_matrix_t       *ctm_inverse,
2224                      double                      tolerance,
2225                      cairo_antialias_t           antialias,
2226                      cairo_clip_t               *clip)
2227 {
2228     i915_surface_t *dst = abstract_dst;
2229     cairo_composite_rectangles_t extents;
2230     composite_polygon_info_t info;
2231     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
2232     int num_boxes = ARRAY_LENGTH (boxes_stack);
2233     cairo_clip_t local_clip;
2234     cairo_bool_t have_clip = FALSE;
2235     cairo_status_t status;
2236
2237     status = _cairo_composite_rectangles_init_for_stroke (&extents,
2238                                                           dst->intel.drm.width,
2239                                                           dst->intel.drm.height,
2240                                                           op, source,
2241                                                           path, stroke_style, ctm,
2242                                                           clip);
2243     if (unlikely (status))
2244         return status;
2245
2246     if (_cairo_clip_contains_extents (clip, &extents))
2247         clip = NULL;
2248
2249     if (clip != NULL) {
2250         clip = _cairo_clip_init_copy (&local_clip, clip);
2251         have_clip = TRUE;
2252     }
2253
2254     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
2255     if (unlikely (status)) {
2256         if (have_clip)
2257             _cairo_clip_fini (&local_clip);
2258
2259         return status;
2260     }
2261
2262     if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
2263         cairo_boxes_t boxes;
2264
2265         _cairo_boxes_init (&boxes);
2266         _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
2267         status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
2268                                                                 stroke_style,
2269                                                                 ctm,
2270                                                                 &boxes);
2271         if (likely (status == CAIRO_STATUS_SUCCESS)) {
2272             status = _clip_and_composite_boxes (dst, op, source,
2273                                                 &boxes, antialias,
2274                                                 &extents, clip, 1.);
2275         }
2276
2277         _cairo_boxes_fini (&boxes);
2278
2279         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2280             goto CLEANUP_BOXES;
2281     }
2282
2283     _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes);
2284
2285     status = _cairo_path_fixed_stroke_to_polygon (path,
2286                                                   stroke_style,
2287                                                   ctm, ctm_inverse,
2288                                                   tolerance,
2289                                                   &info.polygon);
2290     if (unlikely (status))
2291         goto CLEANUP_POLYGON;
2292
2293     if (extents.is_bounded) {
2294         cairo_rectangle_int_t rect;
2295
2296         _cairo_box_round_to_rectangle (&info.polygon.extents, &rect);
2297         if (! _cairo_rectangle_intersect (&extents.bounded, &rect))
2298             goto CLEANUP_POLYGON;
2299     }
2300
2301     if (info.polygon.num_edges == 0) {
2302         if (! extents.is_bounded)
2303             status = i915_fixup_unbounded (dst, &extents, clip);
2304
2305         goto CLEANUP_POLYGON;
2306     }
2307
2308     info.fill_rule = CAIRO_FILL_RULE_WINDING;
2309     info.antialias = antialias;
2310     status = i915_clip_and_composite_spans (dst, op, source, antialias,
2311                                             _composite_polygon_spans, &info,
2312                                             &extents, clip, 1.);
2313
2314 CLEANUP_POLYGON:
2315     _cairo_polygon_fini (&info.polygon);
2316
2317 CLEANUP_BOXES:
2318     if (clip_boxes != boxes_stack)
2319         free (clip_boxes);
2320
2321     if (have_clip)
2322         _cairo_clip_fini (&local_clip);
2323
2324     return status;
2325 }
2326
2327 static cairo_int_status_t
2328 i915_surface_fill (void                 *abstract_dst,
2329                    cairo_operator_t      op,
2330                    const cairo_pattern_t*source,
2331                    cairo_path_fixed_t   *path,
2332                    cairo_fill_rule_t     fill_rule,
2333                    double                tolerance,
2334                    cairo_antialias_t     antialias,
2335                    cairo_clip_t         *clip)
2336 {
2337     return i915_surface_fill_with_alpha (abstract_dst, op, source, path, fill_rule, tolerance, antialias, clip, 1.);
2338 }
2339
2340 static const cairo_surface_backend_t i915_surface_backend = {
2341     CAIRO_SURFACE_TYPE_DRM,
2342     _cairo_default_context_create,
2343
2344     i915_surface_create_similar,
2345     i915_surface_finish,
2346
2347     NULL,
2348     intel_surface_acquire_source_image,
2349     intel_surface_release_source_image,
2350
2351     NULL, NULL, NULL,
2352     NULL, /* composite */
2353     NULL, /* fill */
2354     NULL, /* trapezoids */
2355     NULL, /* span */
2356     NULL, /* check-span */
2357
2358     NULL, /* copy_page */
2359     NULL, /* show_page */
2360     _cairo_drm_surface_get_extents,
2361     NULL, /* old-glyphs */
2362     _cairo_drm_surface_get_font_options,
2363
2364     i915_surface_flush,
2365     NULL, /* mark_dirty */
2366     intel_scaled_font_fini,
2367     intel_scaled_glyph_fini,
2368
2369     i915_surface_paint,
2370     i915_surface_mask,
2371     i915_surface_stroke,
2372     i915_surface_fill,
2373     i915_surface_glyphs,
2374 };
2375
2376 static void
2377 i915_surface_init (i915_surface_t *surface,
2378                    cairo_drm_device_t *device,
2379                    cairo_format_t format,
2380                    int width, int height)
2381 {
2382     intel_surface_init (&surface->intel, &i915_surface_backend, device,
2383                         format, width, height);
2384
2385     switch (format) {
2386     default:
2387     case CAIRO_FORMAT_INVALID:
2388     case CAIRO_FORMAT_A1:
2389         ASSERT_NOT_REACHED;
2390     case CAIRO_FORMAT_ARGB32:
2391         surface->map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888;
2392         surface->colorbuf = COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER;
2393         break;
2394     case CAIRO_FORMAT_RGB24:
2395         surface->map0 = MAPSURF_32BIT | MT_32BIT_XRGB8888;
2396         surface->colorbuf = COLR_BUF_ARGB8888 | DEPTH_FRMT_24_FIXED_8_OTHER;
2397         break;
2398     case CAIRO_FORMAT_RGB16_565:
2399         surface->map0 = MAPSURF_16BIT | MT_16BIT_RGB565;
2400         surface->colorbuf = COLR_BUF_RGB565;
2401         break;
2402     case CAIRO_FORMAT_A8:
2403         surface->map0 = MAPSURF_8BIT | MT_8BIT_A8;
2404         surface->colorbuf = COLR_BUF_8BIT | DEPTH_FRMT_24_FIXED_8_OTHER;
2405         break;
2406     }
2407     surface->colorbuf |= DSTORG_HORT_BIAS (0x8) | DSTORG_VERT_BIAS (0x8);
2408     surface->map0 |= ((height - 1) << MS3_HEIGHT_SHIFT) |
2409                      ((width  - 1) << MS3_WIDTH_SHIFT);
2410     surface->map1 = 0;
2411
2412     surface->is_current_texture = 0;
2413     surface->deferred_clear = FALSE;
2414
2415     surface->offset = 0;
2416
2417     surface->stencil  = NULL;
2418     surface->cache = NULL;
2419 }
2420
2421 cairo_surface_t *
2422 i915_surface_create_internal (cairo_drm_device_t *base_dev,
2423                               cairo_format_t format,
2424                               int width, int height,
2425                               uint32_t tiling,
2426                               cairo_bool_t gpu_target)
2427 {
2428     i915_surface_t *surface;
2429     cairo_status_t status_ignored;
2430
2431     surface = malloc (sizeof (i915_surface_t));
2432     if (unlikely (surface == NULL))
2433         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
2434
2435     i915_surface_init (surface, base_dev, format, width, height);
2436
2437     if (width && height) {
2438         uint32_t size, stride;
2439         intel_bo_t *bo;
2440
2441         width = (width + 3) & -4;
2442         stride = cairo_format_stride_for_width (surface->intel.drm.format, width);
2443         /* check for tiny surfaces for which tiling is irrelevant */
2444         if (height * stride <= 4096)
2445             tiling = I915_TILING_NONE;
2446         if (tiling != I915_TILING_NONE && stride <= 512)
2447             tiling = I915_TILING_NONE;
2448         if (tiling != I915_TILING_NONE) {
2449             if (height <= 8)
2450                 tiling = I915_TILING_NONE;
2451             else if (height <= 16)
2452                 tiling = I915_TILING_X;
2453         }
2454         /* large surfaces we need to blt, so force TILING_X */
2455         if (height > 2048)
2456             tiling = I915_TILING_X;
2457         /* but there is a maximum limit to the tiling pitch */
2458         if (tiling != I915_TILING_NONE && stride > 8192)
2459             tiling = I915_TILING_NONE;
2460
2461         stride = i915_tiling_stride (tiling, stride);
2462         assert (stride >= (uint32_t) cairo_format_stride_for_width (surface->intel.drm.format, width));
2463         assert (tiling == I915_TILING_NONE || stride <= 8192);
2464         height = i915_tiling_height (tiling, height);
2465         if (height > 64*1024) {
2466             free (surface);
2467             cairo_device_destroy (&base_dev->base);
2468             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
2469         }
2470
2471         size = stride * height;
2472         bo = intel_bo_create (to_intel_device (&base_dev->base),
2473                               i915_tiling_size (tiling, size), size,
2474                               gpu_target, tiling, stride);
2475         if (bo == NULL) {
2476             status_ignored = _cairo_drm_surface_finish (&surface->intel.drm);
2477             free (surface);
2478             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
2479         }
2480         assert (bo->base.size >= size);
2481
2482         surface->intel.drm.bo = &bo->base;
2483         surface->intel.drm.stride = stride;
2484
2485         surface->map0 |= MS3_tiling (tiling);
2486         surface->map1 = (stride/4 - 1) << MS4_PITCH_SHIFT;
2487     }
2488
2489     return &surface->intel.drm.base;
2490 }
2491
2492 static cairo_surface_t *
2493 i915_surface_create (cairo_drm_device_t *base_dev,
2494                      cairo_format_t format,
2495                      int width, int height)
2496 {
2497     switch (format) {
2498     case CAIRO_FORMAT_ARGB32:
2499     case CAIRO_FORMAT_RGB16_565:
2500     case CAIRO_FORMAT_RGB24:
2501     case CAIRO_FORMAT_A8:
2502         break;
2503     case CAIRO_FORMAT_INVALID:
2504     default:
2505     case CAIRO_FORMAT_A1:
2506         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
2507     }
2508
2509     return i915_surface_create_internal (base_dev, format, width, height,
2510                                          I915_TILING_DEFAULT, TRUE);
2511 }
2512
2513 static cairo_surface_t *
2514 i915_surface_create_for_name (cairo_drm_device_t *base_dev,
2515                               unsigned int name,
2516                               cairo_format_t format,
2517                               int width, int height, int stride)
2518 {
2519     i915_surface_t *surface;
2520
2521     /* Vol I, p134: size restrictions for textures */
2522     /* Vol I, p129: destination surface stride must be a multiple of 32 bytes */
2523     if (stride < cairo_format_stride_for_width (format, (width + 3) & -4) ||
2524         stride & 31)
2525     {
2526         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
2527     }
2528
2529     switch (format) {
2530     default:
2531     case CAIRO_FORMAT_INVALID:
2532     case CAIRO_FORMAT_A1:
2533         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
2534     case CAIRO_FORMAT_ARGB32:
2535     case CAIRO_FORMAT_RGB16_565:
2536     case CAIRO_FORMAT_RGB24:
2537     case CAIRO_FORMAT_A8:
2538         break;
2539     }
2540
2541     surface = malloc (sizeof (i915_surface_t));
2542     if (unlikely (surface == NULL))
2543         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
2544
2545     i915_surface_init (surface, base_dev, format, width, height);
2546
2547     if (width && height) {
2548         surface->intel.drm.stride = stride;
2549         surface->map1 = (surface->intel.drm.stride/4 - 1) << MS4_PITCH_SHIFT;
2550
2551         surface->intel.drm.bo =
2552             &intel_bo_create_for_name (to_intel_device (&base_dev->base),
2553                                        name)->base;
2554         if (unlikely (surface->intel.drm.bo == NULL)) {
2555             free (surface);
2556             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
2557         }
2558         to_intel_bo (surface->intel.drm.bo)->stride = stride;
2559
2560         surface->map0 |= MS3_tiling (to_intel_bo (surface->intel.drm.bo)->tiling);
2561     }
2562
2563     return &surface->intel.drm.base;
2564 }
2565
2566 static cairo_status_t
2567 i915_buffer_cache_init (intel_buffer_cache_t *cache,
2568                         i915_device_t *device,
2569                         cairo_format_t format,
2570                         int width, int height)
2571 {
2572     const uint32_t tiling = I915_TILING_DEFAULT;
2573     uint32_t stride, size;
2574
2575     assert ((width & 3) == 0);
2576     assert ((height & 1) == 0);
2577     cache->buffer.width = width;
2578     cache->buffer.height = height;
2579
2580     switch (format) {
2581     case CAIRO_FORMAT_INVALID:
2582     case CAIRO_FORMAT_A1:
2583     case CAIRO_FORMAT_RGB24:
2584     case CAIRO_FORMAT_RGB16_565:
2585         ASSERT_NOT_REACHED;
2586     case CAIRO_FORMAT_ARGB32:
2587         cache->buffer.map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888;
2588         stride = width * 4;
2589         break;
2590     case CAIRO_FORMAT_A8:
2591         cache->buffer.map0 = MAPSURF_8BIT | MT_8BIT_I8;
2592         stride = width;
2593         break;
2594     }
2595     assert ((stride & 7) == 0);
2596     assert (i915_tiling_stride (tiling, stride) == stride);
2597     assert (i915_tiling_height (tiling, height) == height);
2598
2599     size = height * stride;
2600     assert (i915_tiling_size (tiling, size) == size);
2601     cache->buffer.bo = intel_bo_create (&device->intel, size, size, FALSE, tiling, stride);
2602     if (unlikely (cache->buffer.bo == NULL))
2603         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2604
2605     cache->buffer.stride = cache->buffer.bo->stride;
2606
2607     cache->buffer.map0 |= ((height - 1) << MS3_HEIGHT_SHIFT) |
2608                           ((width  - 1) << MS3_WIDTH_SHIFT);
2609     cache->buffer.map0 |= MS3_tiling (tiling);
2610     cache->buffer.map1 = ((stride / 4) - 1) << MS4_PITCH_SHIFT;
2611
2612     cache->ref_count = 0;
2613     cairo_list_init (&cache->link);
2614
2615     return CAIRO_STATUS_SUCCESS;
2616 }
2617
2618 i915_surface_t *
2619 i915_surface_create_from_cacheable_image_internal (i915_device_t *device,
2620                                                    cairo_image_surface_t *image)
2621 {
2622     i915_surface_t *surface;
2623     cairo_status_t status;
2624     cairo_list_t *caches;
2625     intel_buffer_cache_t *cache;
2626     cairo_rtree_node_t *node;
2627     cairo_format_t format;
2628     int width, height, bpp;
2629
2630     format = image->format;
2631     if (format == CAIRO_FORMAT_A1)
2632         format = CAIRO_FORMAT_A8;
2633
2634     width = image->width;
2635     height = image->height;
2636     if (width > IMAGE_CACHE_WIDTH/2 || height > IMAGE_CACHE_HEIGHT/2) {
2637         surface = (i915_surface_t *)
2638             i915_surface_create_internal (&device->intel.base,
2639                                           format,
2640                                           width, height,
2641                                           I915_TILING_NONE, FALSE);
2642         if (unlikely (surface->intel.drm.base.status))
2643             return surface;
2644
2645         status = intel_bo_put_image (&device->intel,
2646                                      to_intel_bo (surface->intel.drm.bo),
2647                                      image,
2648                                      0, 0,
2649                                      width, height,
2650                                      0, 0);
2651
2652         if (unlikely (status)) {
2653             cairo_surface_destroy (&surface->intel.drm.base);
2654             return (i915_surface_t *) _cairo_surface_create_in_error (status);
2655         }
2656
2657         return surface;
2658     }
2659
2660     status = cairo_device_acquire (&device->intel.base.base);
2661     if (unlikely (status))
2662         return (i915_surface_t *) _cairo_surface_create_in_error (status);
2663
2664     switch (image->format) {
2665     case CAIRO_FORMAT_ARGB32:
2666     case CAIRO_FORMAT_RGB24:
2667     case CAIRO_FORMAT_RGB16_565:
2668         caches = &device->image_caches[0];
2669         format = CAIRO_FORMAT_ARGB32;
2670         bpp = 4;
2671         break;
2672     case CAIRO_FORMAT_A8:
2673     case CAIRO_FORMAT_A1:
2674         caches = &device->image_caches[1];
2675         format = CAIRO_FORMAT_A8;
2676         bpp = 1;
2677         break;
2678     case CAIRO_FORMAT_INVALID:
2679     default:
2680         ASSERT_NOT_REACHED;
2681         status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
2682         goto CLEANUP_DEVICE;
2683     }
2684
2685     node = NULL;
2686     cairo_list_foreach_entry (cache, intel_buffer_cache_t, caches, link) {
2687         if (! intel_bo_is_inactive (&device->intel, cache->buffer.bo))
2688             continue;
2689
2690         status = _cairo_rtree_insert (&cache->rtree, width, height, &node);
2691         if (unlikely (_cairo_status_is_error (status)))
2692             goto CLEANUP_DEVICE;
2693         if (status == CAIRO_STATUS_SUCCESS)
2694             break;
2695     }
2696     if (node == NULL) {
2697         cache = malloc (sizeof (intel_buffer_cache_t));
2698         if (unlikely (cache == NULL)) {
2699             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2700             goto CLEANUP_DEVICE;
2701         }
2702
2703         status = i915_buffer_cache_init (cache, device, format,
2704                                          IMAGE_CACHE_WIDTH,
2705                                          IMAGE_CACHE_HEIGHT);
2706         if (unlikely (status)) {
2707             free (cache);
2708             goto CLEANUP_DEVICE;
2709         }
2710
2711         _cairo_rtree_init (&cache->rtree,
2712                            IMAGE_CACHE_WIDTH,
2713                            IMAGE_CACHE_HEIGHT,
2714                            4,
2715                            sizeof (i915_image_private_t));
2716
2717         status = _cairo_rtree_insert (&cache->rtree, width, height, &node);
2718         assert (status == CAIRO_STATUS_SUCCESS);
2719
2720         cairo_list_init (&cache->link);
2721     }
2722     cairo_list_move (&cache->link, caches);
2723     ((i915_image_private_t *) node)->container = cache;
2724
2725     status = intel_bo_put_image (&device->intel,
2726                                  cache->buffer.bo,
2727                                  image,
2728                                  0, 0,
2729                                  width, height,
2730                                  node->x, node->y);
2731     if (unlikely (status))
2732         goto CLEANUP_CACHE;
2733
2734     surface = malloc (sizeof (i915_surface_t));
2735     if (unlikely (surface == NULL)) {
2736         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2737         goto CLEANUP_CACHE;
2738     }
2739
2740     i915_surface_init (surface, &device->intel.base,
2741                        format, width, height);
2742
2743     surface->intel.drm.stride = cache->buffer.stride;
2744
2745     surface->map0 |= MS3_tiling (cache->buffer.bo->tiling);
2746     surface->map1 = (surface->intel.drm.stride/4 - 1) << MS4_PITCH_SHIFT;
2747
2748     surface->intel.drm.bo = &intel_bo_reference (cache->buffer.bo)->base;
2749     surface->offset = node->y * cache->buffer.stride + bpp * node->x;
2750
2751     surface->cache = (i915_image_private_t *) node;
2752     cache->ref_count++;
2753
2754     cairo_device_release (&device->intel.base.base);
2755
2756     return surface;
2757
2758 CLEANUP_CACHE:
2759     _cairo_rtree_node_destroy (&cache->rtree, node);
2760     if (cache->ref_count == 0) {
2761         intel_bo_destroy (&device->intel, cache->buffer.bo);
2762         _cairo_rtree_fini (&cache->rtree);
2763         cairo_list_del (&cache->link);
2764         free (cache);
2765     }
2766 CLEANUP_DEVICE:
2767     cairo_device_release (&device->intel.base.base);
2768     return (i915_surface_t *) _cairo_surface_create_in_error (status);
2769 }
2770
2771 static cairo_surface_t *
2772 i915_surface_create_from_cacheable_image (cairo_drm_device_t *device,
2773                                           cairo_surface_t *source)
2774 {
2775     i915_surface_t *surface;
2776     cairo_image_surface_t *image;
2777     void *image_extra;
2778     cairo_status_t status;
2779
2780     status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
2781     if (unlikely (status))
2782         return _cairo_surface_create_in_error (status);
2783
2784     surface = i915_surface_create_from_cacheable_image_internal ((i915_device_t *) device, image);
2785
2786     _cairo_surface_release_source_image (source, image, image_extra);
2787
2788     return &surface->intel.drm.base;
2789 }
2790
2791 static cairo_status_t
2792 i915_surface_enable_scan_out (void *abstract_surface)
2793 {
2794     i915_surface_t *surface = abstract_surface;
2795     intel_bo_t *bo;
2796     cairo_status_t status;
2797
2798     if (unlikely (surface->intel.drm.bo == NULL))
2799         return _cairo_error (CAIRO_STATUS_INVALID_SIZE);
2800
2801     bo = to_intel_bo (surface->intel.drm.bo);
2802     if (bo->tiling == I915_TILING_Y) {
2803         status = i915_surface_batch_flush (surface);
2804         if (unlikely (status))
2805             return status;
2806
2807         bo->tiling = I915_TILING_X;
2808         surface->map0 &= ~MS3_tiling (I915_TILING_Y);
2809         surface->map0 |= MS3_tiling (I915_TILING_X);
2810     }
2811
2812
2813     return CAIRO_STATUS_SUCCESS;
2814 }
2815
2816 static cairo_int_status_t
2817 i915_device_flush (cairo_drm_device_t *device)
2818 {
2819     cairo_status_t status;
2820
2821     if (unlikely (device->base.finished))
2822         return CAIRO_STATUS_SUCCESS;
2823
2824     status = cairo_device_acquire (&device->base);
2825     if (likely (status == CAIRO_STATUS_SUCCESS)) {
2826         status = i915_batch_flush ((i915_device_t *) device);
2827         cairo_device_release (&device->base);
2828     }
2829
2830     return status;
2831 }
2832
2833 static cairo_int_status_t
2834 i915_device_throttle (cairo_drm_device_t *device)
2835 {
2836     cairo_status_t status;
2837
2838     status = cairo_device_acquire (&device->base);
2839     if (unlikely (status))
2840         return status;
2841
2842     status = i915_batch_flush ((i915_device_t *) device);
2843     intel_throttle ((intel_device_t *) device);
2844
2845     cairo_device_release (&device->base);
2846
2847     return status;
2848 }
2849
2850 static void
2851 i915_device_destroy (void *data)
2852 {
2853     i915_device_t *device = data;
2854
2855     if (device->last_vbo)
2856         intel_bo_destroy (&device->intel, device->last_vbo);
2857
2858     i915_batch_cleanup (device);
2859
2860     intel_device_fini (&device->intel);
2861     free (device);
2862 }
2863
2864 COMPILE_TIME_ASSERT (sizeof (i915_batch_setup) == sizeof (((i915_device_t *)0)->batch_header));
2865 COMPILE_TIME_ASSERT (offsetof (i915_device_t, batch_base) == offsetof (i915_device_t, batch_header) + sizeof (i915_batch_setup));
2866
2867 cairo_drm_device_t *
2868 _cairo_drm_i915_device_create (int fd, dev_t dev_id, int vendor_id, int chip_id)
2869 {
2870     i915_device_t *device;
2871     cairo_status_t status;
2872     uint64_t gtt_size;
2873     int n;
2874
2875     if (! intel_info (fd, &gtt_size))
2876         return NULL;
2877
2878     device = malloc (sizeof (i915_device_t));
2879     if (device == NULL)
2880         return (cairo_drm_device_t *) _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
2881
2882     status = intel_device_init (&device->intel, fd);
2883     if (unlikely (status)) {
2884         free (device);
2885         return (cairo_drm_device_t *) _cairo_device_create_in_error (status);
2886     }
2887
2888     device->debug = 0;
2889     if (getenv ("CAIRO_DEBUG_DRM") != NULL)
2890         device->debug = I915_DEBUG_SYNC;
2891
2892     n = intel_get (fd, I915_PARAM_NUM_FENCES_AVAIL);
2893     if (n == 0)
2894         n = 8;
2895     device->batch.fences_avail = n - 2; /* conservative */
2896
2897     device->batch.gtt_avail_size = device->intel.gtt_avail_size / 4;
2898     device->batch.est_gtt_size = I915_BATCH_SIZE;
2899     device->batch.total_gtt_size = I915_BATCH_SIZE;
2900     device->batch.exec_count = 0;
2901     device->batch.reloc_count = 0;
2902     device->batch.used = 0;
2903     device->batch.fences = 0;
2904
2905     memcpy (device->batch_header, i915_batch_setup, sizeof (i915_batch_setup));
2906     device->vbo = 0;
2907     device->vbo_offset = 0;
2908     device->vbo_used = 0;
2909     device->vertex_index = 0;
2910     device->vertex_count = 0;
2911     device->last_vbo = NULL;
2912
2913     for (n = 0; n < ARRAY_LENGTH (device->image_caches); n++)
2914         cairo_list_init (&device->image_caches[n]);
2915
2916     device->intel.base.surface.create = i915_surface_create;
2917     device->intel.base.surface.create_for_name = i915_surface_create_for_name;
2918     device->intel.base.surface.create_from_cacheable_image = i915_surface_create_from_cacheable_image;
2919
2920     device->intel.base.surface.flink = _cairo_drm_surface_flink;
2921     device->intel.base.surface.enable_scan_out = i915_surface_enable_scan_out;
2922     device->intel.base.surface.map_to_image = intel_surface_map_to_image;
2923
2924     device->intel.base.device.flush = i915_device_flush;
2925     device->intel.base.device.throttle = i915_device_throttle;
2926     device->intel.base.device.destroy = i915_device_destroy;
2927
2928     device->floats_per_vertex = 0;
2929     device->current_source = NULL;
2930     device->current_mask = NULL;
2931     device->current_clip = NULL;
2932
2933     i915_device_reset (device);
2934
2935     return _cairo_drm_device_init (&device->intel.base,
2936                                    fd, dev_id, vendor_id, chip_id,
2937                                    16*1024);
2938 }