Merge remote branch 'origin/mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / intel / intel_blit.c
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 static GLuint translate_raster_op(GLenum logicop)
46 {
47 switch(logicop) {
48 case GL_CLEAR: return 0x00;
49 case GL_AND: return 0x88;
50 case GL_AND_REVERSE: return 0x44;
51 case GL_COPY: return 0xCC;
52 case GL_AND_INVERTED: return 0x22;
53 case GL_NOOP: return 0xAA;
54 case GL_XOR: return 0x66;
55 case GL_OR: return 0xEE;
56 case GL_NOR: return 0x11;
57 case GL_EQUIV: return 0x99;
58 case GL_INVERT: return 0x55;
59 case GL_OR_REVERSE: return 0xDD;
60 case GL_COPY_INVERTED: return 0x33;
61 case GL_OR_INVERTED: return 0xBB;
62 case GL_NAND: return 0x77;
63 case GL_SET: return 0xFF;
64 default: return 0;
65 }
66 }
67
68
69 /* Copy BitBlt
70 */
71 GLboolean
72 intelEmitCopyBlit(struct intel_context *intel,
73 GLuint cpp,
74 GLshort src_pitch,
75 dri_bo *src_buffer,
76 GLuint src_offset,
77 uint32_t src_tiling,
78 GLshort dst_pitch,
79 dri_bo *dst_buffer,
80 GLuint dst_offset,
81 uint32_t dst_tiling,
82 GLshort src_x, GLshort src_y,
83 GLshort dst_x, GLshort dst_y,
84 GLshort w, GLshort h,
85 GLenum logic_op)
86 {
87 GLuint CMD, BR13, pass = 0;
88 int dst_y2 = dst_y + h;
89 int dst_x2 = dst_x + w;
90 dri_bo *aper_array[3];
91 BATCH_LOCALS;
92
93 if (dst_tiling != I915_TILING_NONE) {
94 if (dst_offset & 4095)
95 return GL_FALSE;
96 if (dst_tiling == I915_TILING_Y)
97 return GL_FALSE;
98 }
99 if (src_tiling != I915_TILING_NONE) {
100 if (src_offset & 4095)
101 return GL_FALSE;
102 if (src_tiling == I915_TILING_Y)
103 return GL_FALSE;
104 }
105
106 /* do space/cliprects check before going any further */
107 do {
108 aper_array[0] = intel->batch->buf;
109 aper_array[1] = dst_buffer;
110 aper_array[2] = src_buffer;
111
112 if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) {
113 intel_batchbuffer_flush(intel->batch);
114 pass++;
115 } else
116 break;
117 } while (pass < 2);
118
119 if (pass >= 2) {
120 dri_bo_map(dst_buffer, GL_TRUE);
121 dri_bo_map(src_buffer, GL_FALSE);
122 _mesa_copy_rect((GLubyte *)dst_buffer->virtual + dst_offset,
123 cpp,
124 dst_pitch,
125 dst_x, dst_y,
126 w, h,
127 (GLubyte *)src_buffer->virtual + src_offset,
128 src_pitch,
129 src_x, src_y);
130
131 dri_bo_unmap(src_buffer);
132 dri_bo_unmap(dst_buffer);
133
134 return GL_TRUE;
135 }
136
137 intel_batchbuffer_require_space(intel->batch, 8 * 4);
138 DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
139 __FUNCTION__,
140 src_buffer, src_pitch, src_offset, src_x, src_y,
141 dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
142
143 src_pitch *= cpp;
144 dst_pitch *= cpp;
145
146 BR13 = translate_raster_op(logic_op) << 16;
147
148 switch (cpp) {
149 case 1:
150 CMD = XY_SRC_COPY_BLT_CMD;
151 break;
152 case 2:
153 BR13 |= BR13_565;
154 CMD = XY_SRC_COPY_BLT_CMD;
155 break;
156 case 4:
157 BR13 |= BR13_8888;
158 CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
159 break;
160 default:
161 return GL_FALSE;
162 }
163
164 #ifndef I915
165 if (dst_tiling != I915_TILING_NONE) {
166 CMD |= XY_DST_TILED;
167 dst_pitch /= 4;
168 }
169 if (src_tiling != I915_TILING_NONE) {
170 CMD |= XY_SRC_TILED;
171 src_pitch /= 4;
172 }
173 #endif
174
175 if (dst_y2 <= dst_y || dst_x2 <= dst_x) {
176 return GL_TRUE;
177 }
178
179 assert(dst_x < dst_x2);
180 assert(dst_y < dst_y2);
181
182 BEGIN_BATCH(8);
183 OUT_BATCH(CMD);
184 OUT_BATCH(BR13 | (uint16_t)dst_pitch);
185 OUT_BATCH((dst_y << 16) | dst_x);
186 OUT_BATCH((dst_y2 << 16) | dst_x2);
187 OUT_RELOC(dst_buffer,
188 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
189 dst_offset);
190 OUT_BATCH((src_y << 16) | src_x);
191 OUT_BATCH((uint16_t)src_pitch);
192 OUT_RELOC(src_buffer,
193 I915_GEM_DOMAIN_RENDER, 0,
194 src_offset);
195 ADVANCE_BATCH();
196
197 intel_batchbuffer_emit_mi_flush(intel->batch);
198
199 return GL_TRUE;
200 }
201
202
203 /**
204 * Use blitting to clear the renderbuffers named by 'flags'.
205 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
206 * since that might include software renderbuffers or renderbuffers
207 * which we're clearing with triangles.
208 * \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear
209 */
210 void
211 intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
212 {
213 struct intel_context *intel = intel_context(ctx);
214 struct gl_framebuffer *fb = ctx->DrawBuffer;
215 GLuint clear_depth;
216 GLbitfield skipBuffers = 0;
217 unsigned int num_cliprects;
218 struct drm_clip_rect *cliprects;
219 int x_off, y_off;
220 BATCH_LOCALS;
221
222 /*
223 * Compute values for clearing the buffers.
224 */
225 clear_depth = 0;
226 if (mask & BUFFER_BIT_DEPTH) {
227 clear_depth = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
228 }
229 if (mask & BUFFER_BIT_STENCIL) {
230 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
231 }
232
233 /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
234 * the loop below.
235 */
236 if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
237 skipBuffers = BUFFER_BIT_STENCIL;
238 }
239
240 intel_get_cliprects(intel, &cliprects, &num_cliprects, &x_off, &y_off);
241 if (num_cliprects) {
242 GLint cx, cy, cw, ch;
243 drm_clip_rect_t clear;
244 int i;
245
246 /* Get clear bounds after locking */
247 cx = fb->_Xmin;
248 cy = fb->_Ymin;
249 cw = fb->_Xmax - cx;
250 ch = fb->_Ymax - cy;
251
252 if (fb->Name == 0) {
253 /* clearing a window */
254
255 /* flip top to bottom */
256 clear.x1 = cx + x_off;
257 clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
258 clear.x2 = clear.x1 + cw;
259 clear.y2 = clear.y1 + ch;
260 }
261 else {
262 /* clearing FBO */
263 assert(num_cliprects == 1);
264 assert(cliprects == &intel->fboRect);
265 clear.x1 = cx;
266 clear.y1 = cy;
267 clear.x2 = clear.x1 + cw;
268 clear.y2 = clear.y1 + ch;
269 /* no change to mask */
270 }
271
272 for (i = 0; i < num_cliprects; i++) {
273 const drm_clip_rect_t *box = &cliprects[i];
274 drm_clip_rect_t b;
275 GLuint buf;
276 GLuint clearMask = mask; /* use copy, since we modify it below */
277 GLboolean all = (cw == fb->Width && ch == fb->Height);
278
279 if (!all) {
280 intel_intersect_cliprects(&b, &clear, box);
281 }
282 else {
283 b = *box;
284 }
285
286 if (b.x1 >= b.x2 || b.y1 >= b.y2)
287 continue;
288
289 if (0)
290 _mesa_printf("clear %d,%d..%d,%d, mask %x\n",
291 b.x1, b.y1, b.x2, b.y2, mask);
292
293 /* Loop over all renderbuffers */
294 for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
295 const GLbitfield bufBit = 1 << buf;
296 if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
297 /* OK, clear this renderbuffer */
298 struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, buf);
299 dri_bo *write_buffer =
300 intel_region_buffer(intel, irb->region,
301 all ? INTEL_WRITE_FULL :
302 INTEL_WRITE_PART);
303 int x1 = b.x1 + irb->region->draw_x;
304 int y1 = b.y1 + irb->region->draw_y;
305 int x2 = b.x2 + irb->region->draw_x;
306 int y2 = b.y2 + irb->region->draw_y;
307
308 GLuint clearVal;
309 GLint pitch, cpp;
310 GLuint BR13, CMD;
311
312 pitch = irb->region->pitch;
313 cpp = irb->region->cpp;
314
315 DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
316 __FUNCTION__,
317 irb->region->buffer, (pitch * cpp),
318 x1, y1, x2 - x1, y2 - y1);
319
320 BR13 = 0xf0 << 16;
321 CMD = XY_COLOR_BLT_CMD;
322
323 /* Setup the blit command */
324 if (cpp == 4) {
325 BR13 |= BR13_8888;
326 if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
327 if (clearMask & BUFFER_BIT_DEPTH)
328 CMD |= XY_BLT_WRITE_RGB;
329 if (clearMask & BUFFER_BIT_STENCIL)
330 CMD |= XY_BLT_WRITE_ALPHA;
331 }
332 else {
333 /* clearing RGBA */
334 CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
335 }
336 }
337 else {
338 ASSERT(cpp == 2);
339 BR13 |= BR13_565;
340 }
341
342 assert(irb->region->tiling != I915_TILING_Y);
343
344 #ifndef I915
345 if (irb->region->tiling != I915_TILING_NONE) {
346 CMD |= XY_DST_TILED;
347 pitch /= 4;
348 }
349 #endif
350 BR13 |= (pitch * cpp);
351
352 if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
353 clearVal = clear_depth;
354 }
355 else {
356 uint8_t clear[4];
357 GLclampf *color = ctx->Color.ClearColor;
358
359 CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
360 CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
361 CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
362 CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
363
364 switch (irb->Base.Format) {
365 case MESA_FORMAT_ARGB8888:
366 case MESA_FORMAT_XRGB8888:
367 clearVal = PACK_COLOR_8888(clear[3], clear[0],
368 clear[1], clear[2]);
369 break;
370 case MESA_FORMAT_RGB565:
371 clearVal = PACK_COLOR_565(clear[0], clear[1], clear[2]);
372 break;
373 case MESA_FORMAT_ARGB4444:
374 clearVal = PACK_COLOR_4444(clear[3], clear[0],
375 clear[1], clear[2]);
376 break;
377 case MESA_FORMAT_ARGB1555:
378 clearVal = PACK_COLOR_1555(clear[3], clear[0],
379 clear[1], clear[2]);
380 break;
381 default:
382 _mesa_problem(ctx, "Unexpected renderbuffer format: %d\n",
383 irb->Base.Format);
384 clearVal = 0;
385 }
386 }
387
388 /*
389 _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
390 buf, irb->Base.Name);
391 */
392
393 assert(x1 < x2);
394 assert(y1 < y2);
395
396 BEGIN_BATCH(6);
397 OUT_BATCH(CMD);
398 OUT_BATCH(BR13);
399 OUT_BATCH((y1 << 16) | x1);
400 OUT_BATCH((y2 << 16) | x2);
401 OUT_RELOC(write_buffer,
402 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
403 0);
404 OUT_BATCH(clearVal);
405 ADVANCE_BATCH();
406 clearMask &= ~bufBit; /* turn off bit, for faster loop exit */
407 }
408 }
409 }
410 }
411 }
412
413 GLboolean
414 intelEmitImmediateColorExpandBlit(struct intel_context *intel,
415 GLuint cpp,
416 GLubyte *src_bits, GLuint src_size,
417 GLuint fg_color,
418 GLshort dst_pitch,
419 dri_bo *dst_buffer,
420 GLuint dst_offset,
421 uint32_t dst_tiling,
422 GLshort x, GLshort y,
423 GLshort w, GLshort h,
424 GLenum logic_op)
425 {
426 int dwords = ALIGN(src_size, 8) / 4;
427 uint32_t opcode, br13, blit_cmd;
428
429 if (dst_tiling != I915_TILING_NONE) {
430 if (dst_offset & 4095)
431 return GL_FALSE;
432 if (dst_tiling == I915_TILING_Y)
433 return GL_FALSE;
434 }
435
436 assert( logic_op - GL_CLEAR >= 0 );
437 assert( logic_op - GL_CLEAR < 0x10 );
438 assert(dst_pitch > 0);
439
440 if (w < 0 || h < 0)
441 return GL_TRUE;
442
443 dst_pitch *= cpp;
444
445 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n",
446 __FUNCTION__,
447 dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
448
449 intel_batchbuffer_require_space( intel->batch,
450 (8 * 4) +
451 (3 * 4) +
452 dwords * 4 );
453
454 opcode = XY_SETUP_BLT_CMD;
455 if (cpp == 4)
456 opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
457 #ifndef I915
458 if (dst_tiling != I915_TILING_NONE) {
459 opcode |= XY_DST_TILED;
460 dst_pitch /= 4;
461 }
462 #endif
463
464 br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29);
465 if (cpp == 2)
466 br13 |= BR13_565;
467 else
468 br13 |= BR13_8888;
469
470 blit_cmd = XY_TEXT_IMMEDIATE_BLIT_CMD | XY_TEXT_BYTE_PACKED; /* packing? */
471 if (dst_tiling != I915_TILING_NONE)
472 blit_cmd |= XY_DST_TILED;
473
474 BEGIN_BATCH(8 + 3);
475 OUT_BATCH(opcode);
476 OUT_BATCH(br13);
477 OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */
478 OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */
479 OUT_RELOC(dst_buffer,
480 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
481 dst_offset);
482 OUT_BATCH(0); /* bg */
483 OUT_BATCH(fg_color); /* fg */
484 OUT_BATCH(0); /* pattern base addr */
485
486 OUT_BATCH(blit_cmd | ((3 - 2) + dwords));
487 OUT_BATCH((y << 16) | x);
488 OUT_BATCH(((y + h) << 16) | (x + w));
489 ADVANCE_BATCH();
490
491 intel_batchbuffer_data( intel->batch,
492 src_bits,
493 dwords * 4 );
494
495 intel_batchbuffer_emit_mi_flush(intel->batch);
496
497 return GL_TRUE;
498 }
499
500 /* We don't have a memmove-type blit like some other hardware, so we'll do a
501 * rectangular blit covering a large space, then emit 1-scanline blit at the
502 * end to cover the last if we need.
503 */
504 void
505 intel_emit_linear_blit(struct intel_context *intel,
506 drm_intel_bo *dst_bo,
507 unsigned int dst_offset,
508 drm_intel_bo *src_bo,
509 unsigned int src_offset,
510 unsigned int size)
511 {
512 GLuint pitch, height;
513
514 /* The pitch is a signed value. */
515 pitch = MIN2(size, (1 << 15) - 1);
516 height = size / pitch;
517 intelEmitCopyBlit(intel, 1,
518 pitch, src_bo, src_offset, I915_TILING_NONE,
519 pitch, dst_bo, dst_offset, I915_TILING_NONE,
520 0, 0, /* src x/y */
521 0, 0, /* dst x/y */
522 pitch, height, /* w, h */
523 GL_COPY);
524
525 src_offset += pitch * height;
526 dst_offset += pitch * height;
527 size -= pitch * height;
528 assert (size < (1 << 15));
529 if (size != 0) {
530 intelEmitCopyBlit(intel, 1,
531 size, src_bo, src_offset, I915_TILING_NONE,
532 size, dst_bo, dst_offset, I915_TILING_NONE,
533 0, 0, /* src x/y */
534 0, 0, /* dst x/y */
535 size, 1, /* w, h */
536 GL_COPY);
537 }
538 }