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