intel_blit.c revision 1f196b786d6bd0c6a5dbdc638574ff716cc3d4de
1/**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29#include "main/mtypes.h"
30#include "main/context.h"
31#include "main/enums.h"
32#include "main/colormac.h"
33
34#include "intel_blit.h"
35#include "intel_buffers.h"
36#include "intel_context.h"
37#include "intel_fbo.h"
38#include "intel_reg.h"
39#include "intel_regions.h"
40#include "intel_batchbuffer.h"
41#include "intel_chipset.h"
42
43#define FILE_DEBUG_FLAG DEBUG_BLIT
44
45/**
46 * Copy the back color buffer to the front color buffer.
47 * Used for SwapBuffers().
48 */
49void
50intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
51                const drm_clip_rect_t * rect)
52{
53
54   struct intel_context *intel;
55   const intelScreenPrivate *intelScreen;
56
57   DBG("%s\n", __FUNCTION__);
58
59   assert(dPriv);
60
61   intel = intelScreenContext(dPriv->driScreenPriv->private);
62   if (!intel)
63      return;
64
65   intelScreen = intel->intelScreen;
66
67   /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets
68    * should work regardless.
69    */
70   LOCK_HARDWARE(intel);
71
72   if (dPriv && dPriv->numClipRects) {
73      struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
74      struct intel_region *src, *dst;
75      int nbox = dPriv->numClipRects;
76      drm_clip_rect_t *pbox = dPriv->pClipRects;
77      int cpp;
78      int src_pitch, dst_pitch;
79      unsigned short src_x, src_y;
80      int BR13, CMD;
81      int i;
82      dri_bo *aper_array[3];
83
84      src = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);
85      dst = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT);
86
87      src_pitch = src->pitch * src->cpp;
88      dst_pitch = dst->pitch * dst->cpp;
89
90      cpp = src->cpp;
91
92      ASSERT(intel_fb);
93      ASSERT(intel_fb->Base.Name == 0);    /* Not a user-created FBO */
94      ASSERT(src);
95      ASSERT(dst);
96      ASSERT(src->cpp == dst->cpp);
97
98      if (cpp == 2) {
99	 BR13 = (0xCC << 16) | BR13_565;
100	 CMD = XY_SRC_COPY_BLT_CMD;
101      }
102      else {
103	 BR13 = (0xCC << 16) | BR13_8888;
104	 CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
105      }
106
107      assert(src->tiling != I915_TILING_Y);
108      assert(dst->tiling != I915_TILING_Y);
109#ifndef I915
110      if (src->tiling != I915_TILING_NONE) {
111	 CMD |= XY_SRC_TILED;
112	 src_pitch /= 4;
113      }
114      if (dst->tiling != I915_TILING_NONE) {
115	 CMD |= XY_DST_TILED;
116	 dst_pitch /= 4;
117      }
118#endif
119      /* do space/cliprects check before going any further */
120      intel_batchbuffer_require_space(intel->batch, 8 * 4,
121				      REFERENCES_CLIPRECTS);
122   again:
123      aper_array[0] = intel->batch->buf;
124      aper_array[1] = dst->buffer;
125      aper_array[2] = src->buffer;
126
127      if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) {
128	intel_batchbuffer_flush(intel->batch);
129	goto again;
130      }
131
132      for (i = 0; i < nbox; i++, pbox++) {
133	 drm_clip_rect_t box = *pbox;
134
135	 if (rect) {
136	    if (!intel_intersect_cliprects(&box, &box, rect))
137	       continue;
138	 }
139
140	 if (box.x1 >= box.x2 ||
141	     box.y1 >= box.y2)
142	    continue;
143
144	 assert(box.x1 < box.x2);
145	 assert(box.y1 < box.y2);
146	 src_x = box.x1 - dPriv->x + dPriv->backX;
147	 src_y = box.y1 - dPriv->y + dPriv->backY;
148
149	 BEGIN_BATCH(8, REFERENCES_CLIPRECTS);
150	 OUT_BATCH(CMD);
151	 OUT_BATCH(BR13 | dst_pitch);
152	 OUT_BATCH((box.y1 << 16) | box.x1);
153	 OUT_BATCH((box.y2 << 16) | box.x2);
154
155	 OUT_RELOC(dst->buffer,
156		   I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
157		   0);
158	 OUT_BATCH((src_y << 16) | src_x);
159	 OUT_BATCH(src_pitch);
160	 OUT_RELOC(src->buffer,
161		   I915_GEM_DOMAIN_RENDER, 0,
162		   0);
163	 ADVANCE_BATCH();
164      }
165
166      /* Flush the rendering and the batch so that the results all land on the
167       * screen in a timely fashion.
168       */
169      intel_batchbuffer_emit_mi_flush(intel->batch);
170      intel_batchbuffer_flush(intel->batch);
171   }
172
173   UNLOCK_HARDWARE(intel);
174}
175
176static GLuint translate_raster_op(GLenum logicop)
177{
178   switch(logicop) {
179   case GL_CLEAR: return 0x00;
180   case GL_AND: return 0x88;
181   case GL_AND_REVERSE: return 0x44;
182   case GL_COPY: return 0xCC;
183   case GL_AND_INVERTED: return 0x22;
184   case GL_NOOP: return 0xAA;
185   case GL_XOR: return 0x66;
186   case GL_OR: return 0xEE;
187   case GL_NOR: return 0x11;
188   case GL_EQUIV: return 0x99;
189   case GL_INVERT: return 0x55;
190   case GL_OR_REVERSE: return 0xDD;
191   case GL_COPY_INVERTED: return 0x33;
192   case GL_OR_INVERTED: return 0xBB;
193   case GL_NAND: return 0x77;
194   case GL_SET: return 0xFF;
195   default: return 0;
196   }
197}
198
199
200/* Copy BitBlt
201 */
202GLboolean
203intelEmitCopyBlit(struct intel_context *intel,
204		  GLuint cpp,
205		  GLshort src_pitch,
206		  dri_bo *src_buffer,
207		  GLuint src_offset,
208		  uint32_t src_tiling,
209		  GLshort dst_pitch,
210		  dri_bo *dst_buffer,
211		  GLuint dst_offset,
212		  uint32_t dst_tiling,
213		  GLshort src_x, GLshort src_y,
214		  GLshort dst_x, GLshort dst_y,
215		  GLshort w, GLshort h,
216		  GLenum logic_op)
217{
218   GLuint CMD, BR13, pass = 0;
219   int dst_y2 = dst_y + h;
220   int dst_x2 = dst_x + w;
221   dri_bo *aper_array[3];
222   BATCH_LOCALS;
223
224   if (dst_tiling != I915_TILING_NONE) {
225      if (dst_offset & 4095)
226	 return GL_FALSE;
227      if (dst_tiling == I915_TILING_Y)
228	 return GL_FALSE;
229   }
230   if (src_tiling != I915_TILING_NONE) {
231      if (src_offset & 4095)
232	 return GL_FALSE;
233      if (src_tiling == I915_TILING_Y)
234	 return GL_FALSE;
235   }
236
237   /* do space/cliprects check before going any further */
238   do {
239       aper_array[0] = intel->batch->buf;
240       aper_array[1] = dst_buffer;
241       aper_array[2] = src_buffer;
242
243       if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) {
244           intel_batchbuffer_flush(intel->batch);
245           pass++;
246       } else
247           break;
248   } while (pass < 2);
249
250   if (pass >= 2) {
251       LOCK_HARDWARE(intel);
252       dri_bo_map(dst_buffer, GL_TRUE);
253       dri_bo_map(src_buffer, GL_FALSE);
254       _mesa_copy_rect((GLubyte *)dst_buffer->virtual + dst_offset,
255                       cpp,
256                       dst_pitch,
257                       dst_x, dst_y,
258                       w, h,
259                       (GLubyte *)src_buffer->virtual + src_offset,
260                       src_pitch,
261                       src_x, src_y);
262
263       dri_bo_unmap(src_buffer);
264       dri_bo_unmap(dst_buffer);
265       UNLOCK_HARDWARE(intel);
266
267       return GL_TRUE;
268   }
269
270   intel_batchbuffer_require_space(intel->batch, 8 * 4, NO_LOOP_CLIPRECTS);
271   DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
272       __FUNCTION__,
273       src_buffer, src_pitch, src_offset, src_x, src_y,
274       dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
275
276   src_pitch *= cpp;
277   dst_pitch *= cpp;
278
279   BR13 = translate_raster_op(logic_op) << 16;
280
281   switch (cpp) {
282   case 1:
283      CMD = XY_SRC_COPY_BLT_CMD;
284      break;
285   case 2:
286      BR13 |= BR13_565;
287      CMD = XY_SRC_COPY_BLT_CMD;
288      break;
289   case 4:
290      BR13 |= BR13_8888;
291      CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
292      break;
293   default:
294      return GL_FALSE;
295   }
296
297#ifndef I915
298   if (dst_tiling != I915_TILING_NONE) {
299      CMD |= XY_DST_TILED;
300      dst_pitch /= 4;
301   }
302   if (src_tiling != I915_TILING_NONE) {
303      CMD |= XY_SRC_TILED;
304      src_pitch /= 4;
305   }
306#endif
307
308   if (dst_y2 <= dst_y || dst_x2 <= dst_x) {
309      return GL_TRUE;
310   }
311
312   assert(dst_x < dst_x2);
313   assert(dst_y < dst_y2);
314
315   BEGIN_BATCH(8, NO_LOOP_CLIPRECTS);
316   OUT_BATCH(CMD);
317   OUT_BATCH(BR13 | (uint16_t)dst_pitch);
318   OUT_BATCH((dst_y << 16) | dst_x);
319   OUT_BATCH((dst_y2 << 16) | dst_x2);
320   OUT_RELOC(dst_buffer,
321	     I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
322	     dst_offset);
323   OUT_BATCH((src_y << 16) | src_x);
324   OUT_BATCH((uint16_t)src_pitch);
325   OUT_RELOC(src_buffer,
326	     I915_GEM_DOMAIN_RENDER, 0,
327	     src_offset);
328   ADVANCE_BATCH();
329
330   intel_batchbuffer_emit_mi_flush(intel->batch);
331
332   return GL_TRUE;
333}
334
335
336/**
337 * Use blitting to clear the renderbuffers named by 'flags'.
338 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
339 * since that might include software renderbuffers or renderbuffers
340 * which we're clearing with triangles.
341 * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
342 */
343void
344intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
345{
346   struct intel_context *intel = intel_context(ctx);
347   struct gl_framebuffer *fb = ctx->DrawBuffer;
348   GLuint clear_depth;
349   GLbitfield skipBuffers = 0;
350   unsigned int num_cliprects;
351   struct drm_clip_rect *cliprects;
352   int x_off, y_off;
353   BATCH_LOCALS;
354
355   /*
356    * Compute values for clearing the buffers.
357    */
358   clear_depth = 0;
359   if (mask & BUFFER_BIT_DEPTH) {
360      clear_depth = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
361   }
362   if (mask & BUFFER_BIT_STENCIL) {
363      clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
364   }
365
366   /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
367    * the loop below.
368    */
369   if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
370      skipBuffers = BUFFER_BIT_STENCIL;
371   }
372
373   LOCK_HARDWARE(intel);
374
375   intel_get_cliprects(intel, &cliprects, &num_cliprects, &x_off, &y_off);
376   if (num_cliprects) {
377      GLint cx, cy, cw, ch;
378      drm_clip_rect_t clear;
379      int i;
380
381      /* Get clear bounds after locking */
382      cx = fb->_Xmin;
383      cy = fb->_Ymin;
384      cw = fb->_Xmax - cx;
385      ch = fb->_Ymax - cy;
386
387      if (fb->Name == 0) {
388         /* clearing a window */
389
390         /* flip top to bottom */
391         clear.x1 = cx + x_off;
392         clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
393         clear.x2 = clear.x1 + cw;
394         clear.y2 = clear.y1 + ch;
395      }
396      else {
397         /* clearing FBO */
398         assert(num_cliprects == 1);
399         assert(cliprects == &intel->fboRect);
400         clear.x1 = cx;
401         clear.y1 = cy;
402         clear.x2 = clear.x1 + cw;
403         clear.y2 = clear.y1 + ch;
404         /* no change to mask */
405      }
406
407      for (i = 0; i < num_cliprects; i++) {
408         const drm_clip_rect_t *box = &cliprects[i];
409         drm_clip_rect_t b;
410         GLuint buf;
411         GLuint clearMask = mask;      /* use copy, since we modify it below */
412         GLboolean all = (cw == fb->Width && ch == fb->Height);
413
414         if (!all) {
415            intel_intersect_cliprects(&b, &clear, box);
416         }
417         else {
418            b = *box;
419         }
420
421         if (b.x1 >= b.x2 || b.y1 >= b.y2)
422            continue;
423
424         if (0)
425            _mesa_printf("clear %d,%d..%d,%d, mask %x\n",
426                         b.x1, b.y1, b.x2, b.y2, mask);
427
428         /* Loop over all renderbuffers */
429         for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
430            const GLbitfield bufBit = 1 << buf;
431            if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
432               /* OK, clear this renderbuffer */
433	       struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, buf);
434               dri_bo *write_buffer =
435                  intel_region_buffer(intel, irb->region,
436                                      all ? INTEL_WRITE_FULL :
437                                      INTEL_WRITE_PART);
438	       int x1 = b.x1 + irb->region->draw_x;
439	       int y1 = b.y1 + irb->region->draw_y;
440	       int x2 = b.x2 + irb->region->draw_x;
441	       int y2 = b.y2 + irb->region->draw_y;
442
443               GLuint clearVal;
444               GLint pitch, cpp;
445               GLuint BR13, CMD;
446
447               pitch = irb->region->pitch;
448               cpp = irb->region->cpp;
449
450               DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
451                   __FUNCTION__,
452                   irb->region->buffer, (pitch * cpp),
453                   x1, y1, x2 - x1, y2 - y1);
454
455	       BR13 = 0xf0 << 16;
456	       CMD = XY_COLOR_BLT_CMD;
457
458               /* Setup the blit command */
459               if (cpp == 4) {
460                  BR13 |= BR13_8888;
461                  if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
462                     if (clearMask & BUFFER_BIT_DEPTH)
463                        CMD |= XY_BLT_WRITE_RGB;
464                     if (clearMask & BUFFER_BIT_STENCIL)
465                        CMD |= XY_BLT_WRITE_ALPHA;
466                  }
467                  else {
468                     /* clearing RGBA */
469                     CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
470                  }
471               }
472               else {
473                  ASSERT(cpp == 2);
474                  BR13 |= BR13_565;
475               }
476
477	       assert(irb->region->tiling != I915_TILING_Y);
478
479#ifndef I915
480	       if (irb->region->tiling != I915_TILING_NONE) {
481		  CMD |= XY_DST_TILED;
482		  pitch /= 4;
483	       }
484#endif
485	       BR13 |= (pitch * cpp);
486
487               if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
488                  clearVal = clear_depth;
489               }
490               else {
491		  uint8_t clear[4];
492		  GLclampf *color = ctx->Color.ClearColor;
493
494		  CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
495		  CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
496		  CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
497		  CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
498
499		  switch (irb->texformat) {
500		  case MESA_FORMAT_ARGB8888:
501		     clearVal = intel->ClearColor8888;
502		     break;
503		  case MESA_FORMAT_RGB565:
504		     clearVal = intel->ClearColor565;
505		     break;
506		  case MESA_FORMAT_ARGB4444:
507		     clearVal = PACK_COLOR_4444(clear[3], clear[0],
508						clear[1], clear[2]);
509		     break;
510		  case MESA_FORMAT_ARGB1555:
511		     clearVal = PACK_COLOR_1555(clear[3], clear[0],
512						clear[1], clear[2]);
513		     break;
514		  default:
515		     _mesa_problem(ctx, "Unexpected renderbuffer format: %d\n",
516				   irb->texformat);
517		     clearVal = 0;
518		  }
519	       }
520
521               /*
522                  _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
523                  buf, irb->Base.Name);
524                */
525
526               assert(x1 < x2);
527               assert(y1 < y2);
528
529               BEGIN_BATCH(6, REFERENCES_CLIPRECTS);
530               OUT_BATCH(CMD);
531               OUT_BATCH(BR13);
532               OUT_BATCH((y1 << 16) | x1);
533               OUT_BATCH((y2 << 16) | x2);
534               OUT_RELOC(write_buffer,
535			 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
536                         0);
537               OUT_BATCH(clearVal);
538               ADVANCE_BATCH();
539               clearMask &= ~bufBit;    /* turn off bit, for faster loop exit */
540            }
541         }
542      }
543   }
544
545   UNLOCK_HARDWARE(intel);
546}
547
548GLboolean
549intelEmitImmediateColorExpandBlit(struct intel_context *intel,
550				  GLuint cpp,
551				  GLubyte *src_bits, GLuint src_size,
552				  GLuint fg_color,
553				  GLshort dst_pitch,
554				  dri_bo *dst_buffer,
555				  GLuint dst_offset,
556				  uint32_t dst_tiling,
557				  GLshort x, GLshort y,
558				  GLshort w, GLshort h,
559				  GLenum logic_op)
560{
561   int dwords = ALIGN(src_size, 8) / 4;
562   uint32_t opcode, br13, blit_cmd;
563
564   if (dst_tiling != I915_TILING_NONE) {
565      if (dst_offset & 4095)
566	 return GL_FALSE;
567      if (dst_tiling == I915_TILING_Y)
568	 return GL_FALSE;
569   }
570
571   assert( logic_op - GL_CLEAR >= 0 );
572   assert( logic_op - GL_CLEAR < 0x10 );
573   assert(dst_pitch > 0);
574
575   if (w < 0 || h < 0)
576      return GL_TRUE;
577
578   dst_pitch *= cpp;
579
580   DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n",
581       __FUNCTION__,
582       dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
583
584   intel_batchbuffer_require_space( intel->batch,
585				    (8 * 4) +
586				    (3 * 4) +
587				    dwords * 4,
588				    REFERENCES_CLIPRECTS );
589
590   opcode = XY_SETUP_BLT_CMD;
591   if (cpp == 4)
592      opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
593#ifndef I915
594   if (dst_tiling != I915_TILING_NONE) {
595      opcode |= XY_DST_TILED;
596      dst_pitch /= 4;
597   }
598#endif
599
600   br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29);
601   if (cpp == 2)
602      br13 |= BR13_565;
603   else
604      br13 |= BR13_8888;
605
606   blit_cmd = XY_TEXT_IMMEDIATE_BLIT_CMD | XY_TEXT_BYTE_PACKED; /* packing? */
607   if (dst_tiling != I915_TILING_NONE)
608      blit_cmd |= XY_DST_TILED;
609
610   BEGIN_BATCH(8 + 3, REFERENCES_CLIPRECTS);
611   OUT_BATCH(opcode);
612   OUT_BATCH(br13);
613   OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */
614   OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */
615   OUT_RELOC(dst_buffer,
616	     I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
617	     dst_offset);
618   OUT_BATCH(0); /* bg */
619   OUT_BATCH(fg_color); /* fg */
620   OUT_BATCH(0); /* pattern base addr */
621
622   OUT_BATCH(blit_cmd | ((3 - 2) + dwords));
623   OUT_BATCH((y << 16) | x);
624   OUT_BATCH(((y + h) << 16) | (x + w));
625   ADVANCE_BATCH();
626
627   intel_batchbuffer_data( intel->batch,
628			   src_bits,
629			   dwords * 4,
630			   REFERENCES_CLIPRECTS );
631
632   intel_batchbuffer_emit_mi_flush(intel->batch);
633
634   return GL_TRUE;
635}
636
637/* We don't have a memmove-type blit like some other hardware, so we'll do a
638 * rectangular blit covering a large space, then emit 1-scanline blit at the
639 * end to cover the last if we need.
640 */
641void
642intel_emit_linear_blit(struct intel_context *intel,
643		       drm_intel_bo *dst_bo,
644		       unsigned int dst_offset,
645		       drm_intel_bo *src_bo,
646		       unsigned int src_offset,
647		       unsigned int size)
648{
649   GLuint pitch, height;
650
651   /* The pitch is a signed value. */
652   pitch = MIN2(size, (1 << 15) - 1);
653   height = size / pitch;
654   intelEmitCopyBlit(intel, 1,
655		     pitch, src_bo, src_offset, I915_TILING_NONE,
656		     pitch, dst_bo, dst_offset, I915_TILING_NONE,
657		     0, 0, /* src x/y */
658		     0, 0, /* dst x/y */
659		     pitch, height, /* w, h */
660		     GL_COPY);
661
662   src_offset += pitch * height;
663   dst_offset += pitch * height;
664   size -= pitch * height;
665   assert (size < (1 << 15));
666   if (size != 0) {
667      intelEmitCopyBlit(intel, 1,
668			size, src_bo, src_offset, I915_TILING_NONE,
669			size, dst_bo, dst_offset, I915_TILING_NONE,
670			0, 0, /* src x/y */
671			0, 0, /* dst x/y */
672			size, 1, /* w, h */
673			GL_COPY);
674   }
675}
676