intel_blit.c revision 601a6b872c33bfe3cb4ea03a5a8ba5ebe92dedaf
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 <stdio.h> 30#include <errno.h> 31 32#include "mtypes.h" 33#include "context.h" 34#include "enums.h" 35 36#include "intel_batchbuffer.h" 37#include "intel_blit.h" 38#include "intel_buffers.h" 39#include "intel_context.h" 40#include "intel_fbo.h" 41#include "intel_reg.h" 42#include "intel_regions.h" 43 44#define FILE_DEBUG_FLAG DEBUG_BLIT 45 46/** 47 * Copy the back color buffer to the front color buffer. 48 * Used for SwapBuffers(). 49 */ 50void 51intelCopyBuffer(const __DRIdrawablePrivate * dPriv, 52 const drm_clip_rect_t * rect) 53{ 54 55 struct intel_context *intel; 56 const intelScreenPrivate *intelScreen; 57 58 DBG("%s\n", __FUNCTION__); 59 60 assert(dPriv); 61 62 intel = intelScreenContext(dPriv->driScreenPriv->private); 63 if (!intel) 64 return; 65 66 intelScreen = intel->intelScreen; 67 68 if (intel->last_swap_fence) { 69 dri_fence_wait(intel->last_swap_fence); 70 dri_fence_unreference(intel->last_swap_fence); 71 intel->last_swap_fence = NULL; 72 } 73 intel->last_swap_fence = intel->first_swap_fence; 74 intel->first_swap_fence = NULL; 75 76 /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets 77 * should work regardless. 78 */ 79 LOCK_HARDWARE(intel); 80 81 if (dPriv && dPriv->numClipRects) { 82 struct intel_framebuffer *intel_fb = dPriv->driverPrivate; 83 struct intel_region *src, *dst; 84 int nbox = dPriv->numClipRects; 85 drm_clip_rect_t *pbox = dPriv->pClipRects; 86 int cpp; 87 int src_pitch, dst_pitch; 88 int BR13, CMD; 89 int i; 90 91 src = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); 92 dst = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); 93 94 src_pitch = src->pitch * src->cpp; 95 dst_pitch = dst->pitch * dst->cpp; 96 97 cpp = src->cpp; 98 99 ASSERT(intel_fb); 100 ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ 101 ASSERT(src); 102 ASSERT(dst); 103 ASSERT(src->pitch == dst->pitch); 104 ASSERT(src->cpp == dst->cpp); 105 106 if (cpp == 2) { 107 BR13 = (0xCC << 16) | (1 << 24); 108 CMD = XY_SRC_COPY_BLT_CMD; 109 } 110 else { 111 BR13 = (0xCC << 16) | (1 << 24) | (1 << 25); 112 CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; 113 } 114 115#ifndef I915 116 if (src->tiled) { 117 CMD |= XY_SRC_TILED; 118 src_pitch /= 4; 119 } 120 if (dst->tiled) { 121 CMD |= XY_DST_TILED; 122 dst_pitch /= 4; 123 } 124#endif 125 126 for (i = 0; i < nbox; i++, pbox++) { 127 drm_clip_rect_t box = *pbox; 128 129 if (rect) { 130 if (!intel_intersect_cliprects(&box, &box, rect)) 131 continue; 132 } 133 134 if (box.x1 >= box.x2 || 135 box.y1 >= box.y2 || 136 box.x2 > intelScreen->width || 137 box.y2 > intelScreen->height) 138 continue; 139 140 assert(box.x1 < box.x2); 141 assert(box.y1 < box.y2); 142 143 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); 144 OUT_BATCH(CMD); 145 OUT_BATCH(BR13 | dst_pitch); 146 OUT_BATCH((box.y1 << 16) | box.x1); 147 OUT_BATCH((box.y2 << 16) | box.x2); 148 149 OUT_RELOC(dst->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, 0); 150 OUT_BATCH((box.y1 << 16) | box.x1); 151 OUT_BATCH(src_pitch); 152 OUT_RELOC(src->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, 0); 153 ADVANCE_BATCH(); 154 } 155 156 if (intel->first_swap_fence) 157 dri_fence_unreference(intel->first_swap_fence); 158 intel_batchbuffer_flush(intel->batch); 159 intel->first_swap_fence = intel->batch->last_fence; 160 if (intel->first_swap_fence) 161 dri_fence_reference(intel->first_swap_fence); 162 } 163 164 UNLOCK_HARDWARE(intel); 165} 166 167 168 169 170void 171intelEmitFillBlit(struct intel_context *intel, 172 GLuint cpp, 173 GLshort dst_pitch, 174 dri_bo *dst_buffer, 175 GLuint dst_offset, 176 GLboolean dst_tiled, 177 GLshort x, GLshort y, 178 GLshort w, GLshort h, 179 GLuint color) 180{ 181 GLuint BR13, CMD; 182 BATCH_LOCALS; 183 184 dst_pitch *= cpp; 185 186 switch (cpp) { 187 case 1: 188 case 2: 189 case 3: 190 BR13 = (0xF0 << 16) | (1 << 24); 191 CMD = XY_COLOR_BLT_CMD; 192 break; 193 case 4: 194 BR13 = (0xF0 << 16) | (1 << 24) | (1 << 25); 195 CMD = XY_COLOR_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; 196 break; 197 default: 198 return; 199 } 200#ifndef I915 201 if (dst_tiled) { 202 CMD |= XY_DST_TILED; 203 dst_pitch /= 4; 204 } 205#endif 206 207 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", 208 __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h); 209 210 assert(w > 0); 211 assert(h > 0); 212 213 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); 214 OUT_BATCH(CMD); 215 OUT_BATCH(BR13 | dst_pitch); 216 OUT_BATCH((y << 16) | x); 217 OUT_BATCH(((y + h) << 16) | (x + w)); 218 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset); 219 OUT_BATCH(color); 220 ADVANCE_BATCH(); 221} 222 223static GLuint translate_raster_op(GLenum logicop) 224{ 225 switch(logicop) { 226 case GL_CLEAR: return 0x00; 227 case GL_AND: return 0x88; 228 case GL_AND_REVERSE: return 0x44; 229 case GL_COPY: return 0xCC; 230 case GL_AND_INVERTED: return 0x22; 231 case GL_NOOP: return 0xAA; 232 case GL_XOR: return 0x66; 233 case GL_OR: return 0xEE; 234 case GL_NOR: return 0x11; 235 case GL_EQUIV: return 0x99; 236 case GL_INVERT: return 0x55; 237 case GL_OR_REVERSE: return 0xDD; 238 case GL_COPY_INVERTED: return 0x33; 239 case GL_OR_INVERTED: return 0xBB; 240 case GL_NAND: return 0x77; 241 case GL_SET: return 0xFF; 242 default: return 0; 243 } 244} 245 246 247/* Copy BitBlt 248 */ 249void 250intelEmitCopyBlit(struct intel_context *intel, 251 GLuint cpp, 252 GLshort src_pitch, 253 dri_bo *src_buffer, 254 GLuint src_offset, 255 GLboolean src_tiled, 256 GLshort dst_pitch, 257 dri_bo *dst_buffer, 258 GLuint dst_offset, 259 GLboolean dst_tiled, 260 GLshort src_x, GLshort src_y, 261 GLshort dst_x, GLshort dst_y, 262 GLshort w, GLshort h, 263 GLenum logic_op) 264{ 265 GLuint CMD, BR13; 266 int dst_y2 = dst_y + h; 267 int dst_x2 = dst_x + w; 268 BATCH_LOCALS; 269 270 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 case 2: 284 case 3: 285 BR13 |= (1 << 24); 286 CMD = XY_SRC_COPY_BLT_CMD; 287 break; 288 case 4: 289 BR13 |= (1 << 24) | (1 << 25); 290 CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; 291 break; 292 default: 293 return; 294 } 295 296#ifndef I915 297 if (dst_tiled) { 298 CMD |= XY_DST_TILED; 299 dst_pitch /= 4; 300 } 301 if (src_tiled) { 302 CMD |= XY_SRC_TILED; 303 src_pitch /= 4; 304 } 305#endif 306 307 if (dst_y2 <= dst_y || dst_x2 <= dst_x) { 308 return; 309 } 310 311 dst_pitch &= 0xffff; 312 src_pitch &= 0xffff; 313 314 /* Initial y values don't seem to work with negative pitches. If 315 * we adjust the offsets manually (below), it seems to work fine. 316 * 317 * On the other hand, if we always adjust, the hardware doesn't 318 * know which blit directions to use, so overlapping copypixels get 319 * the wrong result. 320 */ 321 if (dst_pitch > 0 && src_pitch > 0) { 322 assert(dst_x < dst_x2); 323 assert(dst_y < dst_y2); 324 325 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); 326 OUT_BATCH(CMD); 327 OUT_BATCH(BR13 | dst_pitch); 328 OUT_BATCH((dst_y << 16) | dst_x); 329 OUT_BATCH((dst_y2 << 16) | dst_x2); 330 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, 331 dst_offset); 332 OUT_BATCH((src_y << 16) | src_x); 333 OUT_BATCH(src_pitch); 334 OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, 335 src_offset); 336 ADVANCE_BATCH(); 337 } 338 else { 339 assert(dst_x < dst_x2); 340 assert(h > 0); 341 342 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); 343 OUT_BATCH(CMD); 344 OUT_BATCH(BR13 | dst_pitch); 345 OUT_BATCH((0 << 16) | dst_x); 346 OUT_BATCH((h << 16) | dst_x2); 347 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, 348 dst_offset + dst_y * dst_pitch); 349 OUT_BATCH((0 << 16) | src_x); 350 OUT_BATCH(src_pitch); 351 OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, 352 src_offset + src_y * src_pitch); 353 ADVANCE_BATCH(); 354 } 355} 356 357 358/** 359 * Use blitting to clear the renderbuffers named by 'flags'. 360 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field 361 * since that might include software renderbuffers or renderbuffers 362 * which we're clearing with triangles. 363 * \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear 364 */ 365void 366intelClearWithBlit(GLcontext *ctx, GLbitfield mask) 367{ 368 struct intel_context *intel = intel_context(ctx); 369 struct gl_framebuffer *fb = ctx->DrawBuffer; 370 GLuint clear_depth; 371 GLbitfield skipBuffers = 0; 372 BATCH_LOCALS; 373 374 /* 375 * Compute values for clearing the buffers. 376 */ 377 clear_depth = 0; 378 if (mask & BUFFER_BIT_DEPTH) { 379 clear_depth = (GLuint) (fb->_DepthMax * ctx->Depth.Clear); 380 } 381 if (mask & BUFFER_BIT_STENCIL) { 382 clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; 383 } 384 385 /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in 386 * the loop below. 387 */ 388 if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) { 389 skipBuffers = BUFFER_BIT_STENCIL; 390 } 391 392 /* XXX Move this flush/lock into the following conditional? */ 393 intelFlush(&intel->ctx); 394 LOCK_HARDWARE(intel); 395 396 if (intel->numClipRects) { 397 GLint cx, cy, cw, ch; 398 drm_clip_rect_t clear; 399 int i; 400 401 /* Get clear bounds after locking */ 402 cx = fb->_Xmin; 403 cy = fb->_Ymin; 404 cw = fb->_Xmax - cx; 405 ch = fb->_Ymax - cy; 406 407 if (fb->Name == 0) { 408 /* clearing a window */ 409 410 /* flip top to bottom */ 411 clear.x1 = cx + intel->drawX; 412 clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch; 413 clear.x2 = clear.x1 + cw; 414 clear.y2 = clear.y1 + ch; 415 } 416 else { 417 /* clearing FBO */ 418 assert(intel->numClipRects == 1); 419 assert(intel->pClipRects == &intel->fboRect); 420 clear.x1 = cx; 421 clear.y1 = cy; 422 clear.x2 = clear.x1 + cw; 423 clear.y2 = clear.y1 + ch; 424 /* no change to mask */ 425 } 426 427 for (i = 0; i < intel->numClipRects; i++) { 428 const drm_clip_rect_t *box = &intel->pClipRects[i]; 429 drm_clip_rect_t b; 430 GLuint buf; 431 GLuint clearMask = mask; /* use copy, since we modify it below */ 432 GLboolean all = (cw == fb->Width && ch == fb->Height); 433 434 if (!all) { 435 intel_intersect_cliprects(&b, &clear, box); 436 } 437 else { 438 b = *box; 439 } 440 441 if (b.x1 >= b.x2 || b.y1 >= b.y2) 442 continue; 443 444 if (0) 445 _mesa_printf("clear %d,%d..%d,%d, mask %x\n", 446 b.x1, b.y1, b.x2, b.y2, mask); 447 448 /* Loop over all renderbuffers */ 449 for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) { 450 const GLbitfield bufBit = 1 << buf; 451 if ((clearMask & bufBit) && !(bufBit & skipBuffers)) { 452 /* OK, clear this renderbuffer */ 453 struct intel_region *irb_region = 454 intel_get_rb_region(fb, buf); 455 dri_bo *write_buffer = 456 intel_region_buffer(intel, irb_region, 457 all ? INTEL_WRITE_FULL : 458 INTEL_WRITE_PART); 459 460 GLuint clearVal; 461 GLint pitch, cpp; 462 GLuint BR13, CMD; 463 464 ASSERT(irb_region); 465 466 pitch = irb_region->pitch; 467 cpp = irb_region->cpp; 468 469 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", 470 __FUNCTION__, 471 irb_region->buffer, (pitch * cpp), 472 irb_region->draw_offset, 473 b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1); 474 475 BR13 = 0xf0 << 16; 476 CMD = XY_COLOR_BLT_CMD; 477 478 /* Setup the blit command */ 479 if (cpp == 4) { 480 BR13 |= (1 << 24) | (1 << 25); 481 if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) { 482 if (clearMask & BUFFER_BIT_DEPTH) 483 CMD |= XY_BLT_WRITE_RGB; 484 if (clearMask & BUFFER_BIT_STENCIL) 485 CMD |= XY_BLT_WRITE_ALPHA; 486 } 487 else { 488 /* clearing RGBA */ 489 CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; 490 } 491 } 492 else { 493 ASSERT(cpp == 2 || cpp == 0); 494 BR13 |= (1 << 24); 495 } 496 497#ifndef I915 498 if (irb_region->tiled) { 499 CMD |= XY_DST_TILED; 500 pitch /= 4; 501 } 502#endif 503 BR13 |= (pitch * cpp); 504 505 if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) { 506 clearVal = clear_depth; 507 } 508 else { 509 clearVal = (cpp == 4) 510 ? intel->ClearColor8888 : intel->ClearColor565; 511 } 512 /* 513 _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n", 514 buf, irb->Base.Name); 515 */ 516 intel_wait_flips(intel, INTEL_BATCH_NO_CLIPRECTS); 517 518 assert(b.x1 < b.x2); 519 assert(b.y1 < b.y2); 520 521 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); 522 OUT_BATCH(CMD); 523 OUT_BATCH(BR13); 524 OUT_BATCH((b.y1 << 16) | b.x1); 525 OUT_BATCH((b.y2 << 16) | b.x2); 526 OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, 527 irb_region->draw_offset); 528 OUT_BATCH(clearVal); 529 ADVANCE_BATCH(); 530 clearMask &= ~bufBit; /* turn off bit, for faster loop exit */ 531 } 532 } 533 } 534 intel_batchbuffer_flush(intel->batch); 535 } 536 537 UNLOCK_HARDWARE(intel); 538} 539 540void 541intelEmitImmediateColorExpandBlit(struct intel_context *intel, 542 GLuint cpp, 543 GLubyte *src_bits, GLuint src_size, 544 GLuint fg_color, 545 GLshort dst_pitch, 546 dri_bo *dst_buffer, 547 GLuint dst_offset, 548 GLboolean dst_tiled, 549 GLshort x, GLshort y, 550 GLshort w, GLshort h, 551 GLenum logic_op) 552{ 553 int dwords = ALIGN(src_size, 8) / 4; 554 uint32_t opcode, br13, blit_cmd; 555 556 assert( logic_op - GL_CLEAR >= 0 ); 557 assert( logic_op - GL_CLEAR < 0x10 ); 558 559 if (w < 0 || h < 0) 560 return; 561 562 dst_pitch *= cpp; 563 564 if (dst_tiled) 565 dst_pitch /= 4; 566 567 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n", 568 __FUNCTION__, 569 dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords); 570 571 intel_batchbuffer_require_space( intel->batch, 572 (8 * 4) + 573 (3 * 4) + 574 dwords, 575 INTEL_BATCH_NO_CLIPRECTS ); 576 577 opcode = XY_SETUP_BLT_CMD; 578 if (cpp == 4) 579 opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; 580 if (dst_tiled) 581 opcode |= XY_DST_TILED; 582 583 br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29); 584 if (cpp == 2) 585 br13 |= BR13_565; 586 else 587 br13 |= BR13_8888; 588 589 blit_cmd = XY_TEXT_IMMEDIATE_BLIT_CMD | XY_TEXT_BYTE_PACKED; /* packing? */ 590 if (dst_tiled) 591 blit_cmd |= XY_DST_TILED; 592 593 BEGIN_BATCH(8 + 3, INTEL_BATCH_NO_CLIPRECTS); 594 OUT_BATCH(opcode); 595 OUT_BATCH(br13); 596 OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */ 597 OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */ 598 OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, dst_offset); 599 OUT_BATCH(0); /* bg */ 600 OUT_BATCH(fg_color); /* fg */ 601 OUT_BATCH(0); /* pattern base addr */ 602 603 OUT_BATCH(blit_cmd | ((3 - 2) + dwords)); 604 OUT_BATCH((y << 16) | x); 605 OUT_BATCH(((y + h) << 16) | (x + w)); 606 ADVANCE_BATCH(); 607 608 intel_batchbuffer_data( intel->batch, 609 src_bits, 610 dwords * 4, 611 INTEL_BATCH_NO_CLIPRECTS ); 612} 613