st_cb_bitmap.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 "shader/program.h"
00039 #include "shader/prog_parameter.h"
00040 #include "shader/prog_print.h"
00041 
00042 #include "st_context.h"
00043 #include "st_atom.h"
00044 #include "st_atom_constbuf.h"
00045 #include "st_program.h"
00046 #include "st_cb_bitmap.h"
00047 #include "st_cb_program.h"
00048 #include "st_mesa_to_tgsi.h"
00049 #include "st_texture.h"
00050 #include "pipe/p_context.h"
00051 #include "pipe/p_defines.h"
00052 #include "pipe/p_inlines.h"
00053 #include "util/u_tile.h"
00054 #include "util/u_draw_quad.h"
00055 #include "util/u_simple_shaders.h"
00056 #include "shader/prog_instruction.h"
00057 #include "cso_cache/cso_context.h"
00058 
00059 
00060 
00080 static GLboolean UseBitmapCache = GL_TRUE;
00081 
00082 
00083 #define BITMAP_CACHE_WIDTH  512
00084 #define BITMAP_CACHE_HEIGHT 32
00085 
00086 struct bitmap_cache
00087 {
00089    GLint xpos, ypos;
00091    GLint xmin, ymin, xmax, ymax;
00092 
00093    GLfloat color[4];
00094 
00095    struct pipe_texture *texture;
00096    struct pipe_surface *surf;
00097 
00098    GLboolean empty;
00099 
00101    ubyte *buffer;
00102 };
00103 
00104 
00105 
00106 
00112 static struct st_fragment_program *
00113 make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
00114 {
00115    struct st_fragment_program *stfp;
00116    struct gl_program *p;
00117    GLuint ic = 0;
00118 
00119    p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
00120    if (!p)
00121       return NULL;
00122 
00123    p->NumInstructions = 3;
00124 
00125    p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
00126    if (!p->Instructions) {
00127       ctx->Driver.DeleteProgram(ctx, p);
00128       return NULL;
00129    }
00130    _mesa_init_instructions(p->Instructions, p->NumInstructions);
00131 
00132    /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
00133    p->Instructions[ic].Opcode = OPCODE_TEX;
00134    p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
00135    p->Instructions[ic].DstReg.Index = 0;
00136    p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
00137    p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
00138    p->Instructions[ic].TexSrcUnit = samplerIndex;
00139    p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
00140    ic++;
00141 
00142    /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
00143    p->Instructions[ic].Opcode = OPCODE_KIL;
00144    p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
00145    p->Instructions[ic].SrcReg[0].Index = 0;
00146    p->Instructions[ic].SrcReg[0].NegateBase = NEGATE_XYZW;
00147    ic++;
00148 
00149    /* END; */
00150    p->Instructions[ic++].Opcode = OPCODE_END;
00151 
00152    assert(ic == p->NumInstructions);
00153 
00154    p->InputsRead = FRAG_BIT_TEX0;
00155    p->OutputsWritten = 0x0;
00156    p->SamplersUsed = (1 << samplerIndex);
00157 
00158    stfp = (struct st_fragment_program *) p;
00159    stfp->Base.UsesKill = GL_TRUE;
00160    st_translate_fragment_program(ctx->st, stfp, NULL);
00161 
00162    return stfp;
00163 }
00164 
00165 
00166 static int
00167 find_free_bit(uint bitfield)
00168 {
00169    int i;
00170    for (i = 0; i < 32; i++) {
00171       if ((bitfield & (1 << i)) == 0) {
00172          return i;
00173       }
00174    }
00175    return -1;
00176 }
00177 
00178 
00182 static struct st_fragment_program *
00183 combined_bitmap_fragment_program(GLcontext *ctx)
00184 {
00185    struct st_context *st = ctx->st;
00186    struct st_fragment_program *stfp = st->fp;
00187 
00188    if (!stfp->bitmap_program) {
00189       /*
00190        * Generate new program which is the user-defined program prefixed
00191        * with the bitmap sampler/kill instructions.
00192        */
00193       struct st_fragment_program *bitmap_prog;
00194       uint sampler;
00195 
00196       sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
00197       bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
00198 
00199       stfp->bitmap_program = (struct st_fragment_program *)
00200          _mesa_combine_programs(ctx,
00201                                 &bitmap_prog->Base.Base, &stfp->Base.Base);
00202       stfp->bitmap_program->bitmap_sampler = sampler;
00203 
00204       /* done with this after combining */
00205       st_reference_fragprog(st, &bitmap_prog, NULL);
00206 
00207 #if 0
00208       {
00209          struct gl_program *p = &stfp->bitmap_program->Base.Base;
00210          printf("Combined bitmap program:\n");
00211          _mesa_print_program(p);
00212          printf("InputsRead: 0x%x\n", p->InputsRead);
00213          printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
00214          _mesa_print_parameter_list(p->Parameters);
00215       }
00216 #endif
00217 
00218       /* translate to TGSI tokens */
00219       st_translate_fragment_program(st, stfp->bitmap_program, NULL);
00220    }
00221 
00222    return stfp->bitmap_program;
00223 }
00224 
00225 
00234 static void
00235 unpack_bitmap(struct st_context *st,
00236               GLint px, GLint py, GLsizei width, GLsizei height,
00237               const struct gl_pixelstore_attrib *unpack,
00238               const GLubyte *bitmap,
00239               ubyte *destBuffer, uint destStride)
00240 {
00241    GLint row, col;
00242 
00243 #define SET_PIXEL(COL, ROW) \
00244    destBuffer[(py + (ROW)) * destStride + px + (COL)] = 0x0;
00245 
00246    for (row = 0; row < height; row++) {
00247       const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
00248                  bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
00249 
00250       if (unpack->LsbFirst) {
00251          /* Lsb first */
00252          GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
00253          for (col = 0; col < width; col++) {
00254 
00255             if (*src & mask) {
00256                SET_PIXEL(col, row);
00257             }
00258 
00259             if (mask == 128U) {
00260                src++;
00261                mask = 1U;
00262             }
00263             else {
00264                mask = mask << 1;
00265             }
00266          }
00267 
00268          /* get ready for next row */
00269          if (mask != 1)
00270             src++;
00271       }
00272       else {
00273          /* Msb first */
00274          GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
00275          for (col = 0; col < width; col++) {
00276 
00277             if (*src & mask) {
00278                SET_PIXEL(col, row);
00279             }
00280 
00281             if (mask == 1U) {
00282                src++;
00283                mask = 128U;
00284             }
00285             else {
00286                mask = mask >> 1;
00287             }
00288          }
00289 
00290          /* get ready for next row */
00291          if (mask != 128)
00292             src++;
00293       }
00294 
00295    } /* row */
00296 
00297 #undef SET_PIXEL
00298 }
00299 
00300 
00304 static struct pipe_texture *
00305 make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
00306                     const struct gl_pixelstore_attrib *unpack,
00307                     const GLubyte *bitmap)
00308 {
00309    struct pipe_context *pipe = ctx->st->pipe;
00310    struct pipe_screen *screen = pipe->screen;
00311    struct pipe_surface *surface;
00312    ubyte *dest;
00313    struct pipe_texture *pt;
00314 
00315    /* PBO source... */
00316    bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap);
00317    if (!bitmap) {
00318       return NULL;
00319    }
00320 
00324    pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format,
00325                           0, width, height, 1, 0,
00326                           PIPE_TEXTURE_USAGE_SAMPLER);
00327    if (!pt) {
00328       _mesa_unmap_bitmap_pbo(ctx, unpack);
00329       return NULL;
00330    }
00331 
00332    surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
00333                                      PIPE_BUFFER_USAGE_CPU_WRITE);
00334 
00335    /* map texture surface */
00336    dest = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE);
00337 
00338    /* Put image into texture surface */
00339    memset(dest, 0xff, height * surface->stride);
00340    unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
00341                  dest, surface->stride);
00342 
00343    _mesa_unmap_bitmap_pbo(ctx, unpack);
00344 
00345    /* Release surface */
00346    screen->surface_unmap(screen, surface);
00347    pipe_surface_reference(&surface, NULL);
00348 
00349    return pt;
00350 }
00351 
00352 static GLuint
00353 setup_bitmap_vertex_data(struct st_context *st,
00354                          int x, int y, int width, int height,
00355                          float z, const float color[4])
00356 {
00357    struct pipe_context *pipe = st->pipe;
00358    const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
00359    const GLfloat fb_width = (GLfloat)fb->Width;
00360    const GLfloat fb_height = (GLfloat)fb->Height;
00361    const GLfloat x0 = (GLfloat)x;
00362    const GLfloat x1 = (GLfloat)(x + width);
00363    const GLfloat y0 = (GLfloat)y;
00364    const GLfloat y1 = (GLfloat)(y + height);
00365    const GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
00366    const GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
00367    const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
00368    const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
00369    const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
00370    const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
00371    const GLuint max_slots = 4096 / sizeof(st->bitmap.vertices);
00372    GLuint i;
00373 
00374    if (st->bitmap.vbuf_slot >= max_slots) {
00375       pipe_buffer_reference(pipe->screen, &st->bitmap.vbuf, NULL);
00376       st->bitmap.vbuf_slot = 0;
00377    }
00378 
00379    if (!st->bitmap.vbuf) {
00380       st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 32, 
00381                                            PIPE_BUFFER_USAGE_VERTEX,
00382                                            max_slots * sizeof(st->bitmap.vertices));
00383    }
00384 
00385    /* Positions are in clip coords since we need to do clipping in case
00386     * the bitmap quad goes beyond the window bounds.
00387     */
00388    st->bitmap.vertices[0][0][0] = clip_x0;
00389    st->bitmap.vertices[0][0][1] = clip_y0;
00390    st->bitmap.vertices[0][2][0] = sLeft;
00391    st->bitmap.vertices[0][2][1] = tTop;
00392 
00393    st->bitmap.vertices[1][0][0] = clip_x1;
00394    st->bitmap.vertices[1][0][1] = clip_y0;
00395    st->bitmap.vertices[1][2][0] = sRight;
00396    st->bitmap.vertices[1][2][1] = tTop;
00397    
00398    st->bitmap.vertices[2][0][0] = clip_x1;
00399    st->bitmap.vertices[2][0][1] = clip_y1;
00400    st->bitmap.vertices[2][2][0] = sRight;
00401    st->bitmap.vertices[2][2][1] = tBot;
00402    
00403    st->bitmap.vertices[3][0][0] = clip_x0;
00404    st->bitmap.vertices[3][0][1] = clip_y1;
00405    st->bitmap.vertices[3][2][0] = sLeft;
00406    st->bitmap.vertices[3][2][1] = tBot;
00407    
00408    /* same for all verts: */
00409    for (i = 0; i < 4; i++) {
00410       st->bitmap.vertices[i][0][2] = z;
00411       st->bitmap.vertices[i][0][3] = 1.0;
00412       st->bitmap.vertices[i][1][0] = color[0];
00413       st->bitmap.vertices[i][1][1] = color[1];
00414       st->bitmap.vertices[i][1][2] = color[2];
00415       st->bitmap.vertices[i][1][3] = color[3];
00416       st->bitmap.vertices[i][2][2] = 0.0; /*R*/
00417       st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
00418    }
00419 
00420    /* put vertex data into vbuf */
00421    {
00422       char *buf = pipe_buffer_map(pipe->screen, 
00423                                   st->bitmap.vbuf, 
00424                                   PIPE_BUFFER_USAGE_CPU_WRITE);
00425 
00426       memcpy(buf + st->bitmap.vbuf_slot * sizeof st->bitmap.vertices, 
00427              st->bitmap.vertices, 
00428              sizeof st->bitmap.vertices);
00429 
00430       pipe_buffer_unmap(pipe->screen, st->bitmap.vbuf);
00431    }
00432 
00433    return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
00434 }
00435 
00436 
00437 
00441 static void
00442 draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
00443                  GLsizei width, GLsizei height,
00444                  struct pipe_texture *pt,
00445                  const GLfloat *color)
00446 {
00447    struct st_context *st = ctx->st;
00448    struct pipe_context *pipe = ctx->st->pipe;
00449    struct cso_context *cso = ctx->st->cso_context;
00450    struct st_fragment_program *stfp;
00451    GLuint maxSize;
00452    GLuint offset;
00453 
00454    stfp = combined_bitmap_fragment_program(ctx);
00455 
00456    /* As an optimization, Mesa's fragment programs will sometimes get the
00457     * primary color from a statevar/constant rather than a varying variable.
00458     * when that's the case, we need to ensure that we use the 'color'
00459     * parameter and not the current attribute color (which may have changed
00460     * through glRasterPos and state validation.
00461     * So, we force the proper color here.  Not elegant, but it works.
00462     */
00463    {
00464       GLfloat colorSave[4];
00465       COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
00466       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
00467       st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
00468       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
00469    }
00470 
00471 
00472    /* limit checks */
00473    /* XXX if the bitmap is larger than the max texture size, break
00474     * it up into chunks.
00475     */
00476    maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
00477    assert(width <= (GLsizei)maxSize);
00478    assert(height <= (GLsizei)maxSize);
00479 
00480    cso_save_rasterizer(cso);
00481    cso_save_samplers(cso);
00482    cso_save_sampler_textures(cso);
00483    cso_save_viewport(cso);
00484    cso_save_fragment_shader(cso);
00485    cso_save_vertex_shader(cso);
00486 
00487    /* rasterizer state: just scissor */
00488    st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
00489    cso_set_rasterizer(cso, &st->bitmap.rasterizer);
00490 
00491    /* fragment shader state: TEX lookup program */
00492    cso_set_fragment_shader_handle(cso, stfp->driver_shader);
00493 
00494    /* vertex shader state: position + texcoord pass-through */
00495    cso_set_vertex_shader_handle(cso, st->bitmap.vs);
00496 
00497    /* user samplers, plus our bitmap sampler */
00498    {
00499       struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
00500       uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers);
00501       uint i;
00502       for (i = 0; i < st->state.num_samplers; i++) {
00503          samplers[i] = &st->state.samplers[i];
00504       }
00505       samplers[stfp->bitmap_sampler] = &st->bitmap.sampler;
00506       cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
00507    }
00508 
00509    /* user textures, plus the bitmap texture */
00510    {
00511       struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
00512       uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures);
00513       memcpy(textures, st->state.sampler_texture, sizeof(textures));
00514       textures[stfp->bitmap_sampler] = pt;
00515       cso_set_sampler_textures(cso, num, textures);
00516    }
00517 
00518    /* viewport state: viewport matching window dims */
00519    {
00520       const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
00521       const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
00522       const GLfloat width = (GLfloat)fb->Width;
00523       const GLfloat height = (GLfloat)fb->Height;
00524       struct pipe_viewport_state vp;
00525       vp.scale[0] =  0.5f * width;
00526       vp.scale[1] = height * (invert ? -0.5f : 0.5f);
00527       vp.scale[2] = 1.0f;
00528       vp.scale[3] = 1.0f;
00529       vp.translate[0] = 0.5f * width;
00530       vp.translate[1] = 0.5f * height;
00531       vp.translate[2] = 0.0f;
00532       vp.translate[3] = 0.0f;
00533       cso_set_viewport(cso, &vp);
00534    }
00535 
00536    /* draw textured quad */
00537    offset = setup_bitmap_vertex_data(st, x, y, width, height,
00538                                      ctx->Current.RasterPos[2],
00539                                      color);
00540 
00541    util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
00542                            PIPE_PRIM_TRIANGLE_FAN,
00543                            4,  /* verts */
00544                            3); /* attribs/vert */
00545 
00546 
00547    /* restore state */
00548    cso_restore_rasterizer(cso);
00549    cso_restore_samplers(cso);
00550    cso_restore_sampler_textures(cso);
00551    cso_restore_viewport(cso);
00552    cso_restore_fragment_shader(cso);
00553    cso_restore_vertex_shader(cso);
00554 }
00555 
00556 
00557 static void
00558 reset_cache(struct st_context *st)
00559 {
00560    struct pipe_context *pipe = st->pipe;
00561    struct pipe_screen *screen = pipe->screen;
00562    struct bitmap_cache *cache = st->bitmap.cache;
00563 
00564    //memset(cache->buffer, 0xff, sizeof(cache->buffer));
00565    cache->empty = GL_TRUE;
00566 
00567    cache->xmin = 1000000;
00568    cache->xmax = -1000000;
00569    cache->ymin = 1000000;
00570    cache->ymax = -1000000;
00571 
00572    if (cache->surf)
00573       screen->tex_surface_release(screen, &cache->surf);
00574 
00575    assert(!cache->texture);
00576 
00577    /* allocate a new texture */
00578    cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
00579                                       st->bitmap.tex_format, 0,
00580                                       BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
00581                                       1, 0,
00582                                       PIPE_TEXTURE_USAGE_SAMPLER);
00583 
00584    /* Map the texture surface.
00585     * Subsequent glBitmap calls will write into the texture image.
00586     */
00587    cache->surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0,
00588                                          PIPE_BUFFER_USAGE_CPU_WRITE);
00589    cache->buffer = screen->surface_map(screen, cache->surf,
00590                                        PIPE_BUFFER_USAGE_CPU_WRITE);
00591 
00592    /* init image to all 0xff */
00593    memset(cache->buffer, 0xff, BITMAP_CACHE_WIDTH * BITMAP_CACHE_HEIGHT);
00594 }
00595 
00596 
00600 void
00601 st_flush_bitmap_cache(struct st_context *st)
00602 {
00603    if (!st->bitmap.cache->empty) {
00604       struct bitmap_cache *cache = st->bitmap.cache;
00605 
00606       if (st->ctx->DrawBuffer) {
00607          struct pipe_context *pipe = st->pipe;
00608          struct pipe_screen *screen = pipe->screen;
00609 
00610          assert(cache->xmin <= cache->xmax);
00611  
00612 /*         printf("flush size %d x %d  at %d, %d\n",
00613                 cache->xmax - cache->xmin,
00614                 cache->ymax - cache->ymin,
00615                 cache->xpos, cache->ypos);
00616 */
00617 
00618          /* The texture surface has been mapped until now.
00619           * So unmap and release the texture surface before drawing.
00620           */
00621          screen->surface_unmap(screen, cache->surf);
00622          cache->buffer = NULL;
00623 
00624          screen->tex_surface_release(screen, &cache->surf);
00625 
00626          draw_bitmap_quad(st->ctx,
00627                           cache->xpos,
00628                           cache->ypos,
00629                           st->ctx->Current.RasterPos[2],
00630                           BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
00631                           cache->texture,
00632                           cache->color);
00633       }
00634 
00635       /* release/free the texture */
00636       pipe_texture_reference(&cache->texture, NULL);
00637 
00638       reset_cache(st);
00639    }
00640 }
00641 
00642 /* Flush bitmap cache and release vertex buffer.
00643  */
00644 void
00645 st_flush_bitmap( struct st_context *st )
00646 {
00647    st_flush_bitmap_cache(st);
00648 
00649    /* Release vertex buffer to avoid synchronous rendering if we were
00650     * to map it in the next frame.
00651     */
00652    pipe_buffer_reference(st->pipe->screen, &st->bitmap.vbuf, NULL);
00653    st->bitmap.vbuf_slot = 0;
00654 }
00655 
00656 
00661 static GLboolean
00662 accum_bitmap(struct st_context *st,
00663              GLint x, GLint y, GLsizei width, GLsizei height,
00664              const struct gl_pixelstore_attrib *unpack,
00665              const GLubyte *bitmap )
00666 {
00667    struct bitmap_cache *cache = st->bitmap.cache;
00668    int px = -999, py;
00669 
00670    if (width > BITMAP_CACHE_WIDTH ||
00671        height > BITMAP_CACHE_HEIGHT)
00672       return GL_FALSE; /* too big to cache */
00673 
00674    if (!cache->empty) {
00675       px = x - cache->xpos;  /* pos in buffer */
00676       py = y - cache->ypos;
00677       if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
00678           py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
00679           !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color)) {
00680          /* This bitmap would extend beyond cache bounds, or the bitmap
00681           * color is changing
00682           * so flush and continue.
00683           */
00684          st_flush_bitmap_cache(st);
00685       }
00686    }
00687 
00688    if (cache->empty) {
00689       /* Initialize.  Center bitmap vertically in the buffer. */
00690       px = 0;
00691       py = (BITMAP_CACHE_HEIGHT - height) / 2;
00692       cache->xpos = x;
00693       cache->ypos = y - py;
00694       cache->empty = GL_FALSE;
00695       COPY_4FV(cache->color, st->ctx->Current.RasterColor);
00696    }
00697 
00698    assert(px != -999);
00699 
00700    if (x < cache->xmin)
00701       cache->xmin = x;
00702    if (y < cache->ymin)
00703       cache->ymin = y;
00704    if (x + width > cache->xmax)
00705       cache->xmax = x + width;
00706    if (y + height > cache->ymax)
00707       cache->ymax = y + height;
00708 
00709    unpack_bitmap(st, px, py, width, height, unpack, bitmap,
00710                  cache->buffer, BITMAP_CACHE_WIDTH);
00711 
00712    return GL_TRUE; /* accumulated */
00713 }
00714 
00715 
00716 
00720 static void
00721 st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
00722           const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
00723 {
00724    struct st_context *st = ctx->st;
00725    struct pipe_texture *pt;
00726 
00727    if (width == 0 || height == 0)
00728       return;
00729 
00730    st_validate_state(st);
00731 
00732    if (!st->bitmap.vs) {
00733       /* create pass-through vertex shader now */
00734       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
00735                                       TGSI_SEMANTIC_COLOR,
00736                                       TGSI_SEMANTIC_GENERIC };
00737       const uint semantic_indexes[] = { 0, 0, 0 };
00738       st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
00739                                                           semantic_names,
00740                                                           semantic_indexes,
00741                                                           &st->bitmap.vert_shader);
00742    }
00743 
00744    if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
00745       return;
00746 
00747    pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
00748    if (pt) {
00749       assert(pt->target == PIPE_TEXTURE_2D);
00750       draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
00751                        width, height, pt,
00752                        st->ctx->Current.RasterColor);
00753       /* release/free the texture */
00754       pipe_texture_reference(&pt, NULL);
00755    }
00756 }
00757 
00758 
00760 void
00761 st_init_bitmap_functions(struct dd_function_table *functions)
00762 {
00763    functions->Bitmap = st_Bitmap;
00764 }
00765 
00766 
00768 void
00769 st_init_bitmap(struct st_context *st)
00770 {
00771    struct pipe_sampler_state *sampler = &st->bitmap.sampler;
00772    struct pipe_context *pipe = st->pipe;
00773    struct pipe_screen *screen = pipe->screen;
00774 
00775    /* init sampler state once */
00776    memset(sampler, 0, sizeof(*sampler));
00777    sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
00778    sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
00779    sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
00780    sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
00781    sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
00782    sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
00783    sampler->normalized_coords = 1;
00784 
00785    /* init baseline rasterizer state once */
00786    memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
00787    st->bitmap.rasterizer.gl_rasterization_rules = 1;
00788    st->bitmap.rasterizer.bypass_vs = 1;
00789 
00790    /* find a usable texture format */
00791    if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D, 
00792                                    PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
00793       st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
00794    }
00795    else {
00796       /* XXX support more formats */
00797       assert(0);
00798    }
00799 
00800    /* alloc bitmap cache object */
00801    st->bitmap.cache = CALLOC_STRUCT(bitmap_cache);
00802 
00803    reset_cache(st);
00804 }
00805 
00806 
00808 void
00809 st_destroy_bitmap(struct st_context *st)
00810 {
00811    struct pipe_context *pipe = st->pipe;
00812    struct pipe_screen *screen = pipe->screen;
00813    struct bitmap_cache *cache = st->bitmap.cache;
00814 
00815    screen->surface_unmap(screen, cache->surf);
00816    screen->tex_surface_release(screen, &cache->surf);
00817 
00818    if (st->bitmap.vs) {
00819       cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
00820       st->bitmap.vs = NULL;
00821    }
00822    util_free_shader(&st->bitmap.vert_shader);
00823 
00824    if (st->bitmap.vbuf) {
00825       pipe_buffer_destroy(pipe->screen, st->bitmap.vbuf);
00826       st->bitmap.vbuf = NULL;
00827    }
00828 
00829    if (st->bitmap.cache) {
00830       pipe_texture_release(&st->bitmap.cache->texture);
00831       FREE(st->bitmap.cache);
00832       st->bitmap.cache = NULL;
00833    }
00834 }

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