st_cb_drawpixels.c revision fc3d564daeacdbd76b97de2ffc10e15931a18c7a
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/state.h" 39#include "shader/program.h" 40#include "shader/prog_parameter.h" 41#include "shader/prog_print.h" 42 43#include "st_context.h" 44#include "st_atom.h" 45#include "st_atom_constbuf.h" 46#include "st_draw.h" 47#include "st_program.h" 48#include "st_cb_drawpixels.h" 49#include "st_cb_readpixels.h" 50#include "st_cb_fbo.h" 51#include "st_cb_texture.h" 52#include "st_draw.h" 53#include "st_format.h" 54#include "st_mesa_to_tgsi.h" 55#include "st_texture.h" 56#include "st_inlines.h" 57 58#include "pipe/p_context.h" 59#include "pipe/p_defines.h" 60#include "pipe/p_inlines.h" 61#include "util/u_tile.h" 62#include "util/u_draw_quad.h" 63#include "util/u_math.h" 64#include "shader/prog_instruction.h" 65#include "cso_cache/cso_context.h" 66 67 68/** 69 * Check if the given program is: 70 * 0: MOVE result.color, fragment.color; 71 * 1: END; 72 */ 73static GLboolean 74is_passthrough_program(const struct gl_fragment_program *prog) 75{ 76 if (prog->Base.NumInstructions == 2) { 77 const struct prog_instruction *inst = prog->Base.Instructions; 78 if (inst[0].Opcode == OPCODE_MOV && 79 inst[1].Opcode == OPCODE_END && 80 inst[0].DstReg.File == PROGRAM_OUTPUT && 81 inst[0].DstReg.Index == FRAG_RESULT_COLOR && 82 inst[0].DstReg.WriteMask == WRITEMASK_XYZW && 83 inst[0].SrcReg[0].File == PROGRAM_INPUT && 84 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 && 85 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) { 86 return GL_TRUE; 87 } 88 } 89 return GL_FALSE; 90} 91 92 93 94/** 95 * Make fragment shader for glDraw/CopyPixels. This shader is made 96 * by combining the pixel transfer shader with the user-defined shader. 97 */ 98static struct st_fragment_program * 99combined_drawpix_fragment_program(GLcontext *ctx) 100{ 101 struct st_context *st = ctx->st; 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_program(ctx, &st->pixel_xfer.program->Base.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, NULL); 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; 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 */ 169static struct st_fragment_program * 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; 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, NULL); 226 227 return st->drawpix.z_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 struct st_vertex_program * 237st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) 238{ 239 GLcontext *ctx = st->ctx; 240 struct st_vertex_program *stvp; 241 struct gl_program *p; 242 GLuint ic = 0; 243 244 if (st->drawpix.vert_shaders[passColor]) 245 return st->drawpix.vert_shaders[passColor]; 246 247 /* 248 * Create shader now 249 */ 250 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); 251 if (!p) 252 return NULL; 253 254 if (passColor) 255 p->NumInstructions = 4; 256 else 257 p->NumInstructions = 3; 258 259 p->Instructions = _mesa_alloc_instructions(p->NumInstructions); 260 if (!p->Instructions) { 261 ctx->Driver.DeleteProgram(ctx, p); 262 return NULL; 263 } 264 _mesa_init_instructions(p->Instructions, p->NumInstructions); 265 /* MOV result.pos, vertex.pos; */ 266 p->Instructions[0].Opcode = OPCODE_MOV; 267 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT; 268 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS; 269 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT; 270 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS; 271 /* MOV result.texcoord0, vertex.texcoord0; */ 272 p->Instructions[1].Opcode = OPCODE_MOV; 273 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT; 274 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0; 275 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT; 276 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0; 277 ic = 2; 278 if (passColor) { 279 /* MOV result.color0, vertex.color0; */ 280 p->Instructions[ic].Opcode = OPCODE_MOV; 281 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 282 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0; 283 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 284 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0; 285 ic++; 286 } 287 288 /* END; */ 289 p->Instructions[ic].Opcode = OPCODE_END; 290 ic++; 291 292 assert(ic == p->NumInstructions); 293 294 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0; 295 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) | 296 (1 << VERT_RESULT_HPOS)); 297 if (passColor) { 298 p->InputsRead |= VERT_BIT_COLOR0; 299 p->OutputsWritten |= (1 << VERT_RESULT_COL0); 300 } 301 302 stvp = (struct st_vertex_program *) p; 303 st_translate_vertex_program(st, stvp, NULL, NULL, NULL); 304 305 st->drawpix.vert_shaders[passColor] = stvp; 306 307 return stvp; 308} 309 310 311static GLenum 312_mesa_base_format(GLenum format) 313{ 314 switch (format) { 315 case GL_DEPTH_COMPONENT: 316 return GL_DEPTH_COMPONENT; 317 case GL_DEPTH_STENCIL: 318 return GL_DEPTH_STENCIL; 319 case GL_STENCIL_INDEX: 320 return GL_STENCIL_INDEX; 321 default: 322 return GL_RGBA; 323 } 324} 325 326 327/** 328 * Make texture containing an image for glDrawPixels image. 329 * If 'pixels' is NULL, leave the texture image data undefined. 330 */ 331static struct pipe_texture * 332make_texture(struct st_context *st, 333 GLsizei width, GLsizei height, GLenum format, GLenum type, 334 const struct gl_pixelstore_attrib *unpack, 335 const GLvoid *pixels) 336{ 337 GLcontext *ctx = st->ctx; 338 struct pipe_context *pipe = st->pipe; 339 struct pipe_screen *screen = pipe->screen; 340 const struct gl_texture_format *mformat; 341 struct pipe_texture *pt; 342 enum pipe_format pipeFormat; 343 GLuint cpp; 344 GLenum baseFormat; 345 int ptw, pth; 346 347 baseFormat = _mesa_base_format(format); 348 349 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type); 350 assert(mformat); 351 352 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat); 353 assert(pipeFormat); 354 cpp = st_sizeof_format(pipeFormat); 355 356 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels); 357 if (!pixels) 358 return NULL; 359 360 /* Need to use POT texture? */ 361 ptw = width; 362 pth = height; 363 if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { 364 int l2pt, maxSize; 365 366 l2pt = util_logbase2(width); 367 if (1<<l2pt != width) { 368 ptw = 1<<(l2pt+1); 369 } 370 l2pt = util_logbase2(height); 371 if (1<<l2pt != height) { 372 pth = 1<<(l2pt+1); 373 } 374 375 /* Check against maximum texture size */ 376 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 377 assert(ptw <= maxSize); 378 assert(pth <= maxSize); 379 } 380 381 pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, ptw, pth, 1, 382 PIPE_TEXTURE_USAGE_SAMPLER); 383 if (!pt) { 384 _mesa_unmap_drawpix_pbo(ctx, unpack); 385 return NULL; 386 } 387 388 { 389 struct pipe_transfer *transfer; 390 static const GLuint dstImageOffsets = 0; 391 GLboolean success; 392 GLubyte *dest; 393 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState; 394 395 /* we'll do pixel transfer in a fragment shader */ 396 ctx->_ImageTransferState = 0x0; 397 398 transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0, 399 PIPE_TRANSFER_WRITE, 0, 0, 400 width, height); 401 402 /* map texture transfer */ 403 dest = screen->transfer_map(screen, transfer); 404 405 /* Put image into texture transfer. 406 * Note that the image is actually going to be upside down in 407 * the texture. We deal with that with texcoords. 408 */ 409 success = mformat->StoreImage(ctx, 2, /* dims */ 410 baseFormat, /* baseInternalFormat */ 411 mformat, /* gl_texture_format */ 412 dest, /* dest */ 413 0, 0, 0, /* dstX/Y/Zoffset */ 414 transfer->stride, /* dstRowStride, bytes */ 415 &dstImageOffsets, /* dstImageOffsets */ 416 width, height, 1, /* size */ 417 format, type, /* src format/type */ 418 pixels, /* data source */ 419 unpack); 420 421 /* unmap */ 422 screen->transfer_unmap(screen, transfer); 423 screen->tex_transfer_destroy(transfer); 424 425 assert(success); 426 427 /* restore */ 428 ctx->_ImageTransferState = imageTransferStateSave; 429 } 430 431 _mesa_unmap_drawpix_pbo(ctx, unpack); 432 433 return pt; 434} 435 436 437/** 438 * Draw quad with texcoords and optional color. 439 * Coords are window coords with y=0=bottom. 440 * \param color may be null 441 * \param invertTex if true, flip texcoords vertically 442 */ 443static void 444draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, 445 GLfloat x1, GLfloat y1, const GLfloat *color, 446 GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord) 447{ 448 struct st_context *st = ctx->st; 449 struct pipe_context *pipe = ctx->st->pipe; 450 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */ 451 452 /* setup vertex data */ 453 { 454 const struct gl_framebuffer *fb = st->ctx->DrawBuffer; 455 const GLfloat fb_width = (GLfloat) fb->Width; 456 const GLfloat fb_height = (GLfloat) fb->Height; 457 const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f; 458 const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f; 459 const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f; 460 const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f; 461 const GLfloat sLeft = 0.0f, sRight = maxXcoord; 462 const GLfloat tTop = invertTex ? maxYcoord : 0.0f; 463 const GLfloat tBot = invertTex ? 0.0f : maxYcoord; 464 GLuint tex, i; 465 466 /* upper-left */ 467 verts[0][0][0] = clip_x0; /* v[0].attr[0].x */ 468 verts[0][0][1] = clip_y0; /* v[0].attr[0].y */ 469 470 /* upper-right */ 471 verts[1][0][0] = clip_x1; 472 verts[1][0][1] = clip_y0; 473 474 /* lower-right */ 475 verts[2][0][0] = clip_x1; 476 verts[2][0][1] = clip_y1; 477 478 /* lower-left */ 479 verts[3][0][0] = clip_x0; 480 verts[3][0][1] = clip_y1; 481 482 tex = color ? 2 : 1; 483 verts[0][tex][0] = sLeft; /* v[0].attr[tex].s */ 484 verts[0][tex][1] = tTop; /* v[0].attr[tex].t */ 485 verts[1][tex][0] = sRight; 486 verts[1][tex][1] = tTop; 487 verts[2][tex][0] = sRight; 488 verts[2][tex][1] = tBot; 489 verts[3][tex][0] = sLeft; 490 verts[3][tex][1] = tBot; 491 492 /* same for all verts: */ 493 if (color) { 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][0] = color[0]; 498 verts[i][1][1] = color[1]; 499 verts[i][1][2] = color[2]; 500 verts[i][1][3] = color[3]; 501 verts[i][2][2] = 0.0f; /*R*/ 502 verts[i][2][3] = 1.0f; /*Q*/ 503 } 504 } 505 else { 506 for (i = 0; i < 4; i++) { 507 verts[i][0][2] = z; /*Z*/ 508 verts[i][0][3] = 1.0f; /*W*/ 509 verts[i][1][2] = 0.0f; /*R*/ 510 verts[i][1][3] = 1.0f; /*Q*/ 511 } 512 } 513 } 514 515 { 516 struct pipe_buffer *buf; 517 518 /* allocate/load buffer object with vertex data */ 519 buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX, 520 sizeof(verts)); 521 st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts); 522 523 util_draw_vertex_buffer(pipe, buf, 0, 524 PIPE_PRIM_QUADS, 525 4, /* verts */ 526 3); /* attribs/vert */ 527 pipe_buffer_reference(&buf, NULL); 528 } 529} 530 531 532 533static void 534draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, 535 GLsizei width, GLsizei height, 536 GLfloat zoomX, GLfloat zoomY, 537 struct pipe_texture *pt, 538 struct st_vertex_program *stvp, 539 struct st_fragment_program *stfp, 540 const GLfloat *color, 541 GLboolean invertTex) 542{ 543 struct st_context *st = ctx->st; 544 struct pipe_context *pipe = ctx->st->pipe; 545 struct cso_context *cso = ctx->st->cso_context; 546 GLfloat x0, y0, x1, y1; 547 GLsizei maxSize; 548 549 /* limit checks */ 550 /* XXX if DrawPixels image is larger than max texture size, break 551 * it up into chunks. 552 */ 553 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 554 assert(width <= maxSize); 555 assert(height <= maxSize); 556 557 cso_save_rasterizer(cso); 558 cso_save_viewport(cso); 559 cso_save_samplers(cso); 560 cso_save_sampler_textures(cso); 561 cso_save_fragment_shader(cso); 562 cso_save_vertex_shader(cso); 563 564 /* rasterizer state: just scissor */ 565 { 566 struct pipe_rasterizer_state rasterizer; 567 memset(&rasterizer, 0, sizeof(rasterizer)); 568 rasterizer.gl_rasterization_rules = 1; 569 rasterizer.scissor = ctx->Scissor.Enabled; 570 cso_set_rasterizer(cso, &rasterizer); 571 } 572 573 /* fragment shader state: TEX lookup program */ 574 cso_set_fragment_shader_handle(cso, stfp->driver_shader); 575 576 /* vertex shader state: position + texcoord pass-through */ 577 cso_set_vertex_shader_handle(cso, stvp->driver_shader); 578 579 580 /* texture sampling state: */ 581 { 582 struct pipe_sampler_state sampler; 583 memset(&sampler, 0, sizeof(sampler)); 584 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; 585 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; 586 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; 587 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 588 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 589 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 590 sampler.normalized_coords = 1; 591 592 cso_single_sampler(cso, 0, &sampler); 593 if (st->pixel_xfer.pixelmap_enabled) { 594 cso_single_sampler(cso, 1, &sampler); 595 } 596 cso_single_sampler_done(cso); 597 } 598 599 /* viewport state: viewport matching window dims */ 600 { 601 const float width = (float) ctx->DrawBuffer->Width; 602 const float height = (float) ctx->DrawBuffer->Height; 603 struct pipe_viewport_state vp; 604 vp.scale[0] = 0.5f * width; 605 vp.scale[1] = -0.5f * height; 606 vp.scale[2] = 1.0f; 607 vp.scale[3] = 1.0f; 608 vp.translate[0] = 0.5f * width; 609 vp.translate[1] = 0.5f * height; 610 vp.translate[2] = 0.0f; 611 vp.translate[3] = 0.0f; 612 cso_set_viewport(cso, &vp); 613 } 614 615 /* texture state: */ 616 if (st->pixel_xfer.pixelmap_enabled) { 617 struct pipe_texture *textures[2]; 618 textures[0] = pt; 619 textures[1] = st->pixel_xfer.pixelmap_texture; 620 pipe->set_sampler_textures(pipe, 2, textures); 621 } 622 else { 623 pipe->set_sampler_textures(pipe, 1, &pt); 624 } 625 626 /* Compute window coords (y=0=bottom) with pixel zoom. 627 * Recall that these coords are transformed by the current 628 * vertex shader and viewport transformation. 629 */ 630 x0 = (GLfloat) x; 631 x1 = x + width * ctx->Pixel.ZoomX; 632 y0 = (GLfloat) y; 633 y1 = y + height * ctx->Pixel.ZoomY; 634 635 draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, 636 (GLfloat) width / pt->width[0], 637 (GLfloat) height / pt->height[0]); 638 639 /* restore state */ 640 cso_restore_rasterizer(cso); 641 cso_restore_viewport(cso); 642 cso_restore_samplers(cso); 643 cso_restore_sampler_textures(cso); 644 cso_restore_fragment_shader(cso); 645 cso_restore_vertex_shader(cso); 646} 647 648 649static void 650draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, 651 GLsizei width, GLsizei height, GLenum format, GLenum type, 652 const struct gl_pixelstore_attrib *unpack, 653 const GLvoid *pixels) 654{ 655 struct st_context *st = ctx->st; 656 struct pipe_context *pipe = st->pipe; 657 struct pipe_screen *screen = pipe->screen; 658 struct st_renderbuffer *strb; 659 enum pipe_transfer_usage usage; 660 struct pipe_transfer *pt; 661 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 662 GLint skipPixels; 663 ubyte *stmap; 664 665 strb = st_renderbuffer(ctx->DrawBuffer-> 666 Attachment[BUFFER_STENCIL].Renderbuffer); 667 668 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 669 y = ctx->DrawBuffer->Height - y - height; 670 } 671 672 if(format != GL_DEPTH_STENCIL && 673 pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0) 674 usage = PIPE_TRANSFER_READ_WRITE; 675 else 676 usage = PIPE_TRANSFER_WRITE; 677 678 pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0, 679 usage, x, y, 680 width, height); 681 682 stmap = screen->transfer_map(screen, pt); 683 684 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels); 685 assert(pixels); 686 687 /* if width > MAX_WIDTH, have to process image in chunks */ 688 skipPixels = 0; 689 while (skipPixels < width) { 690 const GLint spanX = skipPixels; 691 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 692 GLint row; 693 for (row = 0; row < height; row++) { 694 GLubyte sValues[MAX_WIDTH]; 695 GLuint zValues[MAX_WIDTH]; 696 GLenum destType = GL_UNSIGNED_BYTE; 697 const GLvoid *source = _mesa_image_address2d(unpack, pixels, 698 width, height, 699 format, type, 700 row, skipPixels); 701 _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues, 702 type, source, unpack, 703 ctx->_ImageTransferState); 704 705 if (format == GL_DEPTH_STENCIL) { 706 _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, 707 (1 << 24) - 1, type, source, unpack); 708 } 709 710 if (zoom) { 711 _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with " 712 "zoom not complete"); 713 } 714 715 { 716 GLint spanY; 717 718 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 719 spanY = height - row - 1; 720 } 721 else { 722 spanY = row; 723 } 724 725 /* now pack the stencil (and Z) values in the dest format */ 726 switch (pt->format) { 727 case PIPE_FORMAT_S8_UNORM: 728 { 729 ubyte *dest = stmap + spanY * pt->stride + spanX; 730 assert(usage == PIPE_TRANSFER_WRITE); 731 memcpy(dest, sValues, spanWidth); 732 } 733 break; 734 case PIPE_FORMAT_S8Z24_UNORM: 735 if (format == GL_DEPTH_STENCIL) { 736 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 737 GLint k; 738 assert(usage == PIPE_TRANSFER_WRITE); 739 for (k = 0; k < spanWidth; k++) { 740 dest[k] = zValues[k] | (sValues[k] << 24); 741 } 742 } 743 else { 744 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 745 GLint k; 746 assert(usage == PIPE_TRANSFER_READ_WRITE); 747 for (k = 0; k < spanWidth; k++) { 748 dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); 749 } 750 } 751 break; 752 case PIPE_FORMAT_Z24S8_UNORM: 753 if (format == GL_DEPTH_STENCIL) { 754 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 755 GLint k; 756 assert(usage == PIPE_TRANSFER_WRITE); 757 for (k = 0; k < spanWidth; k++) { 758 dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); 759 } 760 } 761 else { 762 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); 763 GLint k; 764 assert(usage == PIPE_TRANSFER_READ_WRITE); 765 for (k = 0; k < spanWidth; k++) { 766 dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); 767 } 768 } 769 break; 770 default: 771 assert(0); 772 } 773 } 774 } 775 skipPixels += spanWidth; 776 } 777 778 _mesa_unmap_drawpix_pbo(ctx, unpack); 779 780 /* unmap the stencil buffer */ 781 screen->transfer_unmap(screen, pt); 782 screen->tex_transfer_destroy(pt); 783} 784 785 786/** 787 * Called via ctx->Driver.DrawPixels() 788 */ 789static void 790st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, 791 GLenum format, GLenum type, 792 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) 793{ 794 struct st_fragment_program *stfp; 795 struct st_vertex_program *stvp; 796 struct st_context *st = ctx->st; 797 struct pipe_surface *ps; 798 const GLfloat *color; 799 800 if (format == GL_STENCIL_INDEX || 801 format == GL_DEPTH_STENCIL) { 802 draw_stencil_pixels(ctx, x, y, width, height, format, type, 803 unpack, pixels); 804 return; 805 } 806 807 _mesa_set_vp_override( ctx, TRUE ); 808 _mesa_update_state( ctx ); 809 810 st_validate_state(st); 811 812 if (format == GL_DEPTH_COMPONENT) { 813 ps = st->state.framebuffer.zsbuf; 814 stfp = make_fragment_shader_z(ctx->st); 815 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); 816 color = ctx->Current.RasterColor; 817 } 818 else { 819 ps = st->state.framebuffer.cbufs[0]; 820 stfp = combined_drawpix_fragment_program(ctx); 821 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE); 822 color = NULL; 823 } 824 825 /* draw with textured quad */ 826 { 827 struct pipe_texture *pt 828 = make_texture(ctx->st, width, height, format, type, unpack, pixels); 829 if (pt) { 830 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], 831 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 832 pt, stvp, stfp, color, GL_FALSE); 833 pipe_texture_reference(&pt, NULL); 834 } 835 } 836 837 _mesa_set_vp_override( ctx, FALSE ); 838} 839 840 841 842static void 843copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, 844 GLsizei width, GLsizei height, 845 GLint dstx, GLint dsty) 846{ 847 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); 848 struct pipe_screen *screen = ctx->st->pipe->screen; 849 enum pipe_transfer_usage usage; 850 struct pipe_transfer *ptDraw; 851 ubyte *drawMap; 852 ubyte *buffer; 853 int i; 854 855 buffer = _mesa_malloc(width * height * sizeof(ubyte)); 856 if (!buffer) { 857 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)"); 858 return; 859 } 860 861 /* this will do stencil pixel transfer ops */ 862 st_read_stencil_pixels(ctx, srcx, srcy, width, height, 863 GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 864 &ctx->DefaultPacking, buffer); 865 866 if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0) 867 usage = PIPE_TRANSFER_READ_WRITE; 868 else 869 usage = PIPE_TRANSFER_WRITE; 870 871 ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx), 872 rbDraw->texture, 0, 0, 0, 873 usage, dstx, dsty, 874 width, height); 875 876 assert(ptDraw->block.width == 1); 877 assert(ptDraw->block.height == 1); 878 879 /* map the stencil buffer */ 880 drawMap = screen->transfer_map(screen, ptDraw); 881 882 /* draw */ 883 /* XXX PixelZoom not handled yet */ 884 for (i = 0; i < height; i++) { 885 ubyte *dst; 886 const ubyte *src; 887 int y; 888 889 y = i; 890 891 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 892 y = height - y - 1; 893 } 894 895 dst = drawMap + y * ptDraw->stride; 896 src = buffer + i * width; 897 898 switch (ptDraw->format) { 899 case PIPE_FORMAT_S8Z24_UNORM: 900 { 901 uint *dst4 = (uint *) dst; 902 int j; 903 assert(usage == PIPE_TRANSFER_READ_WRITE); 904 for (j = 0; j < width; j++) { 905 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24); 906 dst4++; 907 } 908 } 909 break; 910 case PIPE_FORMAT_Z24S8_UNORM: 911 { 912 uint *dst4 = (uint *) dst; 913 int j; 914 assert(usage == PIPE_TRANSFER_READ_WRITE); 915 for (j = 0; j < width; j++) { 916 *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff); 917 dst4++; 918 } 919 } 920 break; 921 case PIPE_FORMAT_S8_UNORM: 922 assert(usage == PIPE_TRANSFER_WRITE); 923 memcpy(dst, src, width); 924 break; 925 default: 926 assert(0); 927 } 928 } 929 930 _mesa_free(buffer); 931 932 /* unmap the stencil buffer */ 933 screen->transfer_unmap(screen, ptDraw); 934 screen->tex_transfer_destroy(ptDraw); 935} 936 937 938static void 939st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, 940 GLsizei width, GLsizei height, 941 GLint dstx, GLint dsty, GLenum type) 942{ 943 struct st_context *st = ctx->st; 944 struct pipe_context *pipe = st->pipe; 945 struct pipe_screen *screen = pipe->screen; 946 struct st_renderbuffer *rbRead; 947 struct st_vertex_program *stvp; 948 struct st_fragment_program *stfp; 949 struct pipe_texture *pt; 950 GLfloat *color; 951 enum pipe_format srcFormat, texFormat; 952 int ptw, pth; 953 954 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 955 956 st_validate_state(st); 957 958 if (srcx < 0) { 959 width -= -srcx; 960 dstx += -srcx; 961 srcx = 0; 962 } 963 964 if (srcy < 0) { 965 height -= -srcy; 966 dsty += -srcy; 967 srcy = 0; 968 } 969 970 if (dstx < 0) { 971 width -= -dstx; 972 srcx += -dstx; 973 dstx = 0; 974 } 975 976 if (dsty < 0) { 977 height -= -dsty; 978 srcy += -dsty; 979 dsty = 0; 980 } 981 982 if (width < 0 || height < 0) 983 return; 984 985 986 if (type == GL_STENCIL) { 987 /* can't use texturing to do stencil */ 988 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); 989 return; 990 } 991 992 if (type == GL_COLOR) { 993 rbRead = st_get_color_read_renderbuffer(ctx); 994 color = NULL; 995 stfp = combined_drawpix_fragment_program(ctx); 996 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE); 997 } 998 else { 999 assert(type == GL_DEPTH); 1000 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); 1001 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 1002 stfp = make_fragment_shader_z(ctx->st); 1003 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); 1004 } 1005 1006 srcFormat = rbRead->texture->format; 1007 1008 if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D, 1009 PIPE_TEXTURE_USAGE_SAMPLER, 0)) { 1010 texFormat = srcFormat; 1011 } 1012 else { 1013 /* srcFormat can't be used as a texture format */ 1014 if (type == GL_DEPTH) { 1015 texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, 1016 PIPE_TEXTURE_USAGE_DEPTH_STENCIL); 1017 assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ 1018 } 1019 else { 1020 /* default color format */ 1021 texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, 1022 PIPE_TEXTURE_USAGE_SAMPLER); 1023 assert(texFormat != PIPE_FORMAT_NONE); 1024 } 1025 } 1026 1027 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 1028 srcy = ctx->DrawBuffer->Height - srcy - height; 1029 1030 if (srcy < 0) { 1031 height -= -srcy; 1032 srcy = 0; 1033 } 1034 1035 if (height < 0) 1036 return; 1037 } 1038 1039 /* Need to use POT texture? */ 1040 ptw = width; 1041 pth = height; 1042 if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) { 1043 int l2pt, maxSize; 1044 1045 l2pt = util_logbase2(width); 1046 if (1<<l2pt != width) { 1047 ptw = 1<<(l2pt+1); 1048 } 1049 l2pt = util_logbase2(height); 1050 if (1<<l2pt != height) { 1051 pth = 1<<(l2pt+1); 1052 } 1053 1054 /* Check against maximum texture size */ 1055 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 1056 assert(ptw <= maxSize); 1057 assert(pth <= maxSize); 1058 } 1059 1060 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, 1061 ptw, pth, 1, 1062 PIPE_TEXTURE_USAGE_SAMPLER); 1063 if (!pt) 1064 return; 1065 1066 1067 if (srcFormat == texFormat) { 1068 /* copy source framebuffer surface into mipmap/texture */ 1069 struct pipe_surface *psRead = screen->get_tex_surface(screen, 1070 rbRead->texture, 0, 0, 0, 1071 PIPE_BUFFER_USAGE_GPU_READ); 1072 struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, 1073 PIPE_BUFFER_USAGE_GPU_WRITE ); 1074 pipe->surface_copy(pipe, 1075 psTex, /* dest */ 1076 0, 0, /* destx/y */ 1077 psRead, 1078 srcx, srcy, width, height); 1079 pipe_surface_reference(&psRead, NULL); 1080 pipe_surface_reference(&psTex, NULL); 1081 } 1082 else { 1083 /* CPU-based fallback/conversion */ 1084 struct pipe_transfer *ptRead = 1085 st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, 1086 PIPE_TRANSFER_READ, srcx, srcy, width, 1087 height); 1088 struct pipe_transfer *ptTex; 1089 enum pipe_transfer_usage transfer_usage; 1090 1091 if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format)) 1092 transfer_usage = PIPE_TRANSFER_READ_WRITE; 1093 else 1094 transfer_usage = PIPE_TRANSFER_WRITE; 1095 1096 ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, 1097 0, 0, width, height); 1098 1099 if (type == GL_COLOR) { 1100 /* alternate path using get/put_tile() */ 1101 GLfloat *buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); 1102 1103 pipe_get_tile_rgba(ptRead, 0, 0, width, height, buf); 1104 pipe_put_tile_rgba(ptTex, 0, 0, width, height, buf); 1105 1106 _mesa_free(buf); 1107 } 1108 else { 1109 /* GL_DEPTH */ 1110 GLuint *buf = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint)); 1111 pipe_get_tile_z(ptRead, 0, 0, width, height, buf); 1112 pipe_put_tile_z(ptTex, 0, 0, width, height, buf); 1113 _mesa_free(buf); 1114 } 1115 1116 screen->tex_transfer_destroy(ptRead); 1117 screen->tex_transfer_destroy(ptTex); 1118 } 1119 1120 /* draw textured quad */ 1121 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], 1122 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 1123 pt, stvp, stfp, color, GL_TRUE); 1124 1125 pipe_texture_reference(&pt, NULL); 1126} 1127 1128 1129 1130void st_init_drawpixels_functions(struct dd_function_table *functions) 1131{ 1132 functions->DrawPixels = st_DrawPixels; 1133 functions->CopyPixels = st_CopyPixels; 1134} 1135 1136 1137void 1138st_destroy_drawpix(struct st_context *st) 1139{ 1140 st_reference_fragprog(st, &st->drawpix.z_shader, NULL); 1141 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); 1142 st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL); 1143 st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL); 1144} 1145