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