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