st_cb_drawpixels.c revision 4b822a101680532ce6df52904af91194b78a16ba
1238b6a9d33bf87e23f86866885394cd453a06495Rafael Espindola/************************************************************************** 2238b6a9d33bf87e23f86866885394cd453a06495Rafael Espindola * 391338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 491338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * All Rights Reserved. 591338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * 691338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * Permission is hereby granted, free of charge, to any person obtaining a 791338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * copy of this software and associated documentation files (the 891338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * "Software"), to deal in the Software without restriction, including 991338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * without limitation the rights to use, copy, modify, merge, publish, 1091338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * distribute, sub license, and/or sell copies of the Software, and to 1191338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * permit persons to whom the Software is furnished to do so, subject to 1291338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * the following conditions: 1391338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * 1491338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * The above copyright notice and this permission notice (including the 1591338cf4129cfdb85af7e9ef396ab09621da10ecAkira Hatanaka * 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 "shader/program.h" 39#include "shader/prog_parameter.h" 40#include "shader/prog_print.h" 41 42#include "st_context.h" 43#include "st_atom.h" 44#include "st_atom_constbuf.h" 45#include "st_draw.h" 46#include "st_program.h" 47#include "st_cb_drawpixels.h" 48#include "st_cb_readpixels.h" 49#include "st_cb_fbo.h" 50#include "st_cb_texture.h" 51#include "st_draw.h" 52#include "st_format.h" 53#include "st_mesa_to_tgsi.h" 54#include "st_texture.h" 55#include "pipe/p_context.h" 56#include "pipe/p_defines.h" 57#include "pipe/p_inlines.h" 58#include "pipe/p_winsys.h" 59#include "util/p_tile.h" 60#include "util/u_draw_quad.h" 61#include "shader/prog_instruction.h" 62#include "cso_cache/cso_context.h" 63 64 65/** 66 * Check if the given program is: 67 * 0: MOVE result.color, fragment.color; 68 * 1: END; 69 */ 70static GLboolean 71is_passthrough_program(const struct gl_fragment_program *prog) 72{ 73 if (prog->Base.NumInstructions == 2) { 74 const struct prog_instruction *inst = prog->Base.Instructions; 75 if (inst[0].Opcode == OPCODE_MOV && 76 inst[1].Opcode == OPCODE_END && 77 inst[0].DstReg.File == PROGRAM_OUTPUT && 78 inst[0].DstReg.Index == FRAG_RESULT_COLR && 79 inst[0].DstReg.WriteMask == WRITEMASK_XYZW && 80 inst[0].SrcReg[0].File == PROGRAM_INPUT && 81 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 && 82 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) { 83 return GL_TRUE; 84 } 85 } 86 return GL_FALSE; 87} 88 89 90 91/** 92 * Make fragment shader for glDraw/CopyPixels. This shader is made 93 * by combining the pixel transfer shader with the user-defined shader. 94 */ 95static struct st_fragment_program * 96combined_drawpix_fragment_program(GLcontext *ctx) 97{ 98 struct st_context *st = ctx->st; 99 struct st_fragment_program *stfp; 100 101 if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn 102 && st->fp->serialNo == st->pixel_xfer.user_prog_sn) { 103 /* the pixel tranfer program has not changed and the user-defined 104 * program has not changed, so re-use the combined program. 105 */ 106 stfp = st->pixel_xfer.combined_prog; 107 } 108 else { 109 /* Concatenate the pixel transfer program with the current user- 110 * defined program. 111 */ 112 if (is_passthrough_program(&st->fp->Base)) { 113 stfp = (struct st_fragment_program *) 114 _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base); 115 } 116 else { 117#if 0 118 printf("Base program:\n"); 119 _mesa_print_program(&st->fp->Base.Base); 120 printf("DrawPix program:\n"); 121 _mesa_print_program(&st->pixel_xfer.program->Base.Base); 122#endif 123 stfp = (struct st_fragment_program *) 124 _mesa_combine_programs(ctx, 125 &st->pixel_xfer.program->Base.Base, 126 &st->fp->Base.Base); 127 } 128 129#if 0 130 { 131 struct gl_program *p = &stfp->Base.Base; 132 printf("Combined DrawPixels program:\n"); 133 _mesa_print_program(p); 134 printf("InputsRead: 0x%x\n", p->InputsRead); 135 printf("OutputsWritten: 0x%x\n", p->OutputsWritten); 136 _mesa_print_parameter_list(p->Parameters); 137 } 138#endif 139 140 /* translate to TGSI tokens */ 141 st_translate_fragment_program(st, stfp, NULL); 142 143 /* save new program, update serial numbers */ 144 st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo; 145 st->pixel_xfer.user_prog_sn = st->fp->serialNo; 146 st->pixel_xfer.combined_prog_sn = stfp->serialNo; 147 st->pixel_xfer.combined_prog = stfp; 148 } 149 150 /* Ideally we'd have updated the pipe constants during the normal 151 * st/atom mechanism. But we can't since this is specific to glDrawPixels. 152 */ 153 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); 154 155 return stfp; 156} 157 158 159/** 160 * Create fragment shader that does a TEX() instruction to get a Z 161 * value, then writes to FRAG_RESULT_DEPR. 162 * Pass fragment color through as-is. 163 */ 164static struct st_fragment_program * 165make_fragment_shader_z(struct st_context *st) 166{ 167 GLcontext *ctx = st->ctx; 168 /* only make programs once and re-use */ 169 static struct st_fragment_program *stfp = NULL; 170 struct gl_program *p; 171 GLuint ic = 0; 172 173 if (stfp) 174 return stfp; 175 176 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); 177 if (!p) 178 return NULL; 179 180 p->NumInstructions = 3; 181 182 p->Instructions = _mesa_alloc_instructions(p->NumInstructions); 183 if (!p->Instructions) { 184 ctx->Driver.DeleteProgram(ctx, p); 185 return NULL; 186 } 187 _mesa_init_instructions(p->Instructions, p->NumInstructions); 188 189 /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */ 190 p->Instructions[ic].Opcode = OPCODE_TEX; 191 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 192 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR; 193 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z; 194 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 195 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0; 196 p->Instructions[ic].TexSrcUnit = 0; 197 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX; 198 ic++; 199 200 /* MOV result.color, fragment.color */ 201 p->Instructions[ic].Opcode = OPCODE_MOV; 202 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 203 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR; 204 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 205 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0; 206 ic++; 207 208 /* END; */ 209 p->Instructions[ic++].Opcode = OPCODE_END; 210 211 assert(ic == p->NumInstructions); 212 213 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0; 214 p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR); 215 p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ 216 217 stfp = (struct st_fragment_program *) p; 218 st_translate_fragment_program(st, stfp, NULL); 219 220 return stfp; 221} 222 223 224 225/** 226 * Create a simple vertex shader that just passes through the 227 * vertex position and texcoord (and optionally, color). 228 */ 229static struct st_vertex_program * 230st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) 231{ 232 /* only make programs once and re-use */ 233 static struct st_vertex_program *progs[2] = { NULL, NULL }; 234 GLcontext *ctx = st->ctx; 235 struct st_vertex_program *stvp; 236 struct gl_program *p; 237 GLuint ic = 0; 238 239 if (progs[passColor]) 240 return progs[passColor]; 241 242 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); 243 if (!p) 244 return NULL; 245 246 if (passColor) 247 p->NumInstructions = 4; 248 else 249 p->NumInstructions = 3; 250 251 p->Instructions = _mesa_alloc_instructions(p->NumInstructions); 252 if (!p->Instructions) { 253 ctx->Driver.DeleteProgram(ctx, p); 254 return NULL; 255 } 256 _mesa_init_instructions(p->Instructions, p->NumInstructions); 257 /* MOV result.pos, vertex.pos; */ 258 p->Instructions[0].Opcode = OPCODE_MOV; 259 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT; 260 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS; 261 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT; 262 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS; 263 /* MOV result.texcoord0, vertex.texcoord0; */ 264 p->Instructions[1].Opcode = OPCODE_MOV; 265 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT; 266 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0; 267 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT; 268 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0; 269 ic = 2; 270 if (passColor) { 271 /* MOV result.color0, vertex.color0; */ 272 p->Instructions[ic].Opcode = OPCODE_MOV; 273 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; 274 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0; 275 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; 276 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0; 277 ic++; 278 } 279 280 /* END; */ 281 p->Instructions[ic].Opcode = OPCODE_END; 282 ic++; 283 284 assert(ic == p->NumInstructions); 285 286 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0; 287 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) | 288 (1 << VERT_RESULT_HPOS)); 289 if (passColor) { 290 p->InputsRead |= VERT_BIT_COLOR0; 291 p->OutputsWritten |= (1 << VERT_RESULT_COL0); 292 } 293 294 stvp = (struct st_vertex_program *) p; 295 st_translate_vertex_program(st, stvp, NULL); 296 297 progs[passColor] = stvp; 298 299 return stvp; 300} 301 302 303static GLenum 304_mesa_base_format(GLenum format) 305{ 306 switch (format) { 307 case GL_DEPTH_COMPONENT: 308 return GL_DEPTH_COMPONENT; 309 case GL_STENCIL_INDEX: 310 return GL_STENCIL_INDEX; 311 default: 312 return GL_RGBA; 313 } 314} 315 316 317/** 318 * Make texture containing an image for glDrawPixels image. 319 * If 'pixels' is NULL, leave the texture image data undefined. 320 */ 321static struct pipe_texture * 322make_texture(struct st_context *st, 323 GLsizei width, GLsizei height, GLenum format, GLenum type, 324 const struct gl_pixelstore_attrib *unpack, 325 const GLvoid *pixels) 326{ 327 GLcontext *ctx = st->ctx; 328 struct pipe_context *pipe = st->pipe; 329 struct pipe_screen *screen = pipe->screen; 330 const struct gl_texture_format *mformat; 331 struct pipe_texture *pt; 332 enum pipe_format pipeFormat; 333 GLuint cpp; 334 GLenum baseFormat; 335 336 baseFormat = _mesa_base_format(format); 337 338 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type); 339 assert(mformat); 340 341 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat); 342 assert(pipeFormat); 343 cpp = st_sizeof_format(pipeFormat); 344 345 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels); 346 if (!pixels) 347 return NULL; 348 349 pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, 350 1, 0); 351 if (!pt) { 352 _mesa_unmap_drapix_pbo(ctx, unpack); 353 return NULL; 354 } 355 356 { 357 struct pipe_surface *surface; 358 static const GLuint dstImageOffsets = 0; 359 GLboolean success; 360 GLubyte *dest; 361 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState; 362 363 /* we'll do pixel transfer in a fragment shader */ 364 ctx->_ImageTransferState = 0x0; 365 366 surface = screen->get_tex_surface(screen, pt, 0, 0, 0); 367 368 /* map texture surface */ 369 dest = pipe_surface_map(surface); 370 371 /* Put image into texture surface. 372 * Note that the image is actually going to be upside down in 373 * the texture. We deal with that with texcoords. 374 */ 375 success = mformat->StoreImage(ctx, 2, /* dims */ 376 baseFormat, /* baseInternalFormat */ 377 mformat, /* gl_texture_format */ 378 dest, /* dest */ 379 0, 0, 0, /* dstX/Y/Zoffset */ 380 surface->pitch * cpp, /* dstRowStride, bytes */ 381 &dstImageOffsets, /* dstImageOffsets */ 382 width, height, 1, /* size */ 383 format, type, /* src format/type */ 384 pixels, /* data source */ 385 unpack); 386 387 /* unmap */ 388 pipe_surface_unmap(surface); 389 pipe_surface_reference(&surface, NULL); 390 pipe->texture_update(pipe, pt, 0, 0x1); 391 392 assert(success); 393 394 /* restore */ 395 ctx->_ImageTransferState = imageTransferStateSave; 396 } 397 398 _mesa_unmap_drapix_pbo(ctx, unpack); 399 400 return pt; 401} 402 403 404/** 405 * Draw textured quad. 406 * Coords are window coords with y=0=bottom. 407 */ 408static void 409draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, 410 GLfloat x1, GLfloat y1, GLboolean invertTex) 411{ 412 GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */ 413 GLuint i; 414 GLfloat sLeft = 0.0, sRight = 1.0; 415 GLfloat tTop = invertTex, tBot = 1.0 - tTop; 416 417 /* upper-left */ 418 verts[0][0][0] = x0; /* attr[0].x */ 419 verts[0][0][1] = y0; /* attr[0].y */ 420 verts[0][1][0] = sLeft; /* attr[1].s */ 421 verts[0][1][1] = tTop; /* attr[1].t */ 422 423 /* upper-right */ 424 verts[1][0][0] = x1; 425 verts[1][0][1] = y0; 426 verts[1][1][0] = sRight; 427 verts[1][1][1] = tTop; 428 429 /* lower-right */ 430 verts[2][0][0] = x1; 431 verts[2][0][1] = y1; 432 verts[2][1][0] = sRight; 433 verts[2][1][1] = tBot; 434 435 /* lower-left */ 436 verts[3][0][0] = x0; 437 verts[3][0][1] = y1; 438 verts[3][1][0] = sLeft; 439 verts[3][1][1] = tBot; 440 441 /* same for all verts: */ 442 for (i = 0; i < 4; i++) { 443 verts[i][0][2] = z; /*Z*/ 444 verts[i][0][3] = 1.0; /*W*/ 445 verts[i][1][2] = 0.0; /*R*/ 446 verts[i][1][3] = 1.0; /*Q*/ 447 } 448 449 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 2, GL_FALSE); 450} 451 452 453static void 454draw_quad_colored(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, 455 GLfloat x1, GLfloat y1, const GLfloat *color, 456 GLboolean invertTex) 457{ 458 GLfloat bias = ctx->st->bitmap_texcoord_bias; 459 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */ 460 GLuint i; 461 GLfloat xBias = bias / (x1-x0); 462 GLfloat yBias = bias / (y1-y0); 463 GLfloat sLeft = 0.0 + xBias, sRight = 1.0 + xBias; 464 GLfloat tTop = invertTex - yBias, tBot = 1.0 - tTop - yBias; 465 466 /* upper-left */ 467 verts[0][0][0] = x0; /* attr[0].x */ 468 verts[0][0][1] = y0; /* attr[0].y */ 469 verts[0][2][0] = sLeft; /* attr[2].s */ 470 verts[0][2][1] = tTop; /* attr[2].t */ 471 472 /* upper-right */ 473 verts[1][0][0] = x1; 474 verts[1][0][1] = y0; 475 verts[1][2][0] = sRight; 476 verts[1][2][1] = tTop; 477 478 /* lower-right */ 479 verts[2][0][0] = x1; 480 verts[2][0][1] = y1; 481 verts[2][2][0] = sRight; 482 verts[2][2][1] = tBot; 483 484 /* lower-left */ 485 verts[3][0][0] = x0; 486 verts[3][0][1] = y1; 487 verts[3][2][0] = sLeft; 488 verts[3][2][1] = tBot; 489 490 /* same for all verts: */ 491 for (i = 0; i < 4; i++) { 492 verts[i][0][2] = z; /*Z*/ 493 verts[i][0][3] = 1.0; /*W*/ 494 verts[i][1][0] = color[0]; 495 verts[i][1][1] = color[1]; 496 verts[i][1][2] = color[2]; 497 verts[i][1][3] = color[3]; 498 verts[i][2][2] = 0.0; /*R*/ 499 verts[i][2][3] = 1.0; /*Q*/ 500 } 501 502 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 3, GL_FALSE); 503} 504 505 506 507static void 508draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, 509 GLsizei width, GLsizei height, 510 GLfloat zoomX, GLfloat zoomY, 511 struct pipe_texture *pt, 512 struct st_vertex_program *stvp, 513 struct st_fragment_program *stfp, 514 const GLfloat *color, 515 GLboolean invertTex) 516{ 517 struct st_context *st = ctx->st; 518 struct pipe_context *pipe = ctx->st->pipe; 519 struct cso_context *cso = ctx->st->cso_context; 520 GLfloat x0, y0, x1, y1; 521 GLuint maxSize; 522 523 /* limit checks */ 524 /* XXX if DrawPixels image is larger than max texture size, break 525 * it up into chunks. 526 */ 527 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); 528 assert(width <= maxSize); 529 assert(height <= maxSize); 530 531 cso_save_rasterizer(cso); 532 cso_save_viewport(cso); 533 cso_save_samplers(cso); 534 cso_save_sampler_textures(cso); 535 536 /* rasterizer state: just scissor */ 537 { 538 struct pipe_rasterizer_state rasterizer; 539 memset(&rasterizer, 0, sizeof(rasterizer)); 540 rasterizer.gl_rasterization_rules = 1; 541 rasterizer.scissor = ctx->Scissor.Enabled; 542 cso_set_rasterizer(cso, &rasterizer); 543 } 544 545 /* fragment shader state: TEX lookup program */ 546 pipe->bind_fs_state(pipe, stfp->driver_shader); 547 548 /* vertex shader state: position + texcoord pass-through */ 549 pipe->bind_vs_state(pipe, stvp->driver_shader); 550 551 552 /* texture sampling state: */ 553 { 554 struct pipe_sampler_state sampler; 555 memset(&sampler, 0, sizeof(sampler)); 556 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; 557 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; 558 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP; 559 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 560 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 561 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 562 sampler.normalized_coords = 1; 563 564 cso_single_sampler(cso, 0, &sampler); 565 if (st->pixel_xfer.pixelmap_enabled) { 566 cso_single_sampler(cso, 1, &sampler); 567 } 568 cso_single_sampler_done(cso); 569 } 570 571 /* viewport state: viewport matching window dims */ 572 { 573 const float width = ctx->DrawBuffer->Width; 574 const float height = ctx->DrawBuffer->Height; 575 struct pipe_viewport_state vp; 576 vp.scale[0] = 0.5 * width; 577 vp.scale[1] = -0.5 * height; 578 vp.scale[2] = 1.0; 579 vp.scale[3] = 1.0; 580 vp.translate[0] = 0.5 * width; 581 vp.translate[1] = 0.5 * height; 582 vp.translate[2] = 0.0; 583 vp.translate[3] = 0.0; 584 cso_set_viewport(cso, &vp); 585 } 586 587 /* texture state: */ 588 if (st->pixel_xfer.pixelmap_enabled) { 589 struct pipe_texture *textures[2]; 590 textures[0] = pt; 591 textures[1] = st->pixel_xfer.pixelmap_texture; 592 pipe->set_sampler_textures(pipe, 2, textures); 593 } 594 else { 595 pipe->set_sampler_textures(pipe, 1, &pt); 596 } 597 598 /* Compute window coords (y=0=bottom) with pixel zoom. 599 * Recall that these coords are transformed by the current 600 * vertex shader and viewport transformation. 601 */ 602 x0 = x; 603 x1 = x + width * ctx->Pixel.ZoomX; 604 y0 = y; 605 y1 = y + height * ctx->Pixel.ZoomY; 606 607 /* draw textured quad */ 608 if (color) 609 draw_quad_colored(ctx, x0, y0, z, x1, y1, color, invertTex); 610 else 611 draw_quad(ctx, x0, y0, z, x1, y1, invertTex); 612 613 /* restore state */ 614 cso_restore_rasterizer(cso); 615 cso_restore_viewport(cso); 616 cso_restore_samplers(cso); 617 cso_restore_sampler_textures(cso); 618 619 /* shaders don't go through cso yet */ 620 pipe->bind_fs_state(pipe, st->fp->driver_shader); 621 pipe->bind_vs_state(pipe, st->vp->driver_shader); 622} 623 624 625/** 626 * Check if a GL format/type combination is a match to the given pipe format. 627 * XXX probably move this to a re-usable place. 628 */ 629static GLboolean 630compatible_formats(GLenum format, GLenum type, enum pipe_format pipeFormat) 631{ 632 static const GLuint one = 1; 633 GLubyte littleEndian = *((GLubyte *) &one); 634 635 if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM && 636 format == GL_RGBA && 637 type == GL_UNSIGNED_BYTE && 638 !littleEndian) { 639 return GL_TRUE; 640 } 641 else if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM && 642 format == GL_ABGR_EXT && 643 type == GL_UNSIGNED_BYTE && 644 littleEndian) { 645 return GL_TRUE; 646 } 647 else if (pipeFormat == PIPE_FORMAT_A8R8G8B8_UNORM && 648 format == GL_BGRA && 649 type == GL_UNSIGNED_BYTE && 650 littleEndian) { 651 return GL_TRUE; 652 } 653 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM && 654 format == GL_RGB && 655 type == GL_UNSIGNED_SHORT_5_6_5) { 656 /* endian don't care */ 657 return GL_TRUE; 658 } 659 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM && 660 format == GL_BGR && 661 type == GL_UNSIGNED_SHORT_5_6_5_REV) { 662 /* endian don't care */ 663 return GL_TRUE; 664 } 665 else if (pipeFormat == PIPE_FORMAT_S8_UNORM && 666 format == GL_STENCIL_INDEX && 667 type == GL_UNSIGNED_BYTE) { 668 return GL_TRUE; 669 } 670 else if (pipeFormat == PIPE_FORMAT_Z32_UNORM && 671 format == GL_DEPTH_COMPONENT && 672 type == GL_UNSIGNED_INT) { 673 return GL_TRUE; 674 } 675 /* XXX add more cases */ 676 else { 677 return GL_FALSE; 678 } 679} 680 681 682/** 683 * Check if any per-fragment ops are enabled. 684 * XXX probably move this to a re-usable place. 685 */ 686static GLboolean 687any_fragment_ops(const struct st_context *st) 688{ 689 if (st->state.depth_stencil.alpha.enabled || 690 st->state.depth_stencil.depth.enabled || 691 st->state.blend.blend_enable || 692 st->state.blend.logicop_enable) 693 /* XXX more checks */ 694 return GL_TRUE; 695 else 696 return GL_FALSE; 697} 698 699 700/** 701 * Check if any pixel transfer ops are enabled. 702 * XXX probably move this to a re-usable place. 703 */ 704static GLboolean 705any_pixel_transfer_ops(const struct st_context *st) 706{ 707 if (st->ctx->Pixel.RedScale != 1.0 || 708 st->ctx->Pixel.RedBias != 0.0 || 709 st->ctx->Pixel.GreenScale != 1.0 || 710 st->ctx->Pixel.GreenBias != 0.0 || 711 st->ctx->Pixel.BlueScale != 1.0 || 712 st->ctx->Pixel.BlueBias != 0.0 || 713 st->ctx->Pixel.AlphaScale != 1.0 || 714 st->ctx->Pixel.AlphaBias != 0.0 || 715 st->ctx->Pixel.MapColorFlag) 716 /* XXX more checks */ 717 return GL_TRUE; 718 else 719 return GL_FALSE; 720} 721 722 723/** 724 * Draw image with a blit, or other non-textured quad method. 725 */ 726static void 727draw_blit(struct st_context *st, 728 GLsizei width, GLsizei height, 729 GLenum format, GLenum type, const GLvoid *pixels) 730{ 731 732 733} 734 735 736static void 737draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, 738 GLsizei width, GLsizei height, GLenum type, 739 const struct gl_pixelstore_attrib *unpack, 740 const GLvoid *pixels) 741{ 742 struct st_context *st = ctx->st; 743 struct pipe_context *pipe = st->pipe; 744 struct pipe_surface *ps = st->state.framebuffer.zsbuf; 745 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 746 GLint skipPixels; 747 ubyte *stmap; 748 749 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 750 751 /* map the stencil buffer */ 752 stmap = pipe_surface_map(ps); 753 754 /* if width > MAX_WIDTH, have to process image in chunks */ 755 skipPixels = 0; 756 while (skipPixels < width) { 757 const GLint spanX = x + skipPixels; 758 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 759 GLint row; 760 for (row = 0; row < height; row++) { 761 GLint spanY = y + row; 762 GLubyte values[MAX_WIDTH]; 763 GLenum destType = GL_UNSIGNED_BYTE; 764 const GLvoid *source = _mesa_image_address2d(unpack, pixels, 765 width, height, 766 GL_COLOR_INDEX, type, 767 row, skipPixels); 768 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values, 769 type, source, unpack, 770 ctx->_ImageTransferState); 771 if (zoom) { 772 /* 773 _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth, 774 spanX, spanY, values); 775 */ 776 } 777 else { 778 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 779 spanY = ctx->DrawBuffer->Height - spanY - 1; 780 } 781 782 switch (ps->format) { 783 case PIPE_FORMAT_U_S8: 784 { 785 ubyte *dest = stmap + spanY * ps->pitch + spanX; 786 memcpy(dest, values, spanWidth); 787 } 788 break; 789 case PIPE_FORMAT_S8Z24_UNORM: 790 { 791 uint *dest = (uint *) stmap + spanY * ps->pitch + spanX; 792 GLint k; 793 for (k = 0; k < spanWidth; k++) { 794 uint p = dest[k]; 795 p = (p & 0xffffff) | (values[k] << 24); 796 dest[k] = p; 797 } 798 } 799 break; 800 default: 801 assert(0); 802 } 803 } 804 } 805 skipPixels += spanWidth; 806 } 807 808 /* unmap the stencil buffer */ 809 pipe_surface_unmap(ps); 810} 811 812 813/** 814 * Called via ctx->Driver.DrawPixels() 815 */ 816static void 817st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, 818 GLenum format, GLenum type, 819 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) 820{ 821 struct st_fragment_program *stfp; 822 struct st_vertex_program *stvp; 823 struct st_context *st = ctx->st; 824 struct pipe_surface *ps; 825 GLuint bufferFormat; 826 const GLfloat *color; 827 828 if (format == GL_STENCIL_INDEX) { 829 draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels); 830 return; 831 } 832 833 st_validate_state(st); 834 835 if (format == GL_DEPTH_COMPONENT) { 836 ps = st->state.framebuffer.zsbuf; 837 stfp = make_fragment_shader_z(ctx->st); 838 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); 839 color = ctx->Current.RasterColor; 840 } 841 else if (format == GL_STENCIL_INDEX) { 842 ps = st->state.framebuffer.zsbuf; 843 /* XXX special case - can't use texture map */ 844 color = NULL; 845 } 846 else { 847 ps = st->state.framebuffer.cbufs[0]; 848 stfp = combined_drawpix_fragment_program(ctx); 849 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE); 850 color = NULL; 851 } 852 853 bufferFormat = ps->format; 854 855 if (1/*any_fragment_ops(st) || 856 any_pixel_transfer_ops(st) || 857 !compatible_formats(format, type, ps->format)*/) { 858 /* textured quad */ 859 struct pipe_texture *pt 860 = make_texture(ctx->st, width, height, format, type, unpack, pixels); 861 if (pt) { 862 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], 863 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 864 pt, stvp, stfp, color, GL_FALSE); 865 pipe_texture_reference(&pt, NULL); 866 } 867 } 868 else { 869 /* blit */ 870 draw_blit(st, width, height, format, type, pixels); 871 } 872} 873 874 875 876static void 877copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, 878 GLsizei width, GLsizei height, 879 GLint dstx, GLint dsty) 880{ 881 struct st_renderbuffer *rbRead = st_renderbuffer(ctx->ReadBuffer->_StencilBuffer); 882 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); 883 struct pipe_surface *psRead = rbRead->surface; 884 struct pipe_surface *psDraw = rbDraw->surface; 885 ubyte *readMap, *drawMap; 886 ubyte *buffer; 887 int i; 888 889 buffer = malloc(width * height * sizeof(ubyte)); 890 if (!buffer) { 891 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)"); 892 return; 893 } 894 895 /* map the stencil buffers */ 896 readMap = pipe_surface_map(psRead); 897 drawMap = pipe_surface_map(psDraw); 898 899 /* this will do stencil pixel transfer ops */ 900 st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE, 901 &ctx->DefaultPacking, buffer); 902 903 /* draw */ 904 /* XXX PixelZoom not handled yet */ 905 for (i = 0; i < height; i++) { 906 ubyte *dst; 907 const ubyte *src; 908 int y; 909 910 y = dsty + i; 911 912 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 913 y = ctx->DrawBuffer->Height - y - 1; 914 } 915 916 dst = drawMap + (y * psDraw->pitch + dstx) * psDraw->cpp; 917 src = buffer + i * width; 918 919 switch (psDraw->format) { 920 case PIPE_FORMAT_S8Z24_UNORM: 921 { 922 uint *dst4 = (uint *) dst; 923 int j; 924 for (j = 0; j < width; j++) { 925 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24); 926 dst4++; 927 } 928 } 929 break; 930 case PIPE_FORMAT_U_S8: 931 memcpy(dst, src, width); 932 break; 933 default: 934 assert(0); 935 } 936 } 937 938 free(buffer); 939 940 /* unmap the stencil buffers */ 941 pipe_surface_unmap(psRead); 942 pipe_surface_unmap(psDraw); 943} 944 945 946static void 947st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, 948 GLsizei width, GLsizei height, 949 GLint dstx, GLint dsty, GLenum type) 950{ 951 struct st_context *st = ctx->st; 952 struct pipe_context *pipe = st->pipe; 953 struct pipe_screen *screen = pipe->screen; 954 struct st_renderbuffer *rbRead; 955 struct st_vertex_program *stvp; 956 struct st_fragment_program *stfp; 957 struct pipe_surface *psRead; 958 struct pipe_surface *psTex; 959 struct pipe_texture *pt; 960 GLfloat *color; 961 enum pipe_format srcFormat, texFormat; 962 963 /* make sure rendering has completed */ 964 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 965 966 st_validate_state(st); 967 968 if (type == GL_STENCIL) { 969 /* can't use texturing to do stencil */ 970 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); 971 return; 972 } 973 974 if (type == GL_COLOR) { 975 rbRead = st_get_color_read_renderbuffer(ctx); 976 color = NULL; 977 stfp = combined_drawpix_fragment_program(ctx); 978 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE); 979 } 980 else { 981 assert(type == GL_DEPTH); 982 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); 983 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; 984 stfp = make_fragment_shader_z(ctx->st); 985 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); 986 } 987 988 psRead = rbRead->surface; 989 srcFormat = psRead->format; 990 991 if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE)) { 992 texFormat = srcFormat; 993 } 994 else { 995 /* srcFormat can't be used as a texture format */ 996 if (type == GL_DEPTH) { 997 static const enum pipe_format zFormats[] = { 998 PIPE_FORMAT_Z16_UNORM, 999 PIPE_FORMAT_Z32_UNORM, 1000 PIPE_FORMAT_S8Z24_UNORM, 1001 PIPE_FORMAT_Z24S8_UNORM 1002 }; 1003 uint i; 1004 texFormat = 0; 1005 for (i = 0; i < Elements(zFormats); i++) { 1006 if (screen->is_format_supported(screen, zFormats[i], 1007 PIPE_TEXTURE)) { 1008 texFormat = zFormats[i]; 1009 break; 1010 } 1011 } 1012 assert(texFormat); /* XXX no depth texture formats??? */ 1013 } 1014 else { 1015 /* todo */ 1016 assert(0); 1017 } 1018 } 1019 1020 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, 1021 width, height, 1, 0); 1022 if (!pt) 1023 return; 1024 1025 psTex = screen->get_tex_surface(screen, pt, 0, 0, 0); 1026 1027 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { 1028 srcy = ctx->DrawBuffer->Height - srcy - height; 1029 } 1030 1031 if (srcFormat == texFormat) { 1032 /* copy source framebuffer surface into mipmap/texture */ 1033 pipe->surface_copy(pipe, 1034 FALSE, 1035 psTex, /* dest */ 1036 0, 0, /* destx/y */ 1037 psRead, 1038 srcx, srcy, width, height); 1039 } 1040 else if (type == GL_COLOR) { 1041 /* alternate path using get/put_tile() */ 1042 GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); 1043 1044 pipe_get_tile_rgba(pipe, psRead, srcx, srcy, width, height, buf); 1045 pipe_put_tile_rgba(pipe, psTex, 0, 0, width, height, buf); 1046 1047 free(buf); 1048 } 1049 else { 1050 /* GL_DEPTH */ 1051 GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); 1052 pipe_get_tile_z(pipe, psRead, srcx, srcy, width, height, buf); 1053 pipe_put_tile_z(pipe, psTex, 0, 0, width, height, buf); 1054 free(buf); 1055 } 1056 1057 /* draw textured quad */ 1058 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], 1059 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, 1060 pt, stvp, stfp, color, GL_TRUE); 1061 1062 pipe_surface_reference(&psTex, NULL); 1063 pipe_texture_reference(&pt, NULL); 1064} 1065 1066 1067 1068void st_init_drawpixels_functions(struct dd_function_table *functions) 1069{ 1070 functions->DrawPixels = st_DrawPixels; 1071 functions->CopyPixels = st_CopyPixels; 1072} 1073