00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "main/imports.h"
00034 #include "main/image.h"
00035 #include "main/bufferobj.h"
00036 #include "main/macros.h"
00037 #include "main/texformat.h"
00038 #include "main/state.h"
00039 #include "shader/program.h"
00040 #include "shader/prog_parameter.h"
00041 #include "shader/prog_print.h"
00042
00043 #include "st_context.h"
00044 #include "st_atom.h"
00045 #include "st_atom_constbuf.h"
00046 #include "st_draw.h"
00047 #include "st_program.h"
00048 #include "st_cb_drawpixels.h"
00049 #include "st_cb_readpixels.h"
00050 #include "st_cb_fbo.h"
00051 #include "st_cb_texture.h"
00052 #include "st_draw.h"
00053 #include "st_format.h"
00054 #include "st_mesa_to_tgsi.h"
00055 #include "st_texture.h"
00056 #include "pipe/p_context.h"
00057 #include "pipe/p_defines.h"
00058 #include "pipe/p_inlines.h"
00059 #include "util/u_tile.h"
00060 #include "util/u_draw_quad.h"
00061 #include "shader/prog_instruction.h"
00062 #include "cso_cache/cso_context.h"
00063
00064
00070 static GLboolean
00071 is_passthrough_program(const struct gl_fragment_program *prog)
00072 {
00073 if (prog->Base.NumInstructions == 2) {
00074 const struct prog_instruction *inst = prog->Base.Instructions;
00075 if (inst[0].Opcode == OPCODE_MOV &&
00076 inst[1].Opcode == OPCODE_END &&
00077 inst[0].DstReg.File == PROGRAM_OUTPUT &&
00078 inst[0].DstReg.Index == FRAG_RESULT_COLR &&
00079 inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
00080 inst[0].SrcReg[0].File == PROGRAM_INPUT &&
00081 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
00082 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
00083 return GL_TRUE;
00084 }
00085 }
00086 return GL_FALSE;
00087 }
00088
00089
00090
00095 static struct st_fragment_program *
00096 combined_drawpix_fragment_program(GLcontext *ctx)
00097 {
00098 struct st_context *st = ctx->st;
00099 struct st_fragment_program *stfp;
00100
00101 if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
00102 && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
00103
00104
00105
00106 stfp = st->pixel_xfer.combined_prog;
00107 }
00108 else {
00109
00110
00111
00112 if (is_passthrough_program(&st->fp->Base)) {
00113 stfp = (struct st_fragment_program *)
00114 _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
00115 }
00116 else {
00117 #if 0
00118 printf("Base program:\n");
00119 _mesa_print_program(&st->fp->Base.Base);
00120 printf("DrawPix program:\n");
00121 _mesa_print_program(&st->pixel_xfer.program->Base.Base);
00122 #endif
00123 stfp = (struct st_fragment_program *)
00124 _mesa_combine_programs(ctx,
00125 &st->pixel_xfer.program->Base.Base,
00126 &st->fp->Base.Base);
00127 }
00128
00129 #if 0
00130 {
00131 struct gl_program *p = &stfp->Base.Base;
00132 printf("Combined DrawPixels program:\n");
00133 _mesa_print_program(p);
00134 printf("InputsRead: 0x%x\n", p->InputsRead);
00135 printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
00136 _mesa_print_parameter_list(p->Parameters);
00137 }
00138 #endif
00139
00140
00141 st_translate_fragment_program(st, stfp, NULL);
00142
00143
00144 st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
00145 st->pixel_xfer.user_prog_sn = st->fp->serialNo;
00146 st->pixel_xfer.combined_prog_sn = stfp->serialNo;
00147 st->pixel_xfer.combined_prog = stfp;
00148 }
00149
00150
00151
00152
00153 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
00154
00155 return stfp;
00156 }
00157
00158
00164 static struct st_fragment_program *
00165 make_fragment_shader_z(struct st_context *st)
00166 {
00167 GLcontext *ctx = st->ctx;
00168 struct gl_program *p;
00169 GLuint ic = 0;
00170
00171 if (st->drawpix.z_shader) {
00172 return st->drawpix.z_shader;
00173 }
00174
00175
00176
00177
00178 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
00179 if (!p)
00180 return NULL;
00181
00182 p->NumInstructions = 3;
00183
00184 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
00185 if (!p->Instructions) {
00186 ctx->Driver.DeleteProgram(ctx, p);
00187 return NULL;
00188 }
00189 _mesa_init_instructions(p->Instructions, p->NumInstructions);
00190
00191
00192 p->Instructions[ic].Opcode = OPCODE_TEX;
00193 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
00194 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR;
00195 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
00196 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
00197 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
00198 p->Instructions[ic].TexSrcUnit = 0;
00199 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
00200 ic++;
00201
00202
00203 p->Instructions[ic].Opcode = OPCODE_MOV;
00204 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
00205 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
00206 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
00207 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
00208 ic++;
00209
00210
00211 p->Instructions[ic++].Opcode = OPCODE_END;
00212
00213 assert(ic == p->NumInstructions);
00214
00215 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
00216 p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR);
00217 p->SamplersUsed = 0x1;
00218
00219 st->drawpix.z_shader = (struct st_fragment_program *) p;
00220 st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
00221
00222 return st->drawpix.z_shader;
00223 }
00224
00225
00226
00231 static struct st_vertex_program *
00232 st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
00233 {
00234 GLcontext *ctx = st->ctx;
00235 struct st_vertex_program *stvp;
00236 struct gl_program *p;
00237 GLuint ic = 0;
00238
00239 if (st->drawpix.vert_shaders[passColor])
00240 return st->drawpix.vert_shaders[passColor];
00241
00242
00243
00244
00245 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
00246 if (!p)
00247 return NULL;
00248
00249 if (passColor)
00250 p->NumInstructions = 4;
00251 else
00252 p->NumInstructions = 3;
00253
00254 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
00255 if (!p->Instructions) {
00256 ctx->Driver.DeleteProgram(ctx, p);
00257 return NULL;
00258 }
00259 _mesa_init_instructions(p->Instructions, p->NumInstructions);
00260
00261 p->Instructions[0].Opcode = OPCODE_MOV;
00262 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
00263 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
00264 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
00265 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
00266
00267 p->Instructions[1].Opcode = OPCODE_MOV;
00268 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
00269 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
00270 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
00271 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
00272 ic = 2;
00273 if (passColor) {
00274
00275 p->Instructions[ic].Opcode = OPCODE_MOV;
00276 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
00277 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
00278 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
00279 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
00280 ic++;
00281 }
00282
00283
00284 p->Instructions[ic].Opcode = OPCODE_END;
00285 ic++;
00286
00287 assert(ic == p->NumInstructions);
00288
00289 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
00290 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
00291 (1 << VERT_RESULT_HPOS));
00292 if (passColor) {
00293 p->InputsRead |= VERT_BIT_COLOR0;
00294 p->OutputsWritten |= (1 << VERT_RESULT_COL0);
00295 }
00296
00297 stvp = (struct st_vertex_program *) p;
00298 st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
00299
00300 st->drawpix.vert_shaders[passColor] = stvp;
00301
00302 return stvp;
00303 }
00304
00305
00306 static GLenum
00307 _mesa_base_format(GLenum format)
00308 {
00309 switch (format) {
00310 case GL_DEPTH_COMPONENT:
00311 return GL_DEPTH_COMPONENT;
00312 case GL_STENCIL_INDEX:
00313 return GL_STENCIL_INDEX;
00314 default:
00315 return GL_RGBA;
00316 }
00317 }
00318
00319
00324 static struct pipe_texture *
00325 make_texture(struct st_context *st,
00326 GLsizei width, GLsizei height, GLenum format, GLenum type,
00327 const struct gl_pixelstore_attrib *unpack,
00328 const GLvoid *pixels)
00329 {
00330 GLcontext *ctx = st->ctx;
00331 struct pipe_context *pipe = st->pipe;
00332 struct pipe_screen *screen = pipe->screen;
00333 const struct gl_texture_format *mformat;
00334 struct pipe_texture *pt;
00335 enum pipe_format pipeFormat;
00336 GLuint cpp;
00337 GLenum baseFormat;
00338
00339 baseFormat = _mesa_base_format(format);
00340
00341 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
00342 assert(mformat);
00343
00344 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
00345 assert(pipeFormat);
00346 cpp = st_sizeof_format(pipeFormat);
00347
00348 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels);
00349 if (!pixels)
00350 return NULL;
00351
00352 pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height,
00353 1, 0,
00354 PIPE_TEXTURE_USAGE_SAMPLER);
00355 if (!pt) {
00356 _mesa_unmap_drawpix_pbo(ctx, unpack);
00357 return NULL;
00358 }
00359
00360 {
00361 struct pipe_surface *surface;
00362 static const GLuint dstImageOffsets = 0;
00363 GLboolean success;
00364 GLubyte *dest;
00365 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
00366
00367
00368 ctx->_ImageTransferState = 0x0;
00369
00370 surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
00371 PIPE_BUFFER_USAGE_CPU_WRITE);
00372
00373
00374 dest = screen->surface_map(screen, surface,
00375 PIPE_BUFFER_USAGE_CPU_WRITE);
00376
00377
00378
00379
00380
00381 success = mformat->StoreImage(ctx, 2,
00382 baseFormat,
00383 mformat,
00384 dest,
00385 0, 0, 0,
00386 surface->stride,
00387 &dstImageOffsets,
00388 width, height, 1,
00389 format, type,
00390 pixels,
00391 unpack);
00392
00393
00394 screen->surface_unmap(screen, surface);
00395 pipe_surface_reference(&surface, NULL);
00396
00397 assert(success);
00398
00399
00400 ctx->_ImageTransferState = imageTransferStateSave;
00401 }
00402
00403 _mesa_unmap_drawpix_pbo(ctx, unpack);
00404
00405 return pt;
00406 }
00407
00408
00415 static void
00416 draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
00417 GLfloat x1, GLfloat y1, const GLfloat *color,
00418 GLboolean invertTex)
00419 {
00420 struct st_context *st = ctx->st;
00421 struct pipe_context *pipe = ctx->st->pipe;
00422 GLfloat verts[4][3][4];
00423
00424
00425 {
00426 const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
00427 const GLfloat fb_width = (GLfloat) fb->Width;
00428 const GLfloat fb_height = (GLfloat) fb->Height;
00429 const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
00430 const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
00431 const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
00432 const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
00433 const GLfloat sLeft = 0.0f, sRight = 1.0f;
00434 const GLfloat tTop = invertTex, tBot = 1.0f - tTop;
00435 GLuint tex, i;
00436
00437
00438 verts[0][0][0] = clip_x0;
00439 verts[0][0][1] = clip_y0;
00440
00441
00442 verts[1][0][0] = clip_x1;
00443 verts[1][0][1] = clip_y0;
00444
00445
00446 verts[2][0][0] = clip_x1;
00447 verts[2][0][1] = clip_y1;
00448
00449
00450 verts[3][0][0] = clip_x0;
00451 verts[3][0][1] = clip_y1;
00452
00453 tex = color ? 2 : 1;
00454 verts[0][tex][0] = sLeft;
00455 verts[0][tex][1] = tTop;
00456 verts[1][tex][0] = sRight;
00457 verts[1][tex][1] = tTop;
00458 verts[2][tex][0] = sRight;
00459 verts[2][tex][1] = tBot;
00460 verts[3][tex][0] = sLeft;
00461 verts[3][tex][1] = tBot;
00462
00463
00464 if (color) {
00465 for (i = 0; i < 4; i++) {
00466 verts[i][0][2] = z;
00467 verts[i][0][3] = 1.0f;
00468 verts[i][1][0] = color[0];
00469 verts[i][1][1] = color[1];
00470 verts[i][1][2] = color[2];
00471 verts[i][1][3] = color[3];
00472 verts[i][2][2] = 0.0f;
00473 verts[i][2][3] = 1.0f;
00474 }
00475 }
00476 else {
00477 for (i = 0; i < 4; i++) {
00478 verts[i][0][2] = z;
00479 verts[i][0][3] = 1.0f;
00480 verts[i][1][2] = 0.0f;
00481 verts[i][1][3] = 1.0f;
00482 }
00483 }
00484 }
00485
00486 {
00487 struct pipe_buffer *buf;
00488 ubyte *map;
00489
00490
00491 buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
00492 sizeof(verts));
00493 map = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_WRITE);
00494 memcpy(map, verts, sizeof(verts));
00495 pipe_buffer_unmap(pipe->screen, buf);
00496
00497 util_draw_vertex_buffer(pipe, buf, 0,
00498 PIPE_PRIM_QUADS,
00499 4,
00500 3);
00501 pipe_buffer_reference(pipe->screen, &buf, NULL);
00502 }
00503 }
00504
00505
00506
00507 static void
00508 draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
00509 GLsizei width, GLsizei height,
00510 GLfloat zoomX, GLfloat zoomY,
00511 struct pipe_texture *pt,
00512 struct st_vertex_program *stvp,
00513 struct st_fragment_program *stfp,
00514 const GLfloat *color,
00515 GLboolean invertTex)
00516 {
00517 struct st_context *st = ctx->st;
00518 struct pipe_context *pipe = ctx->st->pipe;
00519 struct cso_context *cso = ctx->st->cso_context;
00520 GLfloat x0, y0, x1, y1;
00521 GLsizei maxSize;
00522
00523
00524
00525
00526
00527 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
00528 assert(width <= maxSize);
00529 assert(height <= maxSize);
00530
00531 cso_save_rasterizer(cso);
00532 cso_save_viewport(cso);
00533 cso_save_samplers(cso);
00534 cso_save_sampler_textures(cso);
00535 cso_save_fragment_shader(cso);
00536 cso_save_vertex_shader(cso);
00537
00538
00539 {
00540 struct pipe_rasterizer_state rasterizer;
00541 memset(&rasterizer, 0, sizeof(rasterizer));
00542 rasterizer.gl_rasterization_rules = 1;
00543 rasterizer.scissor = ctx->Scissor.Enabled;
00544 cso_set_rasterizer(cso, &rasterizer);
00545 }
00546
00547
00548 cso_set_fragment_shader_handle(cso, stfp->driver_shader);
00549
00550
00551 cso_set_vertex_shader_handle(cso, stvp->driver_shader);
00552
00553
00554
00555 {
00556 struct pipe_sampler_state sampler;
00557 memset(&sampler, 0, sizeof(sampler));
00558 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
00559 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
00560 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
00561 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
00562 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
00563 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
00564 sampler.normalized_coords = 1;
00565
00566 cso_single_sampler(cso, 0, &sampler);
00567 if (st->pixel_xfer.pixelmap_enabled) {
00568 cso_single_sampler(cso, 1, &sampler);
00569 }
00570 cso_single_sampler_done(cso);
00571 }
00572
00573
00574 {
00575 const float width = (float) ctx->DrawBuffer->Width;
00576 const float height = (float) ctx->DrawBuffer->Height;
00577 struct pipe_viewport_state vp;
00578 vp.scale[0] = 0.5f * width;
00579 vp.scale[1] = -0.5f * height;
00580 vp.scale[2] = 1.0f;
00581 vp.scale[3] = 1.0f;
00582 vp.translate[0] = 0.5f * width;
00583 vp.translate[1] = 0.5f * height;
00584 vp.translate[2] = 0.0f;
00585 vp.translate[3] = 0.0f;
00586 cso_set_viewport(cso, &vp);
00587 }
00588
00589
00590 if (st->pixel_xfer.pixelmap_enabled) {
00591 struct pipe_texture *textures[2];
00592 textures[0] = pt;
00593 textures[1] = st->pixel_xfer.pixelmap_texture;
00594 pipe->set_sampler_textures(pipe, 2, textures);
00595 }
00596 else {
00597 pipe->set_sampler_textures(pipe, 1, &pt);
00598 }
00599
00600
00601
00602
00603
00604 x0 = (GLfloat) x;
00605 x1 = x + width * ctx->Pixel.ZoomX;
00606 y0 = (GLfloat) y;
00607 y1 = y + height * ctx->Pixel.ZoomY;
00608
00609 draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex);
00610
00611
00612
00613 cso_restore_rasterizer(cso);
00614 cso_restore_viewport(cso);
00615 cso_restore_samplers(cso);
00616 cso_restore_sampler_textures(cso);
00617 cso_restore_fragment_shader(cso);
00618 cso_restore_vertex_shader(cso);
00619 }
00620
00621
00626 static GLboolean
00627 compatible_formats(GLenum format, GLenum type, enum pipe_format pipeFormat)
00628 {
00629 static const GLuint one = 1;
00630 GLubyte littleEndian = *((GLubyte *) &one);
00631
00632 if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
00633 format == GL_RGBA &&
00634 type == GL_UNSIGNED_BYTE &&
00635 !littleEndian) {
00636 return GL_TRUE;
00637 }
00638 else if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
00639 format == GL_ABGR_EXT &&
00640 type == GL_UNSIGNED_BYTE &&
00641 littleEndian) {
00642 return GL_TRUE;
00643 }
00644 else if (pipeFormat == PIPE_FORMAT_A8R8G8B8_UNORM &&
00645 format == GL_BGRA &&
00646 type == GL_UNSIGNED_BYTE &&
00647 littleEndian) {
00648 return GL_TRUE;
00649 }
00650 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
00651 format == GL_RGB &&
00652 type == GL_UNSIGNED_SHORT_5_6_5) {
00653
00654 return GL_TRUE;
00655 }
00656 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
00657 format == GL_BGR &&
00658 type == GL_UNSIGNED_SHORT_5_6_5_REV) {
00659
00660 return GL_TRUE;
00661 }
00662 else if (pipeFormat == PIPE_FORMAT_S8_UNORM &&
00663 format == GL_STENCIL_INDEX &&
00664 type == GL_UNSIGNED_BYTE) {
00665 return GL_TRUE;
00666 }
00667 else if (pipeFormat == PIPE_FORMAT_Z32_UNORM &&
00668 format == GL_DEPTH_COMPONENT &&
00669 type == GL_UNSIGNED_INT) {
00670 return GL_TRUE;
00671 }
00672
00673 else {
00674 return GL_FALSE;
00675 }
00676 }
00677
00678
00683 static GLboolean
00684 any_fragment_ops(const struct st_context *st)
00685 {
00686 if (st->state.depth_stencil.alpha.enabled ||
00687 st->state.depth_stencil.depth.enabled ||
00688 st->state.blend.blend_enable ||
00689 st->state.blend.logicop_enable)
00690
00691 return GL_TRUE;
00692 else
00693 return GL_FALSE;
00694 }
00695
00696
00701 static GLboolean
00702 any_pixel_transfer_ops(const struct st_context *st)
00703 {
00704 if (st->ctx->Pixel.RedScale != 1.0 ||
00705 st->ctx->Pixel.RedBias != 0.0 ||
00706 st->ctx->Pixel.GreenScale != 1.0 ||
00707 st->ctx->Pixel.GreenBias != 0.0 ||
00708 st->ctx->Pixel.BlueScale != 1.0 ||
00709 st->ctx->Pixel.BlueBias != 0.0 ||
00710 st->ctx->Pixel.AlphaScale != 1.0 ||
00711 st->ctx->Pixel.AlphaBias != 0.0 ||
00712 st->ctx->Pixel.MapColorFlag)
00713
00714 return GL_TRUE;
00715 else
00716 return GL_FALSE;
00717 }
00718
00719
00723 static void
00724 draw_blit(struct st_context *st,
00725 GLsizei width, GLsizei height,
00726 GLenum format, GLenum type, const GLvoid *pixels)
00727 {
00728
00729
00730 }
00731
00732
00733 static void
00734 draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
00735 GLsizei width, GLsizei height, GLenum type,
00736 const struct gl_pixelstore_attrib *unpack,
00737 const GLvoid *pixels)
00738 {
00739 struct st_context *st = ctx->st;
00740 struct pipe_context *pipe = st->pipe;
00741 struct pipe_screen *screen = pipe->screen;
00742 struct st_renderbuffer *strb;
00743 struct pipe_surface *ps;
00744 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
00745 GLint skipPixels;
00746 ubyte *stmap;
00747
00748 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
00749
00750 strb = st_renderbuffer(ctx->DrawBuffer->
00751 Attachment[BUFFER_STENCIL].Renderbuffer);
00752 ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
00753 PIPE_BUFFER_USAGE_CPU_WRITE);
00754
00755
00756 stmap = screen->surface_map(screen, ps,
00757 PIPE_BUFFER_USAGE_CPU_WRITE);
00758
00759
00760 skipPixels = 0;
00761 while (skipPixels < width) {
00762 const GLint spanX = x + skipPixels;
00763 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
00764 GLint row;
00765 for (row = 0; row < height; row++) {
00766 GLint spanY = y + row;
00767 GLubyte values[MAX_WIDTH];
00768 GLenum destType = GL_UNSIGNED_BYTE;
00769 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
00770 width, height,
00771 GL_COLOR_INDEX, type,
00772 row, skipPixels);
00773 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
00774 type, source, unpack,
00775 ctx->_ImageTransferState);
00776 if (zoom) {
00777
00778
00779
00780
00781 }
00782 else {
00783 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
00784 spanY = ctx->DrawBuffer->Height - spanY - 1;
00785 }
00786
00787 switch (ps->format) {
00788 case PIPE_FORMAT_S8_UNORM:
00789 {
00790 ubyte *dest = stmap + spanY * ps->stride + spanX;
00791 memcpy(dest, values, spanWidth);
00792 }
00793 break;
00794 case PIPE_FORMAT_S8Z24_UNORM:
00795 {
00796 uint *dest = (uint *) (stmap + spanY * ps->stride + spanX*4);
00797 GLint k;
00798 for (k = 0; k < spanWidth; k++) {
00799 uint p = dest[k];
00800 p = (p & 0xffffff) | (values[k] << 24);
00801 dest[k] = p;
00802 }
00803 }
00804 break;
00805 default:
00806 assert(0);
00807 }
00808 }
00809 }
00810 skipPixels += spanWidth;
00811 }
00812
00813
00814 screen->surface_unmap(screen, ps);
00815 pipe_surface_reference(&ps, NULL);
00816 }
00817
00818
00822 static void
00823 st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
00824 GLenum format, GLenum type,
00825 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
00826 {
00827 struct st_fragment_program *stfp;
00828 struct st_vertex_program *stvp;
00829 struct st_context *st = ctx->st;
00830 struct pipe_surface *ps;
00831 GLuint bufferFormat;
00832 const GLfloat *color;
00833
00834 if (format == GL_STENCIL_INDEX) {
00835 draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
00836 return;
00837 }
00838
00839 _mesa_set_vp_override( ctx, TRUE );
00840 _mesa_update_state( ctx );
00841
00842 st_validate_state(st);
00843
00844 if (format == GL_DEPTH_COMPONENT) {
00845 ps = st->state.framebuffer.zsbuf;
00846 stfp = make_fragment_shader_z(ctx->st);
00847 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
00848 color = ctx->Current.RasterColor;
00849 }
00850 else if (format == GL_STENCIL_INDEX) {
00851 ps = st->state.framebuffer.zsbuf;
00852
00853 color = NULL;
00854 }
00855 else {
00856 ps = st->state.framebuffer.cbufs[0];
00857 stfp = combined_drawpix_fragment_program(ctx);
00858 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
00859 color = NULL;
00860 }
00861
00862 bufferFormat = ps->format;
00863
00864 if (1
00865
00866 ) {
00867
00868 struct pipe_texture *pt
00869 = make_texture(ctx->st, width, height, format, type, unpack, pixels);
00870 if (pt) {
00871 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
00872 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
00873 pt, stvp, stfp, color, GL_FALSE);
00874 pipe_texture_reference(&pt, NULL);
00875 }
00876 }
00877 else {
00878
00879 draw_blit(st, width, height, format, type, pixels);
00880 }
00881
00882 _mesa_set_vp_override( ctx, FALSE );
00883 }
00884
00885
00886
00887 static void
00888 copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
00889 GLsizei width, GLsizei height,
00890 GLint dstx, GLint dsty)
00891 {
00892 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
00893 struct pipe_screen *screen = ctx->st->pipe->screen;
00894 struct pipe_surface *psDraw;
00895 ubyte *drawMap;
00896 ubyte *buffer;
00897 int i;
00898
00899 buffer = malloc(width * height * sizeof(ubyte));
00900 if (!buffer) {
00901 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
00902 return;
00903 }
00904
00905
00906 st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE,
00907 &ctx->DefaultPacking, buffer);
00908
00909 psDraw = screen->get_tex_surface(screen, rbDraw->texture, 0, 0, 0,
00910 PIPE_BUFFER_USAGE_CPU_WRITE);
00911
00912 assert(psDraw->block.width == 1);
00913 assert(psDraw->block.height == 1);
00914
00915
00916 drawMap = screen->surface_map(screen, psDraw, PIPE_BUFFER_USAGE_CPU_WRITE);
00917
00918
00919
00920 for (i = 0; i < height; i++) {
00921 ubyte *dst;
00922 const ubyte *src;
00923 int y;
00924
00925 y = dsty + i;
00926
00927 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
00928 y = ctx->DrawBuffer->Height - y - 1;
00929 }
00930
00931 dst = drawMap + y * psDraw->stride + dstx * psDraw->block.size;
00932 src = buffer + i * width;
00933
00934 switch (psDraw->format) {
00935 case PIPE_FORMAT_S8Z24_UNORM:
00936 {
00937 uint *dst4 = (uint *) dst;
00938 int j;
00939 for (j = 0; j < width; j++) {
00940 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
00941 dst4++;
00942 }
00943 }
00944 break;
00945 case PIPE_FORMAT_S8_UNORM:
00946 memcpy(dst, src, width);
00947 break;
00948 default:
00949 assert(0);
00950 }
00951 }
00952
00953 free(buffer);
00954
00955
00956 screen->surface_unmap(screen, psDraw);
00957 pipe_surface_reference(&psDraw, NULL);
00958 }
00959
00960
00961 static void
00962 st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
00963 GLsizei width, GLsizei height,
00964 GLint dstx, GLint dsty, GLenum type)
00965 {
00966 struct st_context *st = ctx->st;
00967 struct pipe_context *pipe = st->pipe;
00968 struct pipe_screen *screen = pipe->screen;
00969 struct st_renderbuffer *rbRead;
00970 struct st_vertex_program *stvp;
00971 struct st_fragment_program *stfp;
00972 struct pipe_surface *psTex;
00973 struct pipe_texture *pt;
00974 GLfloat *color;
00975 enum pipe_format srcFormat, texFormat;
00976
00977
00978 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
00979
00980 st_validate_state(st);
00981
00982 if (type == GL_STENCIL) {
00983
00984 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
00985 return;
00986 }
00987
00988 if (type == GL_COLOR) {
00989 rbRead = st_get_color_read_renderbuffer(ctx);
00990 color = NULL;
00991 stfp = combined_drawpix_fragment_program(ctx);
00992 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
00993 }
00994 else {
00995 assert(type == GL_DEPTH);
00996 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
00997 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
00998 stfp = make_fragment_shader_z(ctx->st);
00999 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
01000 }
01001
01002 srcFormat = rbRead->texture->format;
01003
01004 if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D,
01005 PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
01006 texFormat = srcFormat;
01007 }
01008 else {
01009
01010 if (type == GL_DEPTH) {
01011 texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D,
01012 PIPE_TEXTURE_USAGE_DEPTH_STENCIL);
01013 assert(texFormat != PIPE_FORMAT_NONE);
01014 }
01015 else {
01016
01017 texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D,
01018 PIPE_TEXTURE_USAGE_SAMPLER);
01019 assert(texFormat != PIPE_FORMAT_NONE);
01020 }
01021 }
01022
01023 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
01024 width, height, 1, 0,
01025 PIPE_TEXTURE_USAGE_SAMPLER);
01026 if (!pt)
01027 return;
01028
01029 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
01030 srcy = ctx->DrawBuffer->Height - srcy - height;
01031 }
01032
01033 if (srcFormat == texFormat) {
01034
01035 struct pipe_surface *psRead = screen->get_tex_surface(screen,
01036 rbRead->texture, 0, 0, 0,
01037 PIPE_BUFFER_USAGE_GPU_READ);
01038 psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
01039 PIPE_BUFFER_USAGE_GPU_WRITE );
01040 pipe->surface_copy(pipe,
01041 FALSE,
01042 psTex,
01043 0, 0,
01044 psRead,
01045 srcx, srcy, width, height);
01046 pipe_surface_reference(&psRead, NULL);
01047 }
01048 else {
01049
01050 struct pipe_surface *psRead = screen->get_tex_surface(screen,
01051 rbRead->texture, 0, 0, 0,
01052 PIPE_BUFFER_USAGE_CPU_READ);
01053
01054 psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
01055 PIPE_BUFFER_USAGE_CPU_WRITE );
01056
01057 if (type == GL_COLOR) {
01058
01059 GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
01060
01061 pipe_get_tile_rgba(psRead, srcx, srcy, width, height, buf);
01062 pipe_put_tile_rgba(psTex, 0, 0, width, height, buf);
01063
01064 free(buf);
01065 }
01066 else {
01067
01068 GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
01069 pipe_get_tile_z(psRead, srcx, srcy, width, height, buf);
01070 pipe_put_tile_z(psTex, 0, 0, width, height, buf);
01071 free(buf);
01072 }
01073 pipe_surface_reference(&psRead, NULL);
01074 }
01075
01076 pipe_surface_reference(&psTex, NULL);
01077
01078
01079 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
01080 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
01081 pt, stvp, stfp, color, GL_TRUE);
01082
01083 pipe_texture_reference(&pt, NULL);
01084 }
01085
01086
01087
01088 void st_init_drawpixels_functions(struct dd_function_table *functions)
01089 {
01090 functions->DrawPixels = st_DrawPixels;
01091 functions->CopyPixels = st_CopyPixels;
01092 }
01093
01094
01095 void
01096 st_destroy_drawpix(struct st_context *st)
01097 {
01098 st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
01099 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
01100 st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL);
01101 st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL);
01102 }
01103
01104