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