st_cb_drawpixels.c revision b69dad1683f092e3ce9d0f3f8fb1bdf96bdff0c7
1/************************************************************************** 2 * 3 * Copyright 2007 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 * Authors: 30 * Brian Paul 31 */ 32 33#include "main/imports.h" 34#include "main/image.h" 35#include "main/bufferobj.h" 36#include "main/format_pack.h" 37#include "main/macros.h" 38#include "main/mfeatures.h" 39#include "main/mtypes.h" 40#include "main/pack.h" 41#include "main/pbo.h" 42#include "main/readpix.h" 43#include "main/texformat.h" 44#include "main/teximage.h" 45#include "main/texstore.h" 46#include "program/program.h" 47#include "program/prog_print.h" 48#include "program/prog_instruction.h" 49 50#include "st_atom.h" 51#include "st_atom_constbuf.h" 52#include "st_cb_drawpixels.h" 53#include "st_cb_readpixels.h" 54#include "st_cb_fbo.h" 55#include "st_context.h" 56#include "st_debug.h" 57#include "st_format.h" 58#include "st_program.h" 59#include "st_texture.h" 60 61#include "pipe/p_context.h" 62#include "pipe/p_defines.h" 63#include "tgsi/tgsi_ureg.h" 64#include "util/u_draw_quad.h" 65#include "util/u_format.h" 66#include "util/u_inlines.h" 67#include "util/u_math.h" 68#include "util/u_tile.h" 69#include "util/u_upload_mgr.h" 70#include "cso_cache/cso_context.h" 71 72 73#if FEATURE_drawpix 74 75/** 76 * Check if the given program is: 77 * 0: MOVE result.color, fragment.color; 78 * 1: END; 79 */ 80static GLboolean 81is_passthrough_program(const struct gl_fragment_program *prog) 82{ 83 if (prog->Base.NumInstructions == 2) { 84 const struct prog_instruction *inst = prog->Base.Instructions; 85 if (inst[0].Opcode == OPCODE_MOV && 86 inst[1].Opcode == OPCODE_END && 87 inst[0].DstReg.File == PROGRAM_OUTPUT && 88 inst[0].DstReg.Index == FRAG_RESULT_COLOR && 89 inst[0].DstReg.WriteMask == WRITEMASK_XYZW && 90 inst[0].SrcReg[0].File == PROGRAM_INPUT && 91 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 && 92 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) { 93 return GL_TRUE; 94 } 95 } 96 return GL_FALSE; 97} 98 99 100/** 101 * Returns a fragment program which implements the current pixel transfer ops. 102 */ 103static struct gl_fragment_program * 104get_glsl_pixel_transfer_program(struct st_context *st, 105 struct st_fragment_program *orig) 106{ 107 int pixelMaps = 0, scaleAndBias = 0; 108 struct gl_context *ctx = st->ctx; 109 struct st_fragment_program *fp = (struct st_fragment_program *) 110 ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 111 112 if (!fp) 113 return NULL; 114 115 if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 || 116 ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 || 117 ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 || 118 ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) { 119 scaleAndBias = 1; 120 } 121 122 pixelMaps = ctx->Pixel.MapColorFlag; 123 124 if (pixelMaps) { 125 /* create the colormap/texture now if not already done */ 126 if (!st->pixel_xfer.pixelmap_texture) { 127 st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx); 128 st->pixel_xfer.pixelmap_sampler_view = 129 st_create_texture_sampler_view(st->pipe, 130 st->pixel_xfer.pixelmap_texture); 131 } 132 } 133 134 get_pixel_transfer_visitor(fp, orig->glsl_to_tgsi, 135 scaleAndBias, pixelMaps); 136 137 return &fp->Base; 138} 139 140 141/** 142 * Make fragment shader for glDraw/CopyPixels. This shader is made 143 * by combining the pixel transfer shader with the user-defined shader. 144 * \param fpIn the current/incoming fragment program 145 * \param fpOut returns the combined fragment program 146 */ 147void 148st_make_drawpix_fragment_program(struct st_context *st, 149 struct gl_fragment_program *fpIn, 150 struct gl_fragment_program **fpOut) 151{ 152 struct gl_program *newProg; 153 struct st_fragment_program *stfp = (struct st_fragment_program *) fpIn; 154 155 if (is_passthrough_program(fpIn)) { 156 newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx, 157 &st->pixel_xfer.program->Base); 158 } 159 else if (stfp->glsl_to_tgsi != NULL) { 160 newProg = (struct gl_program *) get_glsl_pixel_transfer_program(st, stfp); 161 } 162 else { 163#if 0 164 /* debug */ 165 printf("Base program:\n"); 166 _mesa_print_program(&fpIn->Base); 167 printf("DrawPix program:\n"); 168 _mesa_print_program(&st->pixel_xfer.program->Base.Base); 169#endif 170 newProg = _mesa_combine_programs(st->ctx, 171 &st->pixel_xfer.program->Base.Base, 172 &fpIn->Base); 173 } 174 175#if 0 176 /* debug */ 177 printf("Combined DrawPixels program:\n"); 178 _mesa_print_program(newProg); 179 printf("InputsRead: 0x%x\n", newProg->InputsRead); 180 printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); 181 _mesa_print_parameter_list(newProg->Parameters); 182#endif 183 184 *fpOut = (struct gl_fragment_program *) newProg; 185} 186 187 188/** 189 * Create fragment program that does a TEX() instruction to get a Z and/or 190 * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL. 191 * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). 192 * Pass fragment color through as-is. 193 * \return pointer to the gl_fragment program 194 */ 195struct gl_fragment_program * 196st_make_drawpix_z_stencil_program(struct st_context *st, 197 GLboolean write_depth, 198 GLboolean write_stencil) 199{ 200 struct gl_context *ctx = st->ctx; 201 struct gl_program *p; 202 struct gl_fragment_program *fp; 203 GLuint ic = 0; 204 const GLuint shaderIndex = write_depth * 2 + write_stencil; 205 206 assert(shaderIndex < Elements(st->drawpix.shaders)); 207 208 if (st->drawpix.shaders[shaderIndex]) { 209 /* already have the proper shader */ 210 return st->drawpix.shaders[shaderIndex]; 211 } 212 213 /* 214 * Create shader now 215 */ 216 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 217 if (!p) 218 return NULL; 219 220 p->NumInstructions = write_depth ? 2 : 1; 221 p->NumInstructions += write_stencil ? 1 : 0; 222 223 p->Instructions = _mesa_alloc_instructions(p->NumInstructions); 224 if (!p->Instructions) { 225 ctx->Driver.DeleteProgram(ctx, p); 226 return NULL; 227 } 228 _mesa_init_instructions(p->Instructions, p->NumInstructions); 229 230 if (write_depth) { 231 /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */ 232 p->Instructions[ic].Opcode = OPCODE_TEX; 233 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 234 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH; 235 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z; 236 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 237 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 238 p->Instructions[ic].TexSrcUnit = 0; 239 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; 240 ic++; 241 } 242 243 if (write_stencil) { 244 /* TEX result.stencil, fragment.texcoord[0], texture[0], 2D; */ 245 p->Instructions[ic].Opcode = OPCODE_TEX; 246 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 247 p->Instructions[ic].DstReg.Index = FRAG_RESULT_STENCIL; 248 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Y; 249 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 250 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 251 p->Instructions[ic].TexSrcUnit = 1; 252 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; 253 ic++; 254 } 255 256 /* END; */ 257 p->Instructions[ic++].Opcode = OPCODE_END; 258 259 assert(ic == p->NumInstructions); 260 261 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0; 262 p->OutputsWritten = 0; 263 if (write_depth) 264 p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH); 265 if (write_stencil) 266 p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL); 267 268 p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ 269 if (write_stencil) 270 p->SamplersUsed |= 1 << 1; 271 272 fp = (struct gl_fragment_program *) p; 273 274 /* save the new shader */ 275 st->drawpix.shaders[shaderIndex] = fp; 276 277 return fp; 278} 279 280 281/** 282 * Create a simple vertex shader that just passes through the 283 * vertex position and texcoord (and optionally, color). 284 */ 285static void * 286make_passthrough_vertex_shader(struct st_context *st, 287 GLboolean passColor) 288{ 289 if (!st->drawpix.vert_shaders[passColor]) { 290 struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); 291 292 if (ureg == NULL) 293 return NULL; 294 295 /* MOV result.pos, vertex.pos; */ 296 ureg_MOV(ureg, 297 ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ), 298 ureg_DECL_vs_input( ureg, 0 )); 299 300 /* MOV result.texcoord0, vertex.attr[1]; */ 301 ureg_MOV(ureg, 302 ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), 303 ureg_DECL_vs_input( ureg, 1 )); 304 305 if (passColor) { 306 /* MOV result.color0, vertex.attr[2]; */ 307 ureg_MOV(ureg, 308 ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ), 309 ureg_DECL_vs_input( ureg, 2 )); 310 } 311 312 ureg_END( ureg ); 313 314 st->drawpix.vert_shaders[passColor] = 315 ureg_create_shader_and_destroy( ureg, st->pipe ); 316 } 317 318 return st->drawpix.vert_shaders[passColor]; 319} 320 321 322/** 323 * Return a texture internalFormat for drawing/copying an image 324 * of the given format and type. 325 */ 326static GLenum 327internal_format(struct gl_context *ctx, GLenum format, GLenum type) 328{ 329 switch (format) { 330 case GL_DEPTH_COMPONENT: 331 switch (type) { 332 case GL_UNSIGNED_SHORT: 333 return GL_DEPTH_COMPONENT16; 334 335 case GL_UNSIGNED_INT: 336 return GL_DEPTH_COMPONENT32; 337 338 case GL_FLOAT: 339 if (ctx->Extensions.ARB_depth_buffer_float) 340 return GL_DEPTH_COMPONENT32F; 341 else 342 return GL_DEPTH_COMPONENT; 343 344 default: 345 return GL_DEPTH_COMPONENT; 346 } 347 348 case GL_DEPTH_STENCIL: 349 switch (type) { 350 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: 351 return GL_DEPTH32F_STENCIL8; 352 353 case GL_UNSIGNED_INT_24_8: 354 default: 355 return GL_DEPTH24_STENCIL8; 356 } 357 358 case GL_STENCIL_INDEX: 359 return GL_STENCIL_INDEX; 360 361 default: 362 if (_mesa_is_integer_format(format)) { 363 switch (type) { 364 case GL_BYTE: 365 return GL_RGBA8I; 366 case GL_UNSIGNED_BYTE: 367 return GL_RGBA8UI; 368 case GL_SHORT: 369 return GL_RGBA16I; 370 case GL_UNSIGNED_SHORT: 371 return GL_RGBA16UI; 372 case GL_INT: 373 return GL_RGBA32I; 374 case GL_UNSIGNED_INT: 375 return GL_RGBA32UI; 376 default: 377 assert(0 && "Unexpected type in internal_format()"); 378 return GL_RGBA_INTEGER; 379 } 380 } 381 else { 382 switch (type) { 383 case GL_UNSIGNED_BYTE: 384 case GL_UNSIGNED_INT_8_8_8_8: 385 case GL_UNSIGNED_INT_8_8_8_8_REV: 386 default: 387 return GL_RGBA8; 388 389 case GL_UNSIGNED_BYTE_3_3_2: 390 case GL_UNSIGNED_BYTE_2_3_3_REV: 391 case GL_UNSIGNED_SHORT_4_4_4_4: 392 case GL_UNSIGNED_SHORT_4_4_4_4_REV: 393 return GL_RGBA4; 394 395 case GL_UNSIGNED_SHORT_5_6_5: 396 case GL_UNSIGNED_SHORT_5_6_5_REV: 397 case GL_UNSIGNED_SHORT_5_5_5_1: 398 case GL_UNSIGNED_SHORT_1_5_5_5_REV: 399 return GL_RGB5_A1; 400 401 case GL_UNSIGNED_INT_10_10_10_2: 402 case GL_UNSIGNED_INT_2_10_10_10_REV: 403 return GL_RGB10_A2; 404 405 case GL_UNSIGNED_SHORT: 406 case GL_UNSIGNED_INT: 407 return GL_RGBA16; 408 409 case GL_BYTE: 410 return 411 ctx->Extensions.EXT_texture_snorm ? GL_RGBA8_SNORM : GL_RGBA8; 412 413 case GL_SHORT: 414 case GL_INT: 415 return 416 ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16; 417 418 case GL_HALF_FLOAT_ARB: 419 return 420 ctx->Extensions.ARB_texture_float ? GL_RGBA16F : 421 ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16; 422 423 case GL_FLOAT: 424 case GL_DOUBLE: 425 return 426 ctx->Extensions.ARB_texture_float ? GL_RGBA32F : 427 ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16; 428 429 case GL_UNSIGNED_INT_5_9_9_9_REV: 430 assert(ctx->Extensions.EXT_texture_shared_exponent); 431 return GL_RGB9_E5; 432 433 case GL_UNSIGNED_INT_10F_11F_11F_REV: 434 assert(ctx->Extensions.EXT_packed_float); 435 return GL_R11F_G11F_B10F; 436 } 437 } 438 } 439} 440 441 442/** 443 * Create a temporary texture to hold an image of the given size. 444 * If width, height are not POT and the driver only handles POT textures, 445 * allocate the next larger size of texture that is POT. 446 */ 447static struct pipe_resource * 448alloc_texture(struct st_context *st, GLsizei width, GLsizei height, 449 enum pipe_format texFormat) 450{ 451 struct pipe_resource *pt; 452 453 pt = st_texture_create(st, st->internal_target, texFormat, 0, 454 width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW); 455 456 return pt; 457} 458 459 460/** 461 * Make texture containing an image for glDrawPixels image. 462 * If 'pixels' is NULL, leave the texture image data undefined. 463 */ 464static struct pipe_resource * 465make_texture(struct st_context *st, 466 GLsizei width, GLsizei height, GLenum format, GLenum type, 467 const struct gl_pixelstore_attrib *unpack, 468 const GLvoid *pixels) 469{ 470 struct gl_context *ctx = st->ctx; 471 struct pipe_context *pipe = st->pipe; 472 gl_format mformat; 473 struct pipe_resource *pt; 474 enum pipe_format pipeFormat; 475 GLenum baseInternalFormat, intFormat; 476 477 intFormat = internal_format(ctx, format, type); 478 baseInternalFormat = _mesa_base_tex_format(ctx, intFormat); 479 480 mformat = st_ChooseTextureFormat_renderable(ctx, intFormat, 481 format, type, GL_FALSE); 482 assert(mformat); 483 484 pipeFormat = st_mesa_format_to_pipe_format(mformat); 485 assert(pipeFormat); 486 487 pixels = _mesa_map_pbo_source(ctx, unpack, pixels); 488 if (!pixels) 489 return NULL; 490 491 /* alloc temporary texture */ 492 pt = alloc_texture(st, width, height, pipeFormat); 493 if (!pt) { 494 _mesa_unmap_pbo_source(ctx, unpack); 495 return NULL; 496 } 497 498 { 499 struct pipe_transfer *transfer; 500 GLboolean success; 501 GLubyte *dest; 502 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState; 503 504 /* we'll do pixel transfer in a fragment shader */ 505 ctx->_ImageTransferState = 0x0; 506 507 transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 508 PIPE_TRANSFER_WRITE, 0, 0, 509 width, height); 510 511 /* map texture transfer */ 512 dest = pipe_transfer_map(pipe, transfer); 513 514 515 /* Put image into texture transfer. 516 * Note that the image is actually going to be upside down in 517 * the texture. We deal with that with texcoords. 518 */ 519 success = _mesa_texstore(ctx, 2, /* dims */ 520 baseInternalFormat, /* baseInternalFormat */ 521 mformat, /* gl_format */ 522 transfer->stride, /* dstRowStride, bytes */ 523 &dest, /* destSlices */ 524 width, height, 1, /* size */ 525 format, type, /* src format/type */ 526 pixels, /* data source */ 527 unpack); 528 529 /* unmap */ 530 pipe_transfer_unmap(pipe, transfer); 531 pipe->transfer_destroy(pipe, transfer); 532 533 assert(success); 534 535 /* restore */ 536 ctx->_ImageTransferState = imageTransferStateSave; 537 } 538 539 _mesa_unmap_pbo_source(ctx, unpack); 540 541 return pt; 542} 543 544 545/** 546 * Draw quad with texcoords and optional color. 547 * Coords are gallium window coords with y=0=top. 548 * \param color may be null 549 * \param invertTex if true, flip texcoords vertically 550 */ 551static void 552draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z, 553 GLfloat x1, GLfloat y1, const GLfloat *color, 554 GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord) 555{ 556 struct st_context *st = st_context(ctx); 557 struct pipe_context *pipe = st->pipe; 558 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */ 559 560 /* setup vertex data */ 561 { 562 const struct gl_framebuffer *fb = st->ctx->DrawBuffer; 563 const GLfloat fb_width = (GLfloat) fb->Width; 564 const GLfloat fb_height = (GLfloat) fb->Height; 565 const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f; 566 const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f; 567 const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f; 568 const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f; 569 const GLfloat sLeft = 0.0f, sRight = maxXcoord; 570 const GLfloat tTop = invertTex ? maxYcoord : 0.0f; 571 const GLfloat tBot = invertTex ? 0.0f : maxYcoord; 572 GLuint i; 573 574 /* upper-left */ 575 verts[0][0][0] = clip_x0; /* v[0].attr[0].x */ 576 verts[0][0][1] = clip_y0; /* v[0].attr[0].y */ 577 578 /* upper-right */ 579 verts[1][0][0] = clip_x1; 580 verts[1][0][1] = clip_y0; 581 582 /* lower-right */ 583 verts[2][0][0] = clip_x1; 584 verts[2][0][1] = clip_y1; 585 586 /* lower-left */ 587 verts[3][0][0] = clip_x0; 588 verts[3][0][1] = clip_y1; 589 590 verts[0][1][0] = sLeft; /* v[0].attr[1].S */ 591 verts[0][1][1] = tTop; /* v[0].attr[1].T */ 592 verts[1][1][0] = sRight; 593 verts[1][1][1] = tTop; 594 verts[2][1][0] = sRight; 595 verts[2][1][1] = tBot; 596 verts[3][1][0] = sLeft; 597 verts[3][1][1] = tBot; 598 599 /* same for all verts: */ 600 if (color) { 601 for (i = 0; i < 4; i++) { 602 verts[i][0][2] = z; /* v[i].attr[0].z */ 603 verts[i][0][3] = 1.0f; /* v[i].attr[0].w */ 604 verts[i][2][0] = color[0]; /* v[i].attr[2].r */ 605 verts[i][2][1] = color[1]; /* v[i].attr[2].g */ 606 verts[i][2][2] = color[2]; /* v[i].attr[2].b */ 607 verts[i][2][3] = color[3]; /* v[i].attr[2].a */ 608 verts[i][1][2] = 0.0f; /* v[i].attr[1].R */ 609 verts[i][1][3] = 1.0f; /* v[i].attr[1].Q */ 610 } 611 } 612 else { 613 for (i = 0; i < 4; i++) { 614 verts[i][0][2] = z; /*Z*/ 615 verts[i][0][3] = 1.0f; /*W*/ 616 verts[i][1][2] = 0.0f; /*R*/ 617 verts[i][1][3] = 1.0f; /*Q*/ 618 } 619 } 620 } 621 622 { 623 struct pipe_resource *buf = NULL; 624 unsigned offset; 625 626 u_upload_data(st->uploader, 0, sizeof(verts), verts, &offset, &buf); 627 if (!buf) { 628 return; 629 } 630 631 u_upload_unmap(st->uploader); 632 util_draw_vertex_buffer(pipe, st->cso_context, buf, offset, 633 PIPE_PRIM_QUADS, 634 4, /* verts */ 635 3); /* attribs/vert */ 636 pipe_resource_reference(&buf, NULL); 637 } 638} 639 640 641 642static void 643draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, 644 GLsizei width, GLsizei height, 645 GLfloat zoomX, GLfloat zoomY, 646 struct pipe_sampler_view **sv, 647 int num_sampler_view, 648 void *driver_vp, 649 void *driver_fp, 650 const GLfloat *color, 651 GLboolean invertTex, 652 GLboolean write_depth, GLboolean write_stencil) 653{ 654 struct st_context *st = st_context(ctx); 655 struct pipe_context *pipe = st->pipe; 656 struct cso_context *cso = st->cso_context; 657 GLfloat x0, y0, x1, y1; 658 GLsizei maxSize; 659 boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT; 660 661 /* limit checks */ 662 /* XXX if DrawPixels image is larger than max texture size, break 663 * it up into chunks. 664 */ 665 maxSize = 1 << (pipe->screen->get_param(pipe->screen, 666 PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 667 assert(width <= maxSize); 668 assert(height <= maxSize); 669 670 cso_save_rasterizer(cso); 671 cso_save_viewport(cso); 672 cso_save_samplers(cso); 673 cso_save_fragment_sampler_views(cso); 674 cso_save_fragment_shader(cso); 675 cso_save_stream_outputs(cso); 676 cso_save_vertex_shader(cso); 677 cso_save_geometry_shader(cso); 678 cso_save_vertex_elements(cso); 679 cso_save_vertex_buffers(cso); 680 if (write_stencil) { 681 cso_save_depth_stencil_alpha(cso); 682 cso_save_blend(cso); 683 } 684 685 /* rasterizer state: just scissor */ 686 { 687 struct pipe_rasterizer_state rasterizer; 688 memset(&rasterizer, 0, sizeof(rasterizer)); 689 rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader && 690 ctx->Color._ClampFragmentColor; 691 rasterizer.gl_rasterization_rules = 1; 692 rasterizer.depth_clip = !ctx->Transform.DepthClamp; 693 rasterizer.scissor = ctx->Scissor.Enabled; 694 cso_set_rasterizer(cso, &rasterizer); 695 } 696 697 if (write_stencil) { 698 /* Stencil writing bypasses the normal fragment pipeline to 699 * disable color writing and set stencil test to always pass. 700 */ 701 struct pipe_depth_stencil_alpha_state dsa; 702 struct pipe_blend_state blend; 703 704 /* depth/stencil */ 705 memset(&dsa, 0, sizeof(dsa)); 706 dsa.stencil[0].enabled = 1; 707 dsa.stencil[0].func = PIPE_FUNC_ALWAYS; 708 dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff; 709 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 710 if (write_depth) { 711 /* writing depth+stencil: depth test always passes */ 712 dsa.depth.enabled = 1; 713 dsa.depth.writemask = ctx->Depth.Mask; 714 dsa.depth.func = PIPE_FUNC_ALWAYS; 715 } 716 cso_set_depth_stencil_alpha(cso, &dsa); 717 718 /* blend (colormask) */ 719 memset(&blend, 0, sizeof(blend)); 720 cso_set_blend(cso, &blend); 721 } 722 723 /* fragment shader state: TEX lookup program */ 724 cso_set_fragment_shader_handle(cso, driver_fp); 725 726 /* vertex shader state: position + texcoord pass-through */ 727 cso_set_vertex_shader_handle(cso, driver_vp); 728 729 /* geometry shader state: disabled */ 730 cso_set_geometry_shader_handle(cso, NULL); 731 732 /* texture sampling state: */ 733 { 734 struct pipe_sampler_state sampler; 735 memset(&sampler, 0, sizeof(sampler)); 736 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; 737 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; 738 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; 739 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 740 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 741 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 742 sampler.normalized_coords = normalized; 743 744 cso_single_sampler(cso, 0, &sampler); 745 if (num_sampler_view > 1) { 746 cso_single_sampler(cso, 1, &sampler); 747 } 748 cso_single_sampler_done(cso); 749 } 750 751 /* viewport state: viewport matching window dims */ 752 { 753 const float w = (float) ctx->DrawBuffer->Width; 754 const float h = (float) ctx->DrawBuffer->Height; 755 struct pipe_viewport_state vp; 756 vp.scale[0] = 0.5f * w; 757 vp.scale[1] = -0.5f * h; 758 vp.scale[2] = 0.5f; 759 vp.scale[3] = 1.0f; 760 vp.translate[0] = 0.5f * w; 761 vp.translate[1] = 0.5f * h; 762 vp.translate[2] = 0.5f; 763 vp.translate[3] = 0.0f; 764 cso_set_viewport(cso, &vp); 765 } 766 767 cso_set_vertex_elements(cso, 3, st->velems_util_draw); 768 cso_set_stream_outputs(st->cso_context, 0, NULL, 0); 769 770 /* texture state: */ 771 cso_set_fragment_sampler_views(cso, num_sampler_view, sv); 772 773 /* Compute Gallium window coords (y=0=top) with pixel zoom. 774 * Recall that these coords are transformed by the current 775 * vertex shader and viewport transformation. 776 */ 777 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { 778 y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY); 779 invertTex = !invertTex; 780 } 781 782 x0 = (GLfloat) x; 783 x1 = x + width * ctx->Pixel.ZoomX; 784 y0 = (GLfloat) y; 785 y1 = y + height * ctx->Pixel.ZoomY; 786 787 /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ 788 z = z * 2.0 - 1.0; 789 790 draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, 791 normalized ? ((GLfloat) width / sv[0]->texture->width0) : (GLfloat)width, 792 normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height); 793 794 /* restore state */ 795 cso_restore_rasterizer(cso); 796 cso_restore_viewport(cso); 797 cso_restore_samplers(cso); 798 cso_restore_fragment_sampler_views(cso); 799 cso_restore_fragment_shader(cso); 800 cso_restore_vertex_shader(cso); 801 cso_restore_geometry_shader(cso); 802 cso_restore_vertex_elements(cso); 803 cso_restore_vertex_buffers(cso); 804 cso_restore_stream_outputs(cso); 805 if (write_stencil) { 806 cso_restore_depth_stencil_alpha(cso); 807 cso_restore_blend(cso); 808 } 809} 810 811 812/** 813 * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we 814 * can't use a fragment shader to write stencil values. 815 */ 816static void 817draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, 818 GLsizei width, GLsizei height, GLenum format, GLenum type, 819 const struct gl_pixelstore_attrib *unpack, 820 const GLvoid *pixels) 821{ 822 struct st_context *st = st_context(ctx); 823 struct pipe_context *pipe = st->pipe; 824 struct st_renderbuffer *strb; 825 enum pipe_transfer_usage usage; 826 struct pipe_transfer *pt; 827 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 828 ubyte *stmap; 829 struct gl_pixelstore_attrib clippedUnpack = *unpack; 830 GLubyte *sValues; 831 GLuint *zValues; 832 833 if (!zoom) { 834 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, 835 &clippedUnpack)) { 836 /* totally clipped */ 837 return; 838 } 839 } 840 841 strb = st_renderbuffer(ctx->DrawBuffer-> 842 Attachment[BUFFER_STENCIL].Renderbuffer); 843 844 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 845 y = ctx->DrawBuffer->Height - y - height; 846 } 847 848 if (format == GL_STENCIL_INDEX && 849 _mesa_is_format_packed_depth_stencil(strb->Base.Format)) { 850 /* writing stencil to a combined depth+stencil buffer */ 851 usage = PIPE_TRANSFER_READ_WRITE; 852 } 853 else { 854 usage = PIPE_TRANSFER_WRITE; 855 } 856 857 pt = pipe_get_transfer(pipe, strb->texture, 858 strb->rtt_level, strb->rtt_face + strb->rtt_slice, 859 usage, x, y, 860 width, height); 861 862 stmap = pipe_transfer_map(pipe, pt); 863 864 pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); 865 assert(pixels); 866 867 sValues = (GLubyte *) malloc(width * sizeof(GLubyte)); 868 zValues = (GLuint *) malloc(width * sizeof(GLuint)); 869 870 if (sValues && zValues) { 871 GLint row; 872 for (row = 0; row < height; row++) { 873 GLfloat *zValuesFloat = (GLfloat*)zValues; 874 GLenum destType = GL_UNSIGNED_BYTE; 875 const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, 876 width, height, 877 format, type, 878 row, 0); 879 _mesa_unpack_stencil_span(ctx, width, destType, sValues, 880 type, source, &clippedUnpack, 881 ctx->_ImageTransferState); 882 883 if (format == GL_DEPTH_STENCIL) { 884 GLenum ztype = 885 pt->resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ? 886 GL_FLOAT : GL_UNSIGNED_INT; 887 888 _mesa_unpack_depth_span(ctx, width, ztype, zValues, 889 (1 << 24) - 1, type, source, 890 &clippedUnpack); 891 } 892 893 if (zoom) { 894 _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " 895 "zoom not complete"); 896 } 897 898 { 899 GLint spanY; 900 901 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 902 spanY = height - row - 1; 903 } 904 else { 905 spanY = row; 906 } 907 908 /* now pack the stencil (and Z) values in the dest format */ 909 switch (pt->resource->format) { 910 case PIPE_FORMAT_S8_UINT: 911 { 912 ubyte *dest = stmap + spanY * pt->stride; 913 assert(usage == PIPE_TRANSFER_WRITE); 914 memcpy(dest, sValues, width); 915 } 916 break; 917 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 918 if (format == GL_DEPTH_STENCIL) { 919 uint *dest = (uint *) (stmap + spanY * pt->stride); 920 GLint k; 921 assert(usage == PIPE_TRANSFER_WRITE); 922 for (k = 0; k < width; k++) { 923 dest[k] = zValues[k] | (sValues[k] << 24); 924 } 925 } 926 else { 927 uint *dest = (uint *) (stmap + spanY * pt->stride); 928 GLint k; 929 assert(usage == PIPE_TRANSFER_READ_WRITE); 930 for (k = 0; k < width; k++) { 931 dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); 932 } 933 } 934 break; 935 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 936 if (format == GL_DEPTH_STENCIL) { 937 uint *dest = (uint *) (stmap + spanY * pt->stride); 938 GLint k; 939 assert(usage == PIPE_TRANSFER_WRITE); 940 for (k = 0; k < width; k++) { 941 dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); 942 } 943 } 944 else { 945 uint *dest = (uint *) (stmap + spanY * pt->stride); 946 GLint k; 947 assert(usage == PIPE_TRANSFER_READ_WRITE); 948 for (k = 0; k < width; k++) { 949 dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); 950 } 951 } 952 break; 953 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 954 if (format == GL_DEPTH_STENCIL) { 955 uint *dest = (uint *) (stmap + spanY * pt->stride); 956 GLfloat *destf = (GLfloat*)dest; 957 GLint k; 958 assert(usage == PIPE_TRANSFER_WRITE); 959 for (k = 0; k < width; k++) { 960 destf[k*2] = zValuesFloat[k]; 961 dest[k*2+1] = sValues[k] & 0xff; 962 } 963 } 964 else { 965 uint *dest = (uint *) (stmap + spanY * pt->stride); 966 GLint k; 967 assert(usage == PIPE_TRANSFER_READ_WRITE); 968 for (k = 0; k < width; k++) { 969 dest[k*2+1] = sValues[k] & 0xff; 970 } 971 } 972 break; 973 default: 974 assert(0); 975 } 976 } 977 } 978 } 979 else { 980 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels()"); 981 } 982 983 free(sValues); 984 free(zValues); 985 986 _mesa_unmap_pbo_source(ctx, &clippedUnpack); 987 988 /* unmap the stencil buffer */ 989 pipe_transfer_unmap(pipe, pt); 990 pipe->transfer_destroy(pipe, pt); 991} 992 993 994/** 995 * Get fragment program variant for a glDrawPixels or glCopyPixels 996 * command for RGBA data. 997 */ 998static struct st_fp_variant * 999get_color_fp_variant(struct st_context *st) 1000{ 1001 struct gl_context *ctx = st->ctx; 1002 struct st_fp_variant_key key; 1003 struct st_fp_variant *fpv; 1004 1005 memset(&key, 0, sizeof(key)); 1006 1007 key.st = st; 1008 key.drawpixels = 1; 1009 key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 || 1010 ctx->Pixel.RedScale != 1.0 || 1011 ctx->Pixel.GreenBias != 0.0 || 1012 ctx->Pixel.GreenScale != 1.0 || 1013 ctx->Pixel.BlueBias != 0.0 || 1014 ctx->Pixel.BlueScale != 1.0 || 1015 ctx->Pixel.AlphaBias != 0.0 || 1016 ctx->Pixel.AlphaScale != 1.0); 1017 key.pixelMaps = ctx->Pixel.MapColorFlag; 1018 key.clamp_color = st->clamp_frag_color_in_shader && 1019 st->ctx->Color._ClampFragmentColor; 1020 1021 fpv = st_get_fp_variant(st, st->fp, &key); 1022 1023 return fpv; 1024} 1025 1026 1027/** 1028 * Get fragment program variant for a glDrawPixels or glCopyPixels 1029 * command for depth/stencil data. 1030 */ 1031static struct st_fp_variant * 1032get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth, 1033 GLboolean write_stencil) 1034{ 1035 struct st_fp_variant_key key; 1036 struct st_fp_variant *fpv; 1037 1038 memset(&key, 0, sizeof(key)); 1039 1040 key.st = st; 1041 key.drawpixels = 1; 1042 key.drawpixels_z = write_depth; 1043 key.drawpixels_stencil = write_stencil; 1044 1045 fpv = st_get_fp_variant(st, st->fp, &key); 1046 1047 return fpv; 1048} 1049 1050 1051/** 1052 * Called via ctx->Driver.DrawPixels() 1053 */ 1054static void 1055st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, 1056 GLsizei width, GLsizei height, 1057 GLenum format, GLenum type, 1058 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) 1059{ 1060 void *driver_vp, *driver_fp; 1061 struct st_context *st = st_context(ctx); 1062 const GLfloat *color; 1063 struct pipe_context *pipe = st->pipe; 1064 GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE; 1065 struct pipe_sampler_view *sv[2]; 1066 int num_sampler_view = 1; 1067 struct st_fp_variant *fpv; 1068 1069 if (format == GL_DEPTH_STENCIL) 1070 write_stencil = write_depth = GL_TRUE; 1071 else if (format == GL_STENCIL_INDEX) 1072 write_stencil = GL_TRUE; 1073 else if (format == GL_DEPTH_COMPONENT) 1074 write_depth = GL_TRUE; 1075 1076 if (write_stencil && 1077 !pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) { 1078 /* software fallback */ 1079 draw_stencil_pixels(ctx, x, y, width, height, format, type, 1080 unpack, pixels); 1081 return; 1082 } 1083 1084 /* Mesa state should be up to date by now */ 1085 assert(ctx->NewState == 0x0); 1086 1087 st_validate_state(st); 1088 1089 /* 1090 * Get vertex/fragment shaders 1091 */ 1092 if (write_depth || write_stencil) { 1093 fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil); 1094 1095 driver_fp = fpv->driver_shader; 1096 1097 driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); 1098 1099 color = ctx->Current.RasterColor; 1100 } 1101 else { 1102 fpv = get_color_fp_variant(st); 1103 1104 driver_fp = fpv->driver_shader; 1105 1106 driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); 1107 1108 color = NULL; 1109 if (st->pixel_xfer.pixelmap_enabled) { 1110 sv[1] = st->pixel_xfer.pixelmap_sampler_view; 1111 num_sampler_view++; 1112 } 1113 } 1114 1115 /* update fragment program constants */ 1116 st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); 1117 1118 /* draw with textured quad */ 1119 { 1120 struct pipe_resource *pt 1121 = make_texture(st, width, height, format, type, unpack, pixels); 1122 if (pt) { 1123 sv[0] = st_create_texture_sampler_view(st->pipe, pt); 1124 1125 if (sv[0]) { 1126 /* Create a second sampler view to read stencil. 1127 * The stencil is written using the shader stencil export 1128 * functionality. */ 1129 if (write_stencil) { 1130 enum pipe_format stencil_format = PIPE_FORMAT_NONE; 1131 1132 switch (pt->format) { 1133 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 1134 case PIPE_FORMAT_X24S8_UINT: 1135 stencil_format = PIPE_FORMAT_X24S8_UINT; 1136 break; 1137 case PIPE_FORMAT_S8_UINT_Z24_UNORM: 1138 case PIPE_FORMAT_S8X24_UINT: 1139 stencil_format = PIPE_FORMAT_S8X24_UINT; 1140 break; 1141 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 1142 case PIPE_FORMAT_X32_S8X24_UINT: 1143 stencil_format = PIPE_FORMAT_X32_S8X24_UINT; 1144 break; 1145 case PIPE_FORMAT_S8_UINT: 1146 stencil_format = PIPE_FORMAT_S8_UINT; 1147 break; 1148 default: 1149 assert(0); 1150 } 1151 1152 sv[1] = st_create_texture_sampler_view_format(st->pipe, pt, 1153 stencil_format); 1154 num_sampler_view++; 1155 } 1156 1157 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], 1158 width, height, 1159 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 1160 sv, 1161 num_sampler_view, 1162 driver_vp, 1163 driver_fp, 1164 color, GL_FALSE, write_depth, write_stencil); 1165 pipe_sampler_view_reference(&sv[0], NULL); 1166 if (num_sampler_view > 1) 1167 pipe_sampler_view_reference(&sv[1], NULL); 1168 } 1169 pipe_resource_reference(&pt, NULL); 1170 } 1171 } 1172} 1173 1174 1175 1176/** 1177 * Software fallback for glCopyPixels(GL_STENCIL). 1178 */ 1179static void 1180copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, 1181 GLsizei width, GLsizei height, 1182 GLint dstx, GLint dsty) 1183{ 1184 struct st_renderbuffer *rbDraw; 1185 struct pipe_context *pipe = st_context(ctx)->pipe; 1186 enum pipe_transfer_usage usage; 1187 struct pipe_transfer *ptDraw; 1188 ubyte *drawMap; 1189 ubyte *buffer; 1190 int i; 1191 1192 buffer = malloc(width * height * sizeof(ubyte)); 1193 if (!buffer) { 1194 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)"); 1195 return; 1196 } 1197 1198 /* Get the dest renderbuffer */ 1199 rbDraw = st_renderbuffer(ctx->DrawBuffer-> 1200 Attachment[BUFFER_STENCIL].Renderbuffer); 1201 1202 /* this will do stencil pixel transfer ops */ 1203 _mesa_readpixels(ctx, srcx, srcy, width, height, 1204 GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 1205 &ctx->DefaultPacking, buffer); 1206 1207 if (0) { 1208 /* debug code: dump stencil values */ 1209 GLint row, col; 1210 for (row = 0; row < height; row++) { 1211 printf("%3d: ", row); 1212 for (col = 0; col < width; col++) { 1213 printf("%02x ", buffer[col + row * width]); 1214 } 1215 printf("\n"); 1216 } 1217 } 1218 1219 if (_mesa_is_format_packed_depth_stencil(rbDraw->Base.Format)) 1220 usage = PIPE_TRANSFER_READ_WRITE; 1221 else 1222 usage = PIPE_TRANSFER_WRITE; 1223 1224 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 1225 dsty = rbDraw->Base.Height - dsty - height; 1226 } 1227 1228 ptDraw = pipe_get_transfer(pipe, 1229 rbDraw->texture, 1230 rbDraw->rtt_level, 1231 rbDraw->rtt_face + rbDraw->rtt_slice, 1232 usage, dstx, dsty, 1233 width, height); 1234 1235 assert(util_format_get_blockwidth(ptDraw->resource->format) == 1); 1236 assert(util_format_get_blockheight(ptDraw->resource->format) == 1); 1237 1238 /* map the stencil buffer */ 1239 drawMap = pipe_transfer_map(pipe, ptDraw); 1240 1241 /* draw */ 1242 /* XXX PixelZoom not handled yet */ 1243 for (i = 0; i < height; i++) { 1244 ubyte *dst; 1245 const ubyte *src; 1246 int y; 1247 1248 y = i; 1249 1250 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 1251 y = height - y - 1; 1252 } 1253 1254 dst = drawMap + y * ptDraw->stride; 1255 src = buffer + i * width; 1256 1257 _mesa_pack_ubyte_stencil_row(rbDraw->Base.Format, width, src, dst); 1258 } 1259 1260 free(buffer); 1261 1262 /* unmap the stencil buffer */ 1263 pipe_transfer_unmap(pipe, ptDraw); 1264 pipe->transfer_destroy(pipe, ptDraw); 1265} 1266 1267 1268/** 1269 * Return renderbuffer to use for reading color pixels for glCopyPixels 1270 */ 1271static struct st_renderbuffer * 1272st_get_color_read_renderbuffer(struct gl_context *ctx) 1273{ 1274 struct gl_framebuffer *fb = ctx->ReadBuffer; 1275 struct st_renderbuffer *strb = 1276 st_renderbuffer(fb->_ColorReadBuffer); 1277 1278 return strb; 1279} 1280 1281 1282/** Do the src/dest regions overlap? */ 1283static GLboolean 1284regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY, 1285 GLsizei width, GLsizei height) 1286{ 1287 if (srcX + width <= dstX || 1288 dstX + width <= srcX || 1289 srcY + height <= dstY || 1290 dstY + height <= srcY) 1291 return GL_FALSE; 1292 else 1293 return GL_TRUE; 1294} 1295 1296 1297/** 1298 * Try to do a glCopyPixels for simple cases with a blit by calling 1299 * pipe->resource_copy_region(). 1300 * 1301 * We can do this when we're copying color pixels (depth/stencil 1302 * eventually) with no pixel zoom, no pixel transfer ops, no 1303 * per-fragment ops, the src/dest regions don't overlap and the 1304 * src/dest pixel formats are the same. 1305 */ 1306static GLboolean 1307blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, 1308 GLsizei width, GLsizei height, 1309 GLint dstx, GLint dsty, GLenum type) 1310{ 1311 struct st_context *st = st_context(ctx); 1312 struct pipe_context *pipe = st->pipe; 1313 struct gl_pixelstore_attrib pack, unpack; 1314 GLint readX, readY, readW, readH; 1315 1316 if (type == GL_COLOR && 1317 ctx->Pixel.ZoomX == 1.0 && 1318 ctx->Pixel.ZoomY == 1.0 && 1319 ctx->_ImageTransferState == 0x0 && 1320 !ctx->Color.BlendEnabled && 1321 !ctx->Color.AlphaEnabled && 1322 !ctx->Depth.Test && 1323 !ctx->Fog.Enabled && 1324 !ctx->Stencil.Enabled && 1325 !ctx->FragmentProgram.Enabled && 1326 !ctx->VertexProgram.Enabled && 1327 !ctx->Shader.CurrentFragmentProgram && 1328 st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) && 1329 ctx->DrawBuffer->_NumColorDrawBuffers == 1 && 1330 !ctx->Query.CondRenderQuery) { 1331 struct st_renderbuffer *rbRead, *rbDraw; 1332 GLint drawX, drawY; 1333 1334 /* 1335 * Clip the read region against the src buffer bounds. 1336 * We'll still allocate a temporary buffer/texture for the original 1337 * src region size but we'll only read the region which is on-screen. 1338 * This may mean that we draw garbage pixels into the dest region, but 1339 * that's expected. 1340 */ 1341 readX = srcx; 1342 readY = srcy; 1343 readW = width; 1344 readH = height; 1345 pack = ctx->DefaultPacking; 1346 if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) 1347 return GL_TRUE; /* all done */ 1348 1349 /* clip against dest buffer bounds and scissor box */ 1350 drawX = dstx + pack.SkipPixels; 1351 drawY = dsty + pack.SkipRows; 1352 unpack = pack; 1353 if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack)) 1354 return GL_TRUE; /* all done */ 1355 1356 readX = readX - pack.SkipPixels + unpack.SkipPixels; 1357 readY = readY - pack.SkipRows + unpack.SkipRows; 1358 1359 rbRead = st_get_color_read_renderbuffer(ctx); 1360 rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); 1361 1362 if ((rbRead != rbDraw || 1363 !regions_overlap(readX, readY, drawX, drawY, readW, readH)) && 1364 rbRead->Base.Format == rbDraw->Base.Format) { 1365 struct pipe_box srcBox; 1366 1367 /* flip src/dst position if needed */ 1368 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1369 /* both buffers will have the same orientation */ 1370 readY = ctx->ReadBuffer->Height - readY - readH; 1371 drawY = ctx->DrawBuffer->Height - drawY - readH; 1372 } 1373 1374 u_box_2d(readX, readY, readW, readH, &srcBox); 1375 1376 pipe->resource_copy_region(pipe, 1377 rbDraw->texture, 1378 rbDraw->rtt_level, drawX, drawY, 0, 1379 rbRead->texture, 1380 rbRead->rtt_level, &srcBox); 1381 return GL_TRUE; 1382 } 1383 } 1384 1385 return GL_FALSE; 1386} 1387 1388 1389static void 1390st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, 1391 GLsizei width, GLsizei height, 1392 GLint dstx, GLint dsty, GLenum type) 1393{ 1394 struct st_context *st = st_context(ctx); 1395 struct pipe_context *pipe = st->pipe; 1396 struct pipe_screen *screen = pipe->screen; 1397 struct st_renderbuffer *rbRead; 1398 void *driver_vp, *driver_fp; 1399 struct pipe_resource *pt; 1400 struct pipe_sampler_view *sv[2]; 1401 int num_sampler_view = 1; 1402 GLfloat *color; 1403 enum pipe_format srcFormat, texFormat; 1404 GLboolean invertTex = GL_FALSE; 1405 GLint readX, readY, readW, readH; 1406 GLuint sample_count; 1407 struct gl_pixelstore_attrib pack = ctx->DefaultPacking; 1408 struct st_fp_variant *fpv; 1409 1410 st_validate_state(st); 1411 1412 if (type == GL_DEPTH_STENCIL) { 1413 /* XXX make this more efficient */ 1414 st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_STENCIL); 1415 st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_DEPTH); 1416 return; 1417 } 1418 1419 if (type == GL_STENCIL) { 1420 /* can't use texturing to do stencil */ 1421 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); 1422 return; 1423 } 1424 1425 if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type)) 1426 return; 1427 1428 /* 1429 * The subsequent code implements glCopyPixels by copying the source 1430 * pixels into a temporary texture that's then applied to a textured quad. 1431 * When we draw the textured quad, all the usual per-fragment operations 1432 * are handled. 1433 */ 1434 1435 1436 /* 1437 * Get vertex/fragment shaders 1438 */ 1439 if (type == GL_COLOR) { 1440 rbRead = st_get_color_read_renderbuffer(ctx); 1441 color = NULL; 1442 1443 fpv = get_color_fp_variant(st); 1444 driver_fp = fpv->driver_shader; 1445 1446 driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); 1447 1448 if (st->pixel_xfer.pixelmap_enabled) { 1449 sv[1] = st->pixel_xfer.pixelmap_sampler_view; 1450 num_sampler_view++; 1451 } 1452 } 1453 else { 1454 assert(type == GL_DEPTH); 1455 rbRead = st_renderbuffer(ctx->ReadBuffer-> 1456 Attachment[BUFFER_DEPTH].Renderbuffer); 1457 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 1458 1459 fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE); 1460 driver_fp = fpv->driver_shader; 1461 1462 driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); 1463 } 1464 1465 /* update fragment program constants */ 1466 st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); 1467 1468 sample_count = rbRead->texture->nr_samples; 1469 /* I believe this would be legal, presumably would need to do a resolve 1470 for color, and for depth/stencil spec says to just use one of the 1471 depth/stencil samples per pixel? Need some transfer clarifications. */ 1472 assert(sample_count < 2); 1473 1474 srcFormat = rbRead->texture->format; 1475 1476 if (screen->is_format_supported(screen, srcFormat, st->internal_target, 1477 sample_count, 1478 PIPE_BIND_SAMPLER_VIEW)) { 1479 texFormat = srcFormat; 1480 } 1481 else { 1482 /* srcFormat can't be used as a texture format */ 1483 if (type == GL_DEPTH) { 1484 texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, 1485 GL_NONE, GL_NONE, st->internal_target, 1486 sample_count, PIPE_BIND_DEPTH_STENCIL); 1487 assert(texFormat != PIPE_FORMAT_NONE); 1488 } 1489 else { 1490 /* default color format */ 1491 texFormat = st_choose_format(screen, GL_RGBA, 1492 GL_NONE, GL_NONE, st->internal_target, 1493 sample_count, PIPE_BIND_SAMPLER_VIEW); 1494 assert(texFormat != PIPE_FORMAT_NONE); 1495 } 1496 } 1497 1498 /* Invert src region if needed */ 1499 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1500 srcy = ctx->ReadBuffer->Height - srcy - height; 1501 invertTex = !invertTex; 1502 } 1503 1504 /* Clip the read region against the src buffer bounds. 1505 * We'll still allocate a temporary buffer/texture for the original 1506 * src region size but we'll only read the region which is on-screen. 1507 * This may mean that we draw garbage pixels into the dest region, but 1508 * that's expected. 1509 */ 1510 readX = srcx; 1511 readY = srcy; 1512 readW = width; 1513 readH = height; 1514 _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); 1515 readW = MAX2(0, readW); 1516 readH = MAX2(0, readH); 1517 1518 /* alloc temporary texture */ 1519 pt = alloc_texture(st, width, height, texFormat); 1520 if (!pt) 1521 return; 1522 1523 sv[0] = st_create_texture_sampler_view(st->pipe, pt); 1524 if (!sv[0]) { 1525 pipe_resource_reference(&pt, NULL); 1526 return; 1527 } 1528 1529 /* Make temporary texture which is a copy of the src region. 1530 */ 1531 if (srcFormat == texFormat) { 1532 struct pipe_box src_box; 1533 u_box_2d(readX, readY, readW, readH, &src_box); 1534 /* copy source framebuffer surface into mipmap/texture */ 1535 pipe->resource_copy_region(pipe, 1536 pt, /* dest tex */ 1537 0, /* dest lvl */ 1538 pack.SkipPixels, pack.SkipRows, 0, /* dest pos */ 1539 rbRead->texture, /* src tex */ 1540 rbRead->rtt_level, /* src lvl */ 1541 &src_box); 1542 1543 } 1544 else { 1545 /* CPU-based fallback/conversion */ 1546 struct pipe_transfer *ptRead = 1547 pipe_get_transfer(st->pipe, rbRead->texture, 1548 rbRead->rtt_level, 1549 rbRead->rtt_face + rbRead->rtt_slice, 1550 PIPE_TRANSFER_READ, 1551 readX, readY, readW, readH); 1552 struct pipe_transfer *ptTex; 1553 enum pipe_transfer_usage transfer_usage; 1554 1555 if (ST_DEBUG & DEBUG_FALLBACK) 1556 debug_printf("%s: fallback processing\n", __FUNCTION__); 1557 1558 if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format)) 1559 transfer_usage = PIPE_TRANSFER_READ_WRITE; 1560 else 1561 transfer_usage = PIPE_TRANSFER_WRITE; 1562 1563 ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage, 1564 0, 0, width, height); 1565 1566 /* copy image from ptRead surface to ptTex surface */ 1567 if (type == GL_COLOR) { 1568 /* alternate path using get/put_tile() */ 1569 GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); 1570 enum pipe_format readFormat, drawFormat; 1571 readFormat = util_format_linear(rbRead->texture->format); 1572 drawFormat = util_format_linear(pt->format); 1573 pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH, 1574 readFormat, buf); 1575 pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows, 1576 readW, readH, drawFormat, buf); 1577 free(buf); 1578 } 1579 else { 1580 /* GL_DEPTH */ 1581 GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); 1582 pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf); 1583 pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, 1584 readW, readH, buf); 1585 free(buf); 1586 } 1587 1588 pipe->transfer_destroy(pipe, ptRead); 1589 pipe->transfer_destroy(pipe, ptTex); 1590 } 1591 1592 /* OK, the texture 'pt' contains the src image/pixels. Now draw a 1593 * textured quad with that texture. 1594 */ 1595 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], 1596 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 1597 sv, 1598 num_sampler_view, 1599 driver_vp, 1600 driver_fp, 1601 color, invertTex, GL_FALSE, GL_FALSE); 1602 1603 pipe_resource_reference(&pt, NULL); 1604 pipe_sampler_view_reference(&sv[0], NULL); 1605} 1606 1607 1608 1609void st_init_drawpixels_functions(struct dd_function_table *functions) 1610{ 1611 functions->DrawPixels = st_DrawPixels; 1612 functions->CopyPixels = st_CopyPixels; 1613} 1614 1615 1616void 1617st_destroy_drawpix(struct st_context *st) 1618{ 1619 GLuint i; 1620 1621 for (i = 0; i < Elements(st->drawpix.shaders); i++) { 1622 if (st->drawpix.shaders[i]) 1623 _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL); 1624 } 1625 1626 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); 1627 if (st->drawpix.vert_shaders[0]) 1628 cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[0]); 1629 if (st->drawpix.vert_shaders[1]) 1630 cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[1]); 1631} 1632 1633#endif /* FEATURE_drawpix */ 1634