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