st_cb_drawpixels.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028  /*
00029   * Authors:
00030   *   Brian Paul
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       /* the pixel tranfer program has not changed and the user-defined
00104        * program has not changed, so re-use the combined program.
00105        */
00106       stfp = st->pixel_xfer.combined_prog;
00107    }
00108    else {
00109       /* Concatenate the pixel transfer program with the current user-
00110        * defined program.
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       /* translate to TGSI tokens */
00141       st_translate_fragment_program(st, stfp, NULL);
00142 
00143       /* save new program, update serial numbers */
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    /* Ideally we'd have updated the pipe constants during the normal
00151     * st/atom mechanism.  But we can't since this is specific to glDrawPixels.
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     * Create shader now
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    /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
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    /* MOV result.color, fragment.color */
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    /* END; */
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;  /* sampler 0 (bit 0) is used */
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     * Create shader now
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    /* MOV result.pos, vertex.pos; */
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    /* MOV result.texcoord0, vertex.texcoord0; */
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       /* MOV result.color0, vertex.color0; */
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    /* END; */
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       /* we'll do pixel transfer in a fragment shader */
00368       ctx->_ImageTransferState = 0x0;
00369 
00370       surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
00371                                         PIPE_BUFFER_USAGE_CPU_WRITE);
00372 
00373       /* map texture surface */
00374       dest = screen->surface_map(screen, surface,
00375                                  PIPE_BUFFER_USAGE_CPU_WRITE);
00376 
00377       /* Put image into texture surface.
00378        * Note that the image is actually going to be upside down in
00379        * the texture.  We deal with that with texcoords.
00380        */
00381       success = mformat->StoreImage(ctx, 2,           /* dims */
00382                                     baseFormat,       /* baseInternalFormat */
00383                                     mformat,          /* gl_texture_format */
00384                                     dest,             /* dest */
00385                                     0, 0, 0,          /* dstX/Y/Zoffset */
00386                                     surface->stride,  /* dstRowStride, bytes */
00387                                     &dstImageOffsets, /* dstImageOffsets */
00388                                     width, height, 1, /* size */
00389                                     format, type,     /* src format/type */
00390                                     pixels,           /* data source */
00391                                     unpack);
00392 
00393       /* unmap */
00394       screen->surface_unmap(screen, surface);
00395       pipe_surface_reference(&surface, NULL);
00396 
00397       assert(success);
00398 
00399       /* restore */
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]; /* four verts, three attribs, XYZW */
00423 
00424    /* setup vertex data */
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       /* upper-left */
00438       verts[0][0][0] = clip_x0;    /* v[0].attr[0].x */
00439       verts[0][0][1] = clip_y0;    /* v[0].attr[0].y */
00440 
00441       /* upper-right */
00442       verts[1][0][0] = clip_x1;
00443       verts[1][0][1] = clip_y0;
00444 
00445       /* lower-right */
00446       verts[2][0][0] = clip_x1;
00447       verts[2][0][1] = clip_y1;
00448 
00449       /* lower-left */
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; /* v[0].attr[tex].s */
00455       verts[0][tex][1] = tTop;  /* v[0].attr[tex].t */
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       /* same for all verts: */
00464       if (color) {
00465          for (i = 0; i < 4; i++) {
00466             verts[i][0][2] = z;   /*Z*/
00467             verts[i][0][3] = 1.0f; /*W*/
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; /*R*/
00473             verts[i][2][3] = 1.0f; /*Q*/
00474          }
00475       }
00476       else {
00477          for (i = 0; i < 4; i++) {
00478             verts[i][0][2] = z;   /*Z*/
00479             verts[i][0][3] = 1.0f; /*W*/
00480             verts[i][1][2] = 0.0f; /*R*/
00481             verts[i][1][3] = 1.0f; /*Q*/
00482          }
00483       }
00484    }
00485 
00486    {
00487       struct pipe_buffer *buf;
00488       ubyte *map;
00489 
00490       /* allocate/load buffer object with vertex data */
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,  /* verts */
00500                               3); /* attribs/vert */
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    /* limit checks */
00524    /* XXX if DrawPixels image is larger than max texture size, break
00525     * it up into chunks.
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    /* rasterizer state: just scissor */
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    /* fragment shader state: TEX lookup program */
00548    cso_set_fragment_shader_handle(cso, stfp->driver_shader);
00549 
00550    /* vertex shader state: position + texcoord pass-through */
00551    cso_set_vertex_shader_handle(cso, stvp->driver_shader);
00552 
00553 
00554    /* texture sampling state: */
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    /* viewport state: viewport matching window dims */
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    /* texture state: */
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    /* Compute window coords (y=0=bottom) with pixel zoom.
00601     * Recall that these coords are transformed by the current
00602     * vertex shader and viewport transformation.
00603     */
00604    x0 = (GLfloat) x;
00605    x1 = x + width * ctx->Pixel.ZoomX;
00606    y0 = (GLfloat) y;
00607    y1 = y + height * ctx->Pixel.ZoomY;
00608    //if(!color)
00609    draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex);
00610    //else
00611    //printf("skip draw quad\n");
00612    /* restore state */
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       /* endian don't care */
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       /* endian don't care */
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    /* XXX add more cases */
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       /* XXX more checks */
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       /* XXX more checks */
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    /* map the stencil buffer */
00756    stmap = screen->surface_map(screen, ps, 
00757                                PIPE_BUFFER_USAGE_CPU_WRITE);
00758 
00759    /* if width > MAX_WIDTH, have to process image in chunks */
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             _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
00779                                               spanX, spanY, values);
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    /* unmap the stencil buffer */
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       /* XXX special case - can't use texture map */
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/*any_fragment_ops(st) ||
00865        any_pixel_transfer_ops(st) ||
00866        !compatible_formats(format, type, ps->format)*/) {
00867       /* textured quad */
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       /* blit */
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    /* this will do stencil pixel transfer ops */
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    /* map the stencil buffer */
00916    drawMap = screen->surface_map(screen, psDraw, PIPE_BUFFER_USAGE_CPU_WRITE);
00917 
00918    /* draw */
00919    /* XXX PixelZoom not handled yet */
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    /* unmap the stencil buffer */
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    /* make sure rendering has completed */
00978    pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
00979 
00980    st_validate_state(st);
00981 
00982    if (type == GL_STENCIL) {
00983       /* can't use texturing to do stencil */
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       /* srcFormat can't be used as a texture format */
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); /* XXX no depth texture formats??? */
01014       }
01015       else {
01016          /* default color format */
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       /* copy source framebuffer surface into mipmap/texture */
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, /* dest */
01043                          0, 0, /* destx/y */
01044                          psRead,
01045                          srcx, srcy, width, height);
01046       pipe_surface_reference(&psRead, NULL);
01047    }
01048    else {
01049       /* CPU-based fallback/conversion */
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          /* alternate path using get/put_tile() */
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          /* GL_DEPTH */
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    /* draw textured quad */
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 

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4