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