intel_blit.c revision 5203b7227ccb6b618fa42f08434d4a3cf123dca2
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 45static 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 */ 71GLboolean 72intelEmitCopyBlit(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 */ 210void 211intelClearWithBlit(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 413GLboolean 414intelEmitImmediateColorExpandBlit(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 */ 504void 505intel_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} 539