st_cb_drawpixels.c revision 127328bfadaa5f080730fd41f404f1bc74f490d3
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/texformat.h" 38#include "main/texstore.h" 39#include "shader/program.h" 40#include "shader/prog_print.h" 41 42#include "st_debug.h" 43#include "st_context.h" 44#include "st_atom.h" 45#include "st_atom_constbuf.h" 46#include "st_program.h" 47#include "st_cb_drawpixels.h" 48#include "st_cb_readpixels.h" 49#include "st_cb_fbo.h" 50#include "st_format.h" 51#include "st_texture.h" 52#include "st_inlines.h" 53 54#include "pipe/p_context.h" 55#include "pipe/p_defines.h" 56#include "util/u_inlines.h" 57#include "tgsi/tgsi_ureg.h" 58#include "util/u_tile.h" 59#include "util/u_draw_quad.h" 60#include "util/u_format.h" 61#include "util/u_math.h" 62#include "shader/prog_instruction.h" 63#include "cso_cache/cso_context.h" 64 65 66/** 67 * Check if the given program is: 68 * 0: MOVE result.color, fragment.color; 69 * 1: END; 70 */ 71static GLboolean 72is_passthrough_program(const struct gl_fragment_program *prog) 73{ 74 if (prog->Base.NumInstructions == 2) { 75 const struct prog_instruction *inst = prog->Base.Instructions; 76 if (inst[0].Opcode == OPCODE_MOV && 77 inst[1].Opcode == OPCODE_END && 78 inst[0].DstReg.File == PROGRAM_OUTPUT && 79 inst[0].DstReg.Index == FRAG_RESULT_COLOR && 80 inst[0].DstReg.WriteMask == WRITEMASK_XYZW && 81 inst[0].SrcReg[0].File == PROGRAM_INPUT && 82 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 && 83 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) { 84 return GL_TRUE; 85 } 86 } 87 return GL_FALSE; 88} 89 90 91 92/** 93 * Make fragment shader for glDraw/CopyPixels. This shader is made 94 * by combining the pixel transfer shader with the user-defined shader. 95 * \return pointer to Gallium driver fragment shader 96 */ 97static void * 98combined_drawpix_fragment_program(GLcontext *ctx) 99{ 100 struct st_context *st = st_context(ctx); 101 struct st_fragment_program *stfp; 102 103 if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn 104 && st->fp->serialNo == st->pixel_xfer.user_prog_sn) { 105 /* the pixel tranfer program has not changed and the user-defined 106 * program has not changed, so re-use the combined program. 107 */ 108 stfp = st->pixel_xfer.combined_prog; 109 } 110 else { 111 /* Concatenate the pixel transfer program with the current user- 112 * defined program. 113 */ 114 if (is_passthrough_program(&st->fp->Base)) { 115 stfp = (struct st_fragment_program *) 116 _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base); 117 } 118 else { 119#if 0 120 printf("Base program:\n"); 121 _mesa_print_program(&st->fp->Base.Base); 122 printf("DrawPix program:\n"); 123 _mesa_print_program(&st->pixel_xfer.program->Base.Base); 124#endif 125 stfp = (struct st_fragment_program *) 126 _mesa_combine_programs(ctx, 127 &st->pixel_xfer.program->Base.Base, 128 &st->fp->Base.Base); 129 } 130 131#if 0 132 { 133 struct gl_program *p = &stfp->Base.Base; 134 printf("Combined DrawPixels program:\n"); 135 _mesa_print_program(p); 136 printf("InputsRead: 0x%x\n", p->InputsRead); 137 printf("OutputsWritten: 0x%x\n", p->OutputsWritten); 138 _mesa_print_parameter_list(p->Parameters); 139 } 140#endif 141 142 /* translate to TGSI tokens */ 143 st_translate_fragment_program(st, stfp); 144 145 /* save new program, update serial numbers */ 146 st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo; 147 st->pixel_xfer.user_prog_sn = st->fp->serialNo; 148 st->pixel_xfer.combined_prog_sn = stfp->serialNo; 149 /* can't reference new program directly, already have a reference on it */ 150 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); 151 st->pixel_xfer.combined_prog = stfp; 152 } 153 154 /* Ideally we'd have updated the pipe constants during the normal 155 * st/atom mechanism. But we can't since this is specific to glDrawPixels. 156 */ 157 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); 158 159 return stfp->driver_shader; 160} 161 162 163/** 164 * Create fragment shader that does a TEX() instruction to get a Z 165 * value, then writes to FRAG_RESULT_DEPTH. 166 * Pass fragment color through as-is. 167 * \return pointer to the Gallium driver fragment shader 168 */ 169static void * 170make_fragment_shader_z(struct st_context *st) 171{ 172 GLcontext *ctx = st->ctx; 173 struct gl_program *p; 174 GLuint ic = 0; 175 176 if (st->drawpix.z_shader) { 177 return st->drawpix.z_shader->driver_shader; 178 } 179 180 /* 181 * Create shader now 182 */ 183 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 184 if (!p) 185 return NULL; 186 187 p->NumInstructions = 3; 188 189 p->Instructions = _mesa_alloc_instructions(p->NumInstructions); 190 if (!p->Instructions) { 191 ctx->Driver.DeleteProgram(ctx, p); 192 return NULL; 193 } 194 _mesa_init_instructions(p->Instructions, p->NumInstructions); 195 196 /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */ 197 p->Instructions[ic].Opcode = OPCODE_TEX; 198 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 199 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH; 200 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z; 201 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 202 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 203 p->Instructions[ic].TexSrcUnit = 0; 204 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; 205 ic++; 206 207 /* MOV result.color, fragment.color */ 208 p->Instructions[ic].Opcode = OPCODE_MOV; 209 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 210 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR; 211 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 212 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0; 213 ic++; 214 215 /* END; */ 216 p->Instructions[ic++].Opcode = OPCODE_END; 217 218 assert(ic == p->NumInstructions); 219 220 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0; 221 p->OutputsWritten = (1 << FRAG_RESULT_COLOR) | (1 << FRAG_RESULT_DEPTH); 222 p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ 223 224 st->drawpix.z_shader = (struct st_fragment_program *) p; 225 st_translate_fragment_program(st, st->drawpix.z_shader); 226 227 return st->drawpix.z_shader->driver_shader; 228} 229 230 231 232/** 233 * Create a simple vertex shader that just passes through the 234 * vertex position and texcoord (and optionally, color). 235 */ 236static void * 237make_passthrough_vertex_shader(struct st_context *st, 238 GLboolean passColor) 239{ 240 if (!st->drawpix.vert_shaders[passColor]) { 241 struct ureg_program *ureg = 242 ureg_create( TGSI_PROCESSOR_VERTEX ); 243 244 if (ureg == NULL) 245 return NULL; 246 247 /* MOV result.pos, vertex.pos; */ 248 ureg_MOV(ureg, 249 ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ), 250 ureg_DECL_vs_input( ureg, 0 )); 251 252 /* MOV result.texcoord0, vertex.attr[1]; */ 253 ureg_MOV(ureg, 254 ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), 255 ureg_DECL_vs_input( ureg, 1 )); 256 257 if (passColor) { 258 /* MOV result.color0, vertex.attr[2]; */ 259 ureg_MOV(ureg, 260 ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ), 261 ureg_DECL_vs_input( ureg, 2 )); 262 } 263 264 ureg_END( ureg ); 265 266 st->drawpix.vert_shaders[passColor] = 267 ureg_create_shader_and_destroy( ureg, st->pipe ); 268 } 269 270 return st->drawpix.vert_shaders[passColor]; 271} 272 273 274/** 275 * Return a texture internalFormat for drawing/copying an image 276 * of the given type. 277 */ 278static GLenum 279base_format(GLenum format) 280{ 281 switch (format) { 282 case GL_DEPTH_COMPONENT: 283 return GL_DEPTH_COMPONENT; 284 case GL_DEPTH_STENCIL: 285 return GL_DEPTH_STENCIL; 286 case GL_STENCIL_INDEX: 287 return GL_STENCIL_INDEX; 288 default: 289 return GL_RGBA; 290 } 291} 292 293 294/** 295 * Create a temporary texture to hold an image of the given size. 296 * If width, height are not POT and the driver only handles POT textures, 297 * allocate the next larger size of texture that is POT. 298 */ 299static struct pipe_resource * 300alloc_texture(struct st_context *st, GLsizei width, GLsizei height, 301 enum pipe_format texFormat) 302{ 303 struct pipe_context *pipe = st->pipe; 304 struct pipe_screen *screen = pipe->screen; 305 struct pipe_resource *pt; 306 int ptw, pth; 307 308 ptw = width; 309 pth = height; 310 311 /* Need to use POT texture? */ 312 if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { 313 int l2pt, maxSize; 314 315 l2pt = util_logbase2(width); 316 if (1 << l2pt != width) { 317 ptw = 1 << (l2pt + 1); 318 } 319 320 l2pt = util_logbase2(height); 321 if (1 << l2pt != height) { 322 pth = 1 << (l2pt + 1); 323 } 324 325 /* Check against maximum texture size */ 326 maxSize = 1 << (pipe->screen->get_param(pipe->screen, 327 PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 328 assert(ptw <= maxSize); 329 assert(pth <= maxSize); 330 } 331 332 pt = st_texture_create(st, PIPE_TEXTURE_2D, texFormat, 0, 333 ptw, pth, 1, PIPE_BIND_SAMPLER_VIEW); 334 335 return pt; 336} 337 338 339/** 340 * Make texture containing an image for glDrawPixels image. 341 * If 'pixels' is NULL, leave the texture image data undefined. 342 */ 343static struct pipe_resource * 344make_texture(struct st_context *st, 345 GLsizei width, GLsizei height, GLenum format, GLenum type, 346 const struct gl_pixelstore_attrib *unpack, 347 const GLvoid *pixels) 348{ 349 GLcontext *ctx = st->ctx; 350 struct pipe_context *pipe = st->pipe; 351 gl_format mformat; 352 struct pipe_resource *pt; 353 enum pipe_format pipeFormat; 354 GLuint cpp; 355 GLenum baseFormat; 356 357 baseFormat = base_format(format); 358 359 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type); 360 assert(mformat); 361 362 pipeFormat = st_mesa_format_to_pipe_format(mformat); 363 assert(pipeFormat); 364 cpp = util_format_get_blocksize(pipeFormat); 365 366 pixels = _mesa_map_pbo_source(ctx, unpack, pixels); 367 if (!pixels) 368 return NULL; 369 370 /* alloc temporary texture */ 371 pt = alloc_texture(st, width, height, pipeFormat); 372 if (!pt) { 373 _mesa_unmap_pbo_source(ctx, unpack); 374 return NULL; 375 } 376 377 { 378 struct pipe_transfer *transfer; 379 static const GLuint dstImageOffsets = 0; 380 GLboolean success; 381 GLubyte *dest; 382 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState; 383 384 /* we'll do pixel transfer in a fragment shader */ 385 ctx->_ImageTransferState = 0x0; 386 387 transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0, 388 PIPE_TRANSFER_WRITE, 0, 0, 389 width, height); 390 391 /* map texture transfer */ 392 dest = pipe_transfer_map(pipe, transfer); 393 394 395 /* Put image into texture transfer. 396 * Note that the image is actually going to be upside down in 397 * the texture. We deal with that with texcoords. 398 */ 399 success = _mesa_texstore(ctx, 2, /* dims */ 400 baseFormat, /* baseInternalFormat */ 401 mformat, /* gl_format */ 402 dest, /* dest */ 403 0, 0, 0, /* dstX/Y/Zoffset */ 404 transfer->stride, /* dstRowStride, bytes */ 405 &dstImageOffsets, /* dstImageOffsets */ 406 width, height, 1, /* size */ 407 format, type, /* src format/type */ 408 pixels, /* data source */ 409 unpack); 410 411 /* unmap */ 412 pipe_transfer_unmap(pipe, transfer); 413 pipe->transfer_destroy(pipe, transfer); 414 415 assert(success); 416 417 /* restore */ 418 ctx->_ImageTransferState = imageTransferStateSave; 419 } 420 421 _mesa_unmap_pbo_source(ctx, unpack); 422 423 return pt; 424} 425 426 427/** 428 * Draw quad with texcoords and optional color. 429 * Coords are gallium window coords with y=0=top. 430 * \param color may be null 431 * \param invertTex if true, flip texcoords vertically 432 */ 433static void 434draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, 435 GLfloat x1, GLfloat y1, const GLfloat *color, 436 GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord) 437{ 438 struct st_context *st = st_context(ctx); 439 struct pipe_context *pipe = st->pipe; 440 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */ 441 442 /* setup vertex data */ 443 { 444 const struct gl_framebuffer *fb = st->ctx->DrawBuffer; 445 const GLfloat fb_width = (GLfloat) fb->Width; 446 const GLfloat fb_height = (GLfloat) fb->Height; 447 const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f; 448 const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f; 449 const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f; 450 const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f; 451 const GLfloat sLeft = 0.0f, sRight = maxXcoord; 452 const GLfloat tTop = invertTex ? maxYcoord : 0.0f; 453 const GLfloat tBot = invertTex ? 0.0f : maxYcoord; 454 GLuint i; 455 456 /* upper-left */ 457 verts[0][0][0] = clip_x0; /* v[0].attr[0].x */ 458 verts[0][0][1] = clip_y0; /* v[0].attr[0].y */ 459 460 /* upper-right */ 461 verts[1][0][0] = clip_x1; 462 verts[1][0][1] = clip_y0; 463 464 /* lower-right */ 465 verts[2][0][0] = clip_x1; 466 verts[2][0][1] = clip_y1; 467 468 /* lower-left */ 469 verts[3][0][0] = clip_x0; 470 verts[3][0][1] = clip_y1; 471 472 verts[0][1][0] = sLeft; /* v[0].attr[1].S */ 473 verts[0][1][1] = tTop; /* v[0].attr[1].T */ 474 verts[1][1][0] = sRight; 475 verts[1][1][1] = tTop; 476 verts[2][1][0] = sRight; 477 verts[2][1][1] = tBot; 478 verts[3][1][0] = sLeft; 479 verts[3][1][1] = tBot; 480 481 /* same for all verts: */ 482 if (color) { 483 for (i = 0; i < 4; i++) { 484 verts[i][0][2] = z; /* v[i].attr[0].z */ 485 verts[i][0][3] = 1.0f; /* v[i].attr[0].w */ 486 verts[i][2][0] = color[0]; /* v[i].attr[2].r */ 487 verts[i][2][1] = color[1]; /* v[i].attr[2].g */ 488 verts[i][2][2] = color[2]; /* v[i].attr[2].b */ 489 verts[i][2][3] = color[3]; /* v[i].attr[2].a */ 490 verts[i][1][2] = 0.0f; /* v[i].attr[1].R */ 491 verts[i][1][3] = 1.0f; /* v[i].attr[1].Q */ 492 } 493 } 494 else { 495 for (i = 0; i < 4; i++) { 496 verts[i][0][2] = z; /*Z*/ 497 verts[i][0][3] = 1.0f; /*W*/ 498 verts[i][1][2] = 0.0f; /*R*/ 499 verts[i][1][3] = 1.0f; /*Q*/ 500 } 501 } 502 } 503 504 { 505 struct pipe_resource *buf; 506 507 /* allocate/load buffer object with vertex data */ 508 buf = pipe_buffer_create(pipe->screen, 509 PIPE_BIND_VERTEX_BUFFER, 510 sizeof(verts)); 511 st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts); 512 513 util_draw_vertex_buffer(pipe, buf, 0, 514 PIPE_PRIM_QUADS, 515 4, /* verts */ 516 3); /* attribs/vert */ 517 pipe_resource_reference(&buf, NULL); 518 } 519} 520 521 522 523static void 524draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, 525 GLsizei width, GLsizei height, 526 GLfloat zoomX, GLfloat zoomY, 527 struct pipe_sampler_view *sv, 528 void *driver_vp, 529 void *driver_fp, 530 const GLfloat *color, 531 GLboolean invertTex) 532{ 533 struct st_context *st = st_context(ctx); 534 struct pipe_context *pipe = st->pipe; 535 struct cso_context *cso = st->cso_context; 536 GLfloat x0, y0, x1, y1; 537 GLsizei maxSize; 538 539 /* limit checks */ 540 /* XXX if DrawPixels image is larger than max texture size, break 541 * it up into chunks. 542 */ 543 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 544 assert(width <= maxSize); 545 assert(height <= maxSize); 546 547 cso_save_rasterizer(cso); 548 cso_save_viewport(cso); 549 cso_save_samplers(cso); 550 cso_save_fragment_sampler_views(cso); 551 cso_save_fragment_shader(cso); 552 cso_save_vertex_shader(cso); 553 cso_save_vertex_elements(cso); 554 555 /* rasterizer state: just scissor */ 556 { 557 struct pipe_rasterizer_state rasterizer; 558 memset(&rasterizer, 0, sizeof(rasterizer)); 559 rasterizer.gl_rasterization_rules = 1; 560 rasterizer.scissor = ctx->Scissor.Enabled; 561 cso_set_rasterizer(cso, &rasterizer); 562 } 563 564 /* fragment shader state: TEX lookup program */ 565 cso_set_fragment_shader_handle(cso, driver_fp); 566 567 /* vertex shader state: position + texcoord pass-through */ 568 cso_set_vertex_shader_handle(cso, driver_vp); 569 570 571 /* texture sampling state: */ 572 { 573 struct pipe_sampler_state sampler; 574 memset(&sampler, 0, sizeof(sampler)); 575 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; 576 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; 577 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; 578 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 579 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 580 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 581 sampler.normalized_coords = 1; 582 583 cso_single_sampler(cso, 0, &sampler); 584 if (st->pixel_xfer.pixelmap_enabled) { 585 cso_single_sampler(cso, 1, &sampler); 586 } 587 cso_single_sampler_done(cso); 588 } 589 590 /* viewport state: viewport matching window dims */ 591 { 592 const float w = (float) ctx->DrawBuffer->Width; 593 const float h = (float) ctx->DrawBuffer->Height; 594 struct pipe_viewport_state vp; 595 vp.scale[0] = 0.5f * w; 596 vp.scale[1] = -0.5f * h; 597 vp.scale[2] = 0.5f; 598 vp.scale[3] = 1.0f; 599 vp.translate[0] = 0.5f * w; 600 vp.translate[1] = 0.5f * h; 601 vp.translate[2] = 0.5f; 602 vp.translate[3] = 0.0f; 603 cso_set_viewport(cso, &vp); 604 } 605 606 cso_set_vertex_elements(cso, 3, st->velems_util_draw); 607 608 /* texture state: */ 609 if (st->pixel_xfer.pixelmap_enabled) { 610 struct pipe_sampler_view *sampler_views[2]; 611 sampler_views[0] = sv; 612 sampler_views[1] = st->pixel_xfer.pixelmap_sampler_view; 613 cso_set_fragment_sampler_views(cso, 2, sampler_views); 614 } 615 else { 616 cso_set_fragment_sampler_views(cso, 1, &sv); 617 } 618 619 /* Compute Gallium window coords (y=0=top) with pixel zoom. 620 * Recall that these coords are transformed by the current 621 * vertex shader and viewport transformation. 622 */ 623 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) { 624 y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY); 625 invertTex = !invertTex; 626 } 627 628 x0 = (GLfloat) x; 629 x1 = x + width * ctx->Pixel.ZoomX; 630 y0 = (GLfloat) y; 631 y1 = y + height * ctx->Pixel.ZoomY; 632 633 /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */ 634 z = z * 2.0 - 1.0; 635 636 draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, 637 (GLfloat) width / sv->texture->width0, 638 (GLfloat) height / sv->texture->height0); 639 640 /* restore state */ 641 cso_restore_rasterizer(cso); 642 cso_restore_viewport(cso); 643 cso_restore_samplers(cso); 644 cso_restore_fragment_sampler_views(cso); 645 cso_restore_fragment_shader(cso); 646 cso_restore_vertex_shader(cso); 647 cso_restore_vertex_elements(cso); 648} 649 650 651static void 652draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, 653 GLsizei width, GLsizei height, GLenum format, GLenum type, 654 const struct gl_pixelstore_attrib *unpack, 655 const GLvoid *pixels) 656{ 657 struct st_context *st = st_context(ctx); 658 struct pipe_context *pipe = st->pipe; 659 struct st_renderbuffer *strb; 660 enum pipe_transfer_usage usage; 661 struct pipe_transfer *pt; 662 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 663 GLint skipPixels; 664 ubyte *stmap; 665 struct gl_pixelstore_attrib clippedUnpack = *unpack; 666 667 if (!zoom) { 668 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, 669 &clippedUnpack)) { 670 /* totally clipped */ 671 return; 672 } 673 } 674 675 strb = st_renderbuffer(ctx->DrawBuffer-> 676 Attachment[BUFFER_STENCIL].Renderbuffer); 677 678 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 679 y = ctx->DrawBuffer->Height - y - height; 680 } 681 682 if(format != GL_DEPTH_STENCIL && 683 util_format_get_component_bits(strb->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0) 684 usage = PIPE_TRANSFER_READ_WRITE; 685 else 686 usage = PIPE_TRANSFER_WRITE; 687 688 pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0, 689 usage, x, y, 690 width, height); 691 692 stmap = pipe_transfer_map(pipe, pt); 693 694 pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); 695 assert(pixels); 696 697 /* if width > MAX_WIDTH, have to process image in chunks */ 698 skipPixels = 0; 699 while (skipPixels < width) { 700 const GLint spanX = skipPixels; 701 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 702 GLint row; 703 for (row = 0; row < height; row++) { 704 GLubyte sValues[MAX_WIDTH]; 705 GLuint zValues[MAX_WIDTH]; 706 GLenum destType = GL_UNSIGNED_BYTE; 707 const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, 708 width, height, 709 format, type, 710 row, skipPixels); 711 _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues, 712 type, source, &clippedUnpack, 713 ctx->_ImageTransferState); 714 715 if (format == GL_DEPTH_STENCIL) { 716 _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, 717 (1 << 24) - 1, type, source, 718 &clippedUnpack); 719 } 720 721 if (zoom) { 722 _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " 723 "zoom not complete"); 724 } 725 726 { 727 GLint spanY; 728 729 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 730 spanY = height - row - 1; 731 } 732 else { 733 spanY = row; 734 } 735 736 /* now pack the stencil (and Z) values in the dest format */ 737 switch (pt->resource->format) { 738 case PIPE_FORMAT_S8_USCALED: 739 { 740 ubyte *dest = stmap + spanY * pt->stride + spanX; 741 assert(usage == PIPE_TRANSFER_WRITE); 742 memcpy(dest, sValues, spanWidth); 743 } 744 break; 745 case PIPE_FORMAT_Z24_UNORM_S8_USCALED: 746 if (format == GL_DEPTH_STENCIL) { 747 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 748 GLint k; 749 assert(usage == PIPE_TRANSFER_WRITE); 750 for (k = 0; k < spanWidth; k++) { 751 dest[k] = zValues[k] | (sValues[k] << 24); 752 } 753 } 754 else { 755 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 756 GLint k; 757 assert(usage == PIPE_TRANSFER_READ_WRITE); 758 for (k = 0; k < spanWidth; k++) { 759 dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); 760 } 761 } 762 break; 763 case PIPE_FORMAT_S8_USCALED_Z24_UNORM: 764 if (format == GL_DEPTH_STENCIL) { 765 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 766 GLint k; 767 assert(usage == PIPE_TRANSFER_WRITE); 768 for (k = 0; k < spanWidth; k++) { 769 dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); 770 } 771 } 772 else { 773 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 774 GLint k; 775 assert(usage == PIPE_TRANSFER_READ_WRITE); 776 for (k = 0; k < spanWidth; k++) { 777 dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); 778 } 779 } 780 break; 781 default: 782 assert(0); 783 } 784 } 785 } 786 skipPixels += spanWidth; 787 } 788 789 _mesa_unmap_pbo_source(ctx, &clippedUnpack); 790 791 /* unmap the stencil buffer */ 792 pipe_transfer_unmap(pipe, pt); 793 pipe->transfer_destroy(pipe, pt); 794} 795 796 797/** 798 * Called via ctx->Driver.DrawPixels() 799 */ 800static void 801st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, 802 GLenum format, GLenum type, 803 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) 804{ 805 void *driver_vp, *driver_fp; 806 struct st_context *st = st_context(ctx); 807 const GLfloat *color; 808 809 if (format == GL_STENCIL_INDEX || 810 format == GL_DEPTH_STENCIL) { 811 draw_stencil_pixels(ctx, x, y, width, height, format, type, 812 unpack, pixels); 813 return; 814 } 815 816 /* Mesa state should be up to date by now */ 817 assert(ctx->NewState == 0x0); 818 819 st_validate_state(st); 820 821 if (format == GL_DEPTH_COMPONENT) { 822 driver_fp = make_fragment_shader_z(st); 823 driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); 824 color = ctx->Current.RasterColor; 825 } 826 else { 827 driver_fp = combined_drawpix_fragment_program(ctx); 828 driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); 829 color = NULL; 830 } 831 832 /* draw with textured quad */ 833 { 834 struct pipe_resource *pt 835 = make_texture(st, width, height, format, type, unpack, pixels); 836 if (pt) { 837 struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt); 838 839 if (sv) { 840 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], 841 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 842 sv, 843 driver_vp, 844 driver_fp, 845 color, GL_FALSE); 846 pipe_sampler_view_reference(&sv, NULL); 847 } 848 pipe_resource_reference(&pt, NULL); 849 } 850 } 851} 852 853 854 855static void 856copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, 857 GLsizei width, GLsizei height, 858 GLint dstx, GLint dsty) 859{ 860 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); 861 struct pipe_context *pipe = st_context(ctx)->pipe; 862 enum pipe_transfer_usage usage; 863 struct pipe_transfer *ptDraw; 864 ubyte *drawMap; 865 ubyte *buffer; 866 int i; 867 868 buffer = malloc(width * height * sizeof(ubyte)); 869 if (!buffer) { 870 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)"); 871 return; 872 } 873 874 /* this will do stencil pixel transfer ops */ 875 st_read_stencil_pixels(ctx, srcx, srcy, width, height, 876 GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 877 &ctx->DefaultPacking, buffer); 878 879 if(util_format_get_component_bits(rbDraw->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0) 880 usage = PIPE_TRANSFER_READ_WRITE; 881 else 882 usage = PIPE_TRANSFER_WRITE; 883 884 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 885 dsty = rbDraw->Base.Height - dsty - height; 886 } 887 888 ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx), 889 rbDraw->texture, 0, 0, 0, 890 usage, dstx, dsty, 891 width, height); 892 893 assert(util_format_get_blockwidth(ptDraw->resource->format) == 1); 894 assert(util_format_get_blockheight(ptDraw->resource->format) == 1); 895 896 /* map the stencil buffer */ 897 drawMap = pipe_transfer_map(pipe, ptDraw); 898 899 /* draw */ 900 /* XXX PixelZoom not handled yet */ 901 for (i = 0; i < height; i++) { 902 ubyte *dst; 903 const ubyte *src; 904 int y; 905 906 y = i; 907 908 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 909 y = height - y - 1; 910 } 911 912 dst = drawMap + y * ptDraw->stride; 913 src = buffer + i * width; 914 915 switch (ptDraw->resource->format) { 916 case PIPE_FORMAT_Z24_UNORM_S8_USCALED: 917 { 918 uint *dst4 = (uint *) dst; 919 int j; 920 assert(usage == PIPE_TRANSFER_READ_WRITE); 921 for (j = 0; j < width; j++) { 922 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24); 923 dst4++; 924 } 925 } 926 break; 927 case PIPE_FORMAT_S8_USCALED_Z24_UNORM: 928 { 929 uint *dst4 = (uint *) dst; 930 int j; 931 assert(usage == PIPE_TRANSFER_READ_WRITE); 932 for (j = 0; j < width; j++) { 933 *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff); 934 dst4++; 935 } 936 } 937 break; 938 case PIPE_FORMAT_S8_USCALED: 939 assert(usage == PIPE_TRANSFER_WRITE); 940 memcpy(dst, src, width); 941 break; 942 default: 943 assert(0); 944 } 945 } 946 947 free(buffer); 948 949 /* unmap the stencil buffer */ 950 pipe_transfer_unmap(pipe, ptDraw); 951 pipe->transfer_destroy(pipe, ptDraw); 952} 953 954 955static void 956st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, 957 GLsizei width, GLsizei height, 958 GLint dstx, GLint dsty, GLenum type) 959{ 960 struct st_context *st = st_context(ctx); 961 struct pipe_context *pipe = st->pipe; 962 struct pipe_screen *screen = pipe->screen; 963 struct st_renderbuffer *rbRead; 964 void *driver_vp, *driver_fp; 965 struct pipe_resource *pt; 966 struct pipe_sampler_view *sv; 967 GLfloat *color; 968 enum pipe_format srcFormat, texFormat; 969 GLboolean invertTex = GL_FALSE; 970 GLint readX, readY, readW, readH; 971 GLuint sample_count; 972 struct gl_pixelstore_attrib pack = ctx->DefaultPacking; 973 974 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 975 976 st_validate_state(st); 977 978 if (type == GL_STENCIL) { 979 /* can't use texturing to do stencil */ 980 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); 981 return; 982 } 983 984 if (type == GL_COLOR) { 985 rbRead = st_get_color_read_renderbuffer(ctx); 986 color = NULL; 987 driver_fp = combined_drawpix_fragment_program(ctx); 988 driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); 989 } 990 else { 991 assert(type == GL_DEPTH); 992 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); 993 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 994 driver_fp = make_fragment_shader_z(st); 995 driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); 996 } 997 998 sample_count = rbRead->texture->nr_samples; 999 /* I believe this would be legal, presumably would need to do a resolve 1000 for color, and for depth/stencil spec says to just use one of the 1001 depth/stencil samples per pixel? Need some transfer clarifications. */ 1002 assert(sample_count < 2); 1003 1004 srcFormat = rbRead->texture->format; 1005 1006 if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, sample_count, 1007 PIPE_BIND_SAMPLER_VIEW, 0)) { 1008 texFormat = srcFormat; 1009 } 1010 else { 1011 /* srcFormat can't be used as a texture format */ 1012 if (type == GL_DEPTH) { 1013 texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, 1014 PIPE_TEXTURE_2D, sample_count, 1015 PIPE_BIND_DEPTH_STENCIL); 1016 assert(texFormat != PIPE_FORMAT_NONE); 1017 } 1018 else { 1019 /* default color format */ 1020 texFormat = st_choose_format(screen, GL_RGBA, PIPE_TEXTURE_2D, 1021 sample_count, PIPE_BIND_SAMPLER_VIEW); 1022 assert(texFormat != PIPE_FORMAT_NONE); 1023 } 1024 } 1025 1026 /* Invert src region if needed */ 1027 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1028 srcy = ctx->ReadBuffer->Height - srcy - height; 1029 invertTex = !invertTex; 1030 } 1031 1032 /* Clip the read region against the src buffer bounds. 1033 * We'll still allocate a temporary buffer/texture for the original 1034 * src region size but we'll only read the region which is on-screen. 1035 * This may mean that we draw garbage pixels into the dest region, but 1036 * that's expected. 1037 */ 1038 readX = srcx; 1039 readY = srcy; 1040 readW = width; 1041 readH = height; 1042 _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); 1043 readW = MAX2(0, readW); 1044 readH = MAX2(0, readH); 1045 1046 /* alloc temporary texture */ 1047 pt = alloc_texture(st, width, height, texFormat); 1048 if (!pt) 1049 return; 1050 1051 sv = st_create_texture_sampler_view(st->pipe, pt); 1052 if (!sv) { 1053 pipe_resource_reference(&pt, NULL); 1054 return; 1055 } 1056 1057 /* Make temporary texture which is a copy of the src region. 1058 */ 1059 if (srcFormat == texFormat) { 1060 struct pipe_subresource srcsub, dstsub; 1061 srcsub.face = 0; 1062 srcsub.level = 0; 1063 dstsub.face = 0; 1064 dstsub.level = 0; 1065 /* copy source framebuffer surface into mipmap/texture */ 1066 pipe->resource_copy_region(pipe, 1067 pt, /* dest tex */ 1068 dstsub, 1069 pack.SkipPixels, pack.SkipRows, 0, /* dest pos */ 1070 rbRead->texture, /* src tex */ 1071 srcsub, 1072 readX, readY, 0, readW, readH); /* src region */ 1073 1074 } 1075 else { 1076 /* CPU-based fallback/conversion */ 1077 struct pipe_transfer *ptRead = 1078 st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, 1079 PIPE_TRANSFER_READ, 1080 readX, readY, readW, readH); 1081 struct pipe_transfer *ptTex; 1082 enum pipe_transfer_usage transfer_usage; 1083 1084 if (ST_DEBUG & DEBUG_FALLBACK) 1085 debug_printf("%s: fallback processing\n", __FUNCTION__); 1086 1087 if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format)) 1088 transfer_usage = PIPE_TRANSFER_READ_WRITE; 1089 else 1090 transfer_usage = PIPE_TRANSFER_WRITE; 1091 1092 ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, 1093 0, 0, width, height); 1094 1095 /* copy image from ptRead surface to ptTex surface */ 1096 if (type == GL_COLOR) { 1097 /* alternate path using get/put_tile() */ 1098 GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); 1099 pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf); 1100 pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows, 1101 readW, readH, buf); 1102 free(buf); 1103 } 1104 else { 1105 /* GL_DEPTH */ 1106 GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); 1107 pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); 1108 pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows, 1109 readW, readH, buf); 1110 free(buf); 1111 } 1112 1113 pipe->transfer_destroy(pipe, ptRead); 1114 pipe->transfer_destroy(pipe, ptTex); 1115 } 1116 1117 /* OK, the texture 'pt' contains the src image/pixels. Now draw a 1118 * textured quad with that texture. 1119 */ 1120 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], 1121 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 1122 sv, 1123 driver_vp, 1124 driver_fp, 1125 color, invertTex); 1126 1127 pipe_resource_reference(&pt, NULL); 1128 pipe_sampler_view_reference(&sv, NULL); 1129} 1130 1131 1132 1133void st_init_drawpixels_functions(struct dd_function_table *functions) 1134{ 1135 functions->DrawPixels = st_DrawPixels; 1136 functions->CopyPixels = st_CopyPixels; 1137} 1138 1139 1140void 1141st_destroy_drawpix(struct st_context *st) 1142{ 1143 st_reference_fragprog(st, &st->drawpix.z_shader, NULL); 1144 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); 1145 if (st->drawpix.vert_shaders[0]) 1146 free(st->drawpix.vert_shaders[0]); 1147 if (st->drawpix.vert_shaders[1]) 1148 free(st->drawpix.vert_shaders[1]); 1149} 1150