Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  /*
  29.   * Authors:
  30.   *   Brian Paul
  31.   */
  32.  
  33. #include "main/imports.h"
  34. #include "main/image.h"
  35. #include "main/bufferobj.h"
  36. #include "main/macros.h"
  37. #include "program/program.h"
  38. #include "program/prog_print.h"
  39.  
  40. #include "st_context.h"
  41. #include "st_atom.h"
  42. #include "st_atom_constbuf.h"
  43. #include "st_program.h"
  44. #include "st_cb_bitmap.h"
  45. #include "st_texture.h"
  46.  
  47. #include "pipe/p_context.h"
  48. #include "pipe/p_defines.h"
  49. #include "pipe/p_shader_tokens.h"
  50. #include "util/u_inlines.h"
  51. #include "util/u_draw_quad.h"
  52. #include "util/u_simple_shaders.h"
  53. #include "program/prog_instruction.h"
  54. #include "cso_cache/cso_context.h"
  55.  
  56.  
  57. #if FEATURE_drawpix
  58.  
  59. /**
  60.  * glBitmaps are drawn as textured quads.  The user's bitmap pattern
  61.  * is stored in a texture image.  An alpha8 texture format is used.
  62.  * The fragment shader samples a bit (texel) from the texture, then
  63.  * discards the fragment if the bit is off.
  64.  *
  65.  * Note that we actually store the inverse image of the bitmap to
  66.  * simplify the fragment program.  An "on" bit gets stored as texel=0x0
  67.  * and an "off" bit is stored as texel=0xff.  Then we kill the
  68.  * fragment if the negated texel value is less than zero.
  69.  */
  70.  
  71.  
  72. /**
  73.  * The bitmap cache attempts to accumulate multiple glBitmap calls in a
  74.  * buffer which is then rendered en mass upon a flush, state change, etc.
  75.  * A wide, short buffer is used to target the common case of a series
  76.  * of glBitmap calls being used to draw text.
  77.  */
  78. static GLboolean UseBitmapCache = GL_TRUE;
  79.  
  80.  
  81. #define BITMAP_CACHE_WIDTH  512
  82. #define BITMAP_CACHE_HEIGHT 32
  83.  
  84. struct bitmap_cache
  85. {
  86.    /** Window pos to render the cached image */
  87.    GLint xpos, ypos;
  88.    /** Bounds of region used in window coords */
  89.    GLint xmin, ymin, xmax, ymax;
  90.  
  91.    GLfloat color[4];
  92.  
  93.    /** Bitmap's Z position */
  94.    GLfloat zpos;
  95.  
  96.    struct pipe_resource *texture;
  97.    struct pipe_transfer *trans;
  98.  
  99.    GLboolean empty;
  100.  
  101.    /** An I8 texture image: */
  102.    ubyte *buffer;
  103. };
  104.  
  105.  
  106. /** Epsilon for Z comparisons */
  107. #define Z_EPSILON 1e-06
  108.  
  109.  
  110. /**
  111.  * Make fragment program for glBitmap:
  112.  *   Sample the texture and kill the fragment if the bit is 0.
  113.  * This program will be combined with the user's fragment program.
  114.  */
  115. static struct st_fragment_program *
  116. make_bitmap_fragment_program(struct gl_context *ctx, GLuint samplerIndex)
  117. {
  118.    struct st_context *st = st_context(ctx);
  119.    struct st_fragment_program *stfp;
  120.    struct gl_program *p;
  121.    GLuint ic = 0;
  122.  
  123.    p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
  124.    if (!p)
  125.       return NULL;
  126.  
  127.    p->NumInstructions = 3;
  128.  
  129.    p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
  130.    if (!p->Instructions) {
  131.       ctx->Driver.DeleteProgram(ctx, p);
  132.       return NULL;
  133.    }
  134.    _mesa_init_instructions(p->Instructions, p->NumInstructions);
  135.  
  136.    /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
  137.    p->Instructions[ic].Opcode = OPCODE_TEX;
  138.    p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
  139.    p->Instructions[ic].DstReg.Index = 0;
  140.    p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
  141.    p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
  142.    p->Instructions[ic].TexSrcUnit = samplerIndex;
  143.    p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
  144.    ic++;
  145.  
  146.    /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
  147.    p->Instructions[ic].Opcode = OPCODE_KIL;
  148.    p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
  149.  
  150.    if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
  151.       p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
  152.  
  153.    p->Instructions[ic].SrcReg[0].Index = 0;
  154.    p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
  155.    ic++;
  156.  
  157.    /* END; */
  158.    p->Instructions[ic++].Opcode = OPCODE_END;
  159.  
  160.    assert(ic == p->NumInstructions);
  161.  
  162.    p->InputsRead = FRAG_BIT_TEX0;
  163.    p->OutputsWritten = 0x0;
  164.    p->SamplersUsed = (1 << samplerIndex);
  165.  
  166.    stfp = (struct st_fragment_program *) p;
  167.    stfp->Base.UsesKill = GL_TRUE;
  168.  
  169.    return stfp;
  170. }
  171.  
  172.  
  173. static int
  174. find_free_bit(uint bitfield)
  175. {
  176.    int i;
  177.    for (i = 0; i < 32; i++) {
  178.       if ((bitfield & (1 << i)) == 0) {
  179.          return i;
  180.       }
  181.    }
  182.    return -1;
  183. }
  184.  
  185.  
  186. /**
  187.  * Combine basic bitmap fragment program with the user-defined program.
  188.  */
  189. static struct st_fragment_program *
  190. combined_bitmap_fragment_program(struct gl_context *ctx)
  191. {
  192.    struct st_context *st = st_context(ctx);
  193.    struct st_fragment_program *stfp = st->fp;
  194.  
  195.    if (!stfp->bitmap_program) {
  196.       /*
  197.        * Generate new program which is the user-defined program prefixed
  198.        * with the bitmap sampler/kill instructions.
  199.        */
  200.       struct st_fragment_program *bitmap_prog;
  201.       uint sampler;
  202.  
  203.       sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
  204.       bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
  205.  
  206.       stfp->bitmap_program = (struct st_fragment_program *)
  207.          _mesa_combine_programs(ctx,
  208.                                 &bitmap_prog->Base.Base, &stfp->Base.Base);
  209.       stfp->bitmap_program->bitmap_sampler = sampler;
  210.  
  211.       /* done with this after combining */
  212.       st_reference_fragprog(st, &bitmap_prog, NULL);
  213.  
  214. #if 0
  215.       {
  216.          struct gl_program *p = &stfp->bitmap_program->Base.Base;
  217.          printf("Combined bitmap program:\n");
  218.          _mesa_print_program(p);
  219.          printf("InputsRead: 0x%x\n", p->InputsRead);
  220.          printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
  221.          _mesa_print_parameter_list(p->Parameters);
  222.       }
  223. #endif
  224.  
  225.       /* translate to TGSI tokens */
  226.       st_translate_fragment_program(st, stfp->bitmap_program);
  227.    }
  228.  
  229.    return stfp->bitmap_program;
  230. }
  231.  
  232.  
  233. /**
  234.  * Copy user-provide bitmap bits into texture buffer, expanding
  235.  * bits into texels.
  236.  * "On" bits will set texels to 0x0.
  237.  * "Off" bits will not modify texels.
  238.  * Note that the image is actually going to be upside down in
  239.  * the texture.  We deal with that with texcoords.
  240.  */
  241. static void
  242. unpack_bitmap(struct st_context *st,
  243.               GLint px, GLint py, GLsizei width, GLsizei height,
  244.               const struct gl_pixelstore_attrib *unpack,
  245.               const GLubyte *bitmap,
  246.               ubyte *destBuffer, uint destStride)
  247. {
  248.    destBuffer += py * destStride + px;
  249.  
  250.    _mesa_expand_bitmap(width, height, unpack, bitmap,
  251.                        destBuffer, destStride, 0x0);
  252. }
  253.  
  254.  
  255. /**
  256.  * Create a texture which represents a bitmap image.
  257.  */
  258. static struct pipe_resource *
  259. make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
  260.                     const struct gl_pixelstore_attrib *unpack,
  261.                     const GLubyte *bitmap)
  262. {
  263.    struct st_context *st = st_context(ctx);
  264.    struct pipe_context *pipe = st->pipe;
  265.    struct pipe_transfer *transfer;
  266.    ubyte *dest;
  267.    struct pipe_resource *pt;
  268.  
  269.    /* PBO source... */
  270.    bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
  271.    if (!bitmap) {
  272.       return NULL;
  273.    }
  274.  
  275.    /**
  276.     * Create texture to hold bitmap pattern.
  277.     */
  278.    pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
  279.                           0, width, height, 1,
  280.                           PIPE_BIND_SAMPLER_VIEW);
  281.    if (!pt) {
  282.       _mesa_unmap_pbo_source(ctx, unpack);
  283.       return NULL;
  284.    }
  285.  
  286.    transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
  287.                                 PIPE_TRANSFER_WRITE,
  288.                                 0, 0, width, height);
  289.  
  290.    dest = pipe_transfer_map(pipe, transfer);
  291.  
  292.    /* Put image into texture transfer */
  293.    memset(dest, 0xff, height * transfer->stride);
  294.    unpack_bitmap(st, 0, 0, width, height, unpack, bitmap,
  295.                  dest, transfer->stride);
  296.  
  297.    _mesa_unmap_pbo_source(ctx, unpack);
  298.  
  299.    /* Release transfer */
  300.    pipe_transfer_unmap(pipe, transfer);
  301.    pipe->transfer_destroy(pipe, transfer);
  302.  
  303.    return pt;
  304. }
  305.  
  306. static GLuint
  307. setup_bitmap_vertex_data(struct st_context *st, bool normalized,
  308.                          int x, int y, int width, int height,
  309.                          float z, const float color[4])
  310. {
  311.    struct pipe_context *pipe = st->pipe;
  312.    const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
  313.    const GLfloat fb_width = (GLfloat)fb->Width;
  314.    const GLfloat fb_height = (GLfloat)fb->Height;
  315.    const GLfloat x0 = (GLfloat)x;
  316.    const GLfloat x1 = (GLfloat)(x + width);
  317.    const GLfloat y0 = (GLfloat)y;
  318.    const GLfloat y1 = (GLfloat)(y + height);
  319.    GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
  320.    GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
  321.    const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
  322.    const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
  323.    const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
  324.    const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
  325.    const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
  326.    GLuint i;
  327.  
  328.    if(!normalized)
  329.    {
  330.       sRight = width;
  331.       tBot = height;
  332.    }
  333.  
  334.    /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
  335.     * no_flush) updates to buffers where we know there is no conflict
  336.     * with previous data.  Currently using max_slots > 1 will cause
  337.     * synchronous rendering if the driver flushes its command buffers
  338.     * between one bitmap and the next.  Our flush hook below isn't
  339.     * sufficient to catch this as the driver doesn't tell us when it
  340.     * flushes its own command buffers.  Until this gets fixed, pay the
  341.     * price of allocating a new buffer for each bitmap cache-flush to
  342.     * avoid synchronous rendering.
  343.     */
  344.    if (st->bitmap.vbuf_slot >= max_slots) {
  345.       pipe_resource_reference(&st->bitmap.vbuf, NULL);
  346.       st->bitmap.vbuf_slot = 0;
  347.    }
  348.  
  349.    if (!st->bitmap.vbuf) {
  350.       st->bitmap.vbuf = pipe_buffer_create(pipe->screen,
  351.                                            PIPE_BIND_VERTEX_BUFFER,
  352.                                            max_slots * sizeof(st->bitmap.vertices));
  353.    }
  354.  
  355.    /* Positions are in clip coords since we need to do clipping in case
  356.     * the bitmap quad goes beyond the window bounds.
  357.     */
  358.    st->bitmap.vertices[0][0][0] = clip_x0;
  359.    st->bitmap.vertices[0][0][1] = clip_y0;
  360.    st->bitmap.vertices[0][2][0] = sLeft;
  361.    st->bitmap.vertices[0][2][1] = tTop;
  362.  
  363.    st->bitmap.vertices[1][0][0] = clip_x1;
  364.    st->bitmap.vertices[1][0][1] = clip_y0;
  365.    st->bitmap.vertices[1][2][0] = sRight;
  366.    st->bitmap.vertices[1][2][1] = tTop;
  367.    
  368.    st->bitmap.vertices[2][0][0] = clip_x1;
  369.    st->bitmap.vertices[2][0][1] = clip_y1;
  370.    st->bitmap.vertices[2][2][0] = sRight;
  371.    st->bitmap.vertices[2][2][1] = tBot;
  372.    
  373.    st->bitmap.vertices[3][0][0] = clip_x0;
  374.    st->bitmap.vertices[3][0][1] = clip_y1;
  375.    st->bitmap.vertices[3][2][0] = sLeft;
  376.    st->bitmap.vertices[3][2][1] = tBot;
  377.    
  378.    /* same for all verts: */
  379.    for (i = 0; i < 4; i++) {
  380.       st->bitmap.vertices[i][0][2] = z;
  381.       st->bitmap.vertices[i][0][3] = 1.0;
  382.       st->bitmap.vertices[i][1][0] = color[0];
  383.       st->bitmap.vertices[i][1][1] = color[1];
  384.       st->bitmap.vertices[i][1][2] = color[2];
  385.       st->bitmap.vertices[i][1][3] = color[3];
  386.       st->bitmap.vertices[i][2][2] = 0.0; /*R*/
  387.       st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
  388.    }
  389.  
  390.    /* put vertex data into vbuf */
  391.    pipe_buffer_write_nooverlap(st->pipe,
  392.                                            st->bitmap.vbuf,
  393.                                            st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
  394.                                            sizeof st->bitmap.vertices,
  395.                                            st->bitmap.vertices);
  396.  
  397.    return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
  398. }
  399.  
  400.  
  401.  
  402. /**
  403.  * Render a glBitmap by drawing a textured quad
  404.  */
  405. static void
  406. draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
  407.                  GLsizei width, GLsizei height,
  408.                  struct pipe_sampler_view *sv,
  409.                  const GLfloat *color)
  410. {
  411.    struct st_context *st = st_context(ctx);
  412.    struct pipe_context *pipe = st->pipe;
  413.    struct cso_context *cso = st->cso_context;
  414.    struct st_fragment_program *stfp;
  415.    GLuint maxSize;
  416.    GLuint offset;
  417.  
  418.    stfp = combined_bitmap_fragment_program(ctx);
  419.  
  420.    /* As an optimization, Mesa's fragment programs will sometimes get the
  421.     * primary color from a statevar/constant rather than a varying variable.
  422.     * when that's the case, we need to ensure that we use the 'color'
  423.     * parameter and not the current attribute color (which may have changed
  424.     * through glRasterPos and state validation.
  425.     * So, we force the proper color here.  Not elegant, but it works.
  426.     */
  427.    {
  428.       GLfloat colorSave[4];
  429.       COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
  430.       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
  431.       st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
  432.       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
  433.    }
  434.  
  435.  
  436.    /* limit checks */
  437.    /* XXX if the bitmap is larger than the max texture size, break
  438.     * it up into chunks.
  439.     */
  440.    maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
  441.    assert(width <= (GLsizei)maxSize);
  442.    assert(height <= (GLsizei)maxSize);
  443.  
  444.    cso_save_rasterizer(cso);
  445.    cso_save_samplers(cso);
  446.    cso_save_fragment_sampler_views(cso);
  447.    cso_save_viewport(cso);
  448.    cso_save_fragment_shader(cso);
  449.    cso_save_vertex_shader(cso);
  450.    cso_save_vertex_elements(cso);
  451.  
  452.    /* rasterizer state: just scissor */
  453.    st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
  454.    cso_set_rasterizer(cso, &st->bitmap.rasterizer);
  455.  
  456.    /* fragment shader state: TEX lookup program */
  457.    cso_set_fragment_shader_handle(cso, stfp->driver_shader);
  458.  
  459.    /* vertex shader state: position + texcoord pass-through */
  460.    cso_set_vertex_shader_handle(cso, st->bitmap.vs);
  461.  
  462.    /* user samplers, plus our bitmap sampler */
  463.    {
  464.       struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
  465.       uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers);
  466.       uint i;
  467.       for (i = 0; i < st->state.num_samplers; i++) {
  468.          samplers[i] = &st->state.samplers[i];
  469.       }
  470.       samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
  471.       cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
  472.    }
  473.  
  474.    /* user textures, plus the bitmap texture */
  475.    {
  476.       struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
  477.       uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures);
  478.       memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views));
  479.       sampler_views[stfp->bitmap_sampler] = sv;
  480.       cso_set_fragment_sampler_views(cso, num, sampler_views);
  481.    }
  482.  
  483.    /* viewport state: viewport matching window dims */
  484.    {
  485.       const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
  486.       const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
  487.       const GLfloat width = (GLfloat)fb->Width;
  488.       const GLfloat height = (GLfloat)fb->Height;
  489.       struct pipe_viewport_state vp;
  490.       vp.scale[0] =  0.5f * width;
  491.       vp.scale[1] = height * (invert ? -0.5f : 0.5f);
  492.       vp.scale[2] = 0.5f;
  493.       vp.scale[3] = 1.0f;
  494.       vp.translate[0] = 0.5f * width;
  495.       vp.translate[1] = 0.5f * height;
  496.       vp.translate[2] = 0.5f;
  497.       vp.translate[3] = 0.0f;
  498.       cso_set_viewport(cso, &vp);
  499.    }
  500.  
  501.    cso_set_vertex_elements(cso, 3, st->velems_util_draw);
  502.  
  503.    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
  504.    z = z * 2.0 - 1.0;
  505.  
  506.    /* draw textured quad */
  507.    offset = setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color);
  508.  
  509.    util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
  510.                            PIPE_PRIM_TRIANGLE_FAN,
  511.                            4,  /* verts */
  512.                            3); /* attribs/vert */
  513.  
  514.  
  515.    /* restore state */
  516.    cso_restore_rasterizer(cso);
  517.    cso_restore_samplers(cso);
  518.    cso_restore_fragment_sampler_views(cso);
  519.    cso_restore_viewport(cso);
  520.    cso_restore_fragment_shader(cso);
  521.    cso_restore_vertex_shader(cso);
  522.    cso_restore_vertex_elements(cso);
  523. }
  524.  
  525.  
  526. static void
  527. reset_cache(struct st_context *st)
  528. {
  529.    struct pipe_context *pipe = st->pipe;
  530.    struct bitmap_cache *cache = st->bitmap.cache;
  531.  
  532.    /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/
  533.    cache->empty = GL_TRUE;
  534.  
  535.    cache->xmin = 1000000;
  536.    cache->xmax = -1000000;
  537.    cache->ymin = 1000000;
  538.    cache->ymax = -1000000;
  539.  
  540.    if (cache->trans) {
  541.       pipe->transfer_destroy(pipe, cache->trans);
  542.       cache->trans = NULL;
  543.    }
  544.  
  545.    assert(!cache->texture);
  546.  
  547.    /* allocate a new texture */
  548.    cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
  549.                                       st->bitmap.tex_format, 0,
  550.                                       BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
  551.                                       1,
  552.                                       PIPE_BIND_SAMPLER_VIEW);
  553. }
  554.  
  555.  
  556. /** Print bitmap image to stdout (debug) */
  557. static void
  558. print_cache(const struct bitmap_cache *cache)
  559. {
  560.    int i, j, k;
  561.  
  562.    for (i = 0; i < BITMAP_CACHE_HEIGHT; i++) {
  563.       k = BITMAP_CACHE_WIDTH * (BITMAP_CACHE_HEIGHT - i - 1);
  564.       for (j = 0; j < BITMAP_CACHE_WIDTH; j++) {
  565.          if (cache->buffer[k])
  566.             printf("X");
  567.          else
  568.             printf(" ");
  569.          k++;
  570.       }
  571.       printf("\n");
  572.    }
  573. }
  574.  
  575.  
  576. static void
  577. create_cache_trans(struct st_context *st)
  578. {
  579.    struct pipe_context *pipe = st->pipe;
  580.    struct bitmap_cache *cache = st->bitmap.cache;
  581.  
  582.    if (cache->trans)
  583.       return;
  584.  
  585.    /* Map the texture transfer.
  586.     * Subsequent glBitmap calls will write into the texture image.
  587.     */
  588.    cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0,
  589.                                     PIPE_TRANSFER_WRITE, 0, 0,
  590.                                     BITMAP_CACHE_WIDTH,
  591.                                     BITMAP_CACHE_HEIGHT);
  592.    cache->buffer = pipe_transfer_map(pipe, cache->trans);
  593.  
  594.    /* init image to all 0xff */
  595.    memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
  596. }
  597.  
  598.  
  599. /**
  600.  * If there's anything in the bitmap cache, draw/flush it now.
  601.  */
  602. void
  603. st_flush_bitmap_cache(struct st_context *st)
  604. {
  605.    if (!st->bitmap.cache->empty) {
  606.       struct bitmap_cache *cache = st->bitmap.cache;
  607.  
  608.       if (st->ctx->DrawBuffer) {
  609.          struct pipe_context *pipe = st->pipe;
  610.          struct pipe_sampler_view *sv;
  611.  
  612.          assert(cache->xmin <= cache->xmax);
  613.  
  614. /*         printf("flush size %d x %d  at %d, %d\n",
  615.                 cache->xmax - cache->xmin,
  616.                 cache->ymax - cache->ymin,
  617.                 cache->xpos, cache->ypos);
  618. */
  619.  
  620.          /* The texture transfer has been mapped until now.
  621.           * So unmap and release the texture transfer before drawing.
  622.           */
  623.          if (cache->trans) {
  624.             if (0)
  625.                print_cache(cache);
  626.             pipe_transfer_unmap(pipe, cache->trans);
  627.             cache->buffer = NULL;
  628.  
  629.             pipe->transfer_destroy(pipe, cache->trans);
  630.             cache->trans = NULL;
  631.          }
  632.  
  633.          sv = st_create_texture_sampler_view(st->pipe, cache->texture);
  634.          if (sv) {
  635.             draw_bitmap_quad(st->ctx,
  636.                              cache->xpos,
  637.                              cache->ypos,
  638.                              cache->zpos,
  639.                              BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
  640.                              sv,
  641.                              cache->color);
  642.  
  643.             pipe_sampler_view_reference(&sv, NULL);
  644.          }
  645.       }
  646.  
  647.       /* release/free the texture */
  648.       pipe_resource_reference(&cache->texture, NULL);
  649.  
  650.       reset_cache(st);
  651.    }
  652. }
  653.  
  654. /* Flush bitmap cache and release vertex buffer.
  655.  */
  656. void
  657. st_flush_bitmap( struct st_context *st )
  658. {
  659.    st_flush_bitmap_cache(st);
  660.  
  661.    /* Release vertex buffer to avoid synchronous rendering if we were
  662.     * to map it in the next frame.
  663.     */
  664.    pipe_resource_reference(&st->bitmap.vbuf, NULL);
  665.    st->bitmap.vbuf_slot = 0;
  666. }
  667.  
  668.  
  669. /**
  670.  * Try to accumulate this glBitmap call in the bitmap cache.
  671.  * \return  GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
  672.  */
  673. static GLboolean
  674. accum_bitmap(struct st_context *st,
  675.              GLint x, GLint y, GLsizei width, GLsizei height,
  676.              const struct gl_pixelstore_attrib *unpack,
  677.              const GLubyte *bitmap )
  678. {
  679.    struct bitmap_cache *cache = st->bitmap.cache;
  680.    int px = -999, py = -999;
  681.    const GLfloat z = st->ctx->Current.RasterPos[2];
  682.  
  683.    if (width > BITMAP_CACHE_WIDTH ||
  684.        height > BITMAP_CACHE_HEIGHT)
  685.       return GL_FALSE; /* too big to cache */
  686.  
  687.    if (!cache->empty) {
  688.       px = x - cache->xpos;  /* pos in buffer */
  689.       py = y - cache->ypos;
  690.       if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
  691.           py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
  692.           !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
  693.           ((fabs(z - cache->zpos) > Z_EPSILON))) {
  694.          /* This bitmap would extend beyond cache bounds, or the bitmap
  695.           * color is changing
  696.           * so flush and continue.
  697.           */
  698.          st_flush_bitmap_cache(st);
  699.       }
  700.    }
  701.  
  702.    if (cache->empty) {
  703.       /* Initialize.  Center bitmap vertically in the buffer. */
  704.       px = 0;
  705.       py = (BITMAP_CACHE_HEIGHT - height) / 2;
  706.       cache->xpos = x;
  707.       cache->ypos = y - py;
  708.       cache->zpos = z;
  709.       cache->empty = GL_FALSE;
  710.       COPY_4FV(cache->color, st->ctx->Current.RasterColor);
  711.    }
  712.  
  713.    assert(px != -999);
  714.    assert(py != -999);
  715.  
  716.    if (x < cache->xmin)
  717.       cache->xmin = x;
  718.    if (y < cache->ymin)
  719.       cache->ymin = y;
  720.    if (x + width > cache->xmax)
  721.       cache->xmax = x + width;
  722.    if (y + height > cache->ymax)
  723.       cache->ymax = y + height;
  724.  
  725.    /* create the transfer if needed */
  726.    create_cache_trans(st);
  727.  
  728.    unpack_bitmap(st, px, py, width, height, unpack, bitmap,
  729.                  cache->buffer, BITMAP_CACHE_WIDTH);
  730.  
  731.    return GL_TRUE; /* accumulated */
  732. }
  733.  
  734.  
  735.  
  736. /**
  737.  * Called via ctx->Driver.Bitmap()
  738.  */
  739. static void
  740. st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
  741.           const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
  742. {
  743.    struct st_context *st = st_context(ctx);
  744.    struct pipe_resource *pt;
  745.  
  746.    if (width == 0 || height == 0)
  747.       return;
  748.  
  749.    st_validate_state(st);
  750.  
  751.    if (!st->bitmap.vs) {
  752.       /* create pass-through vertex shader now */
  753.       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
  754.                                       TGSI_SEMANTIC_COLOR,
  755.                                       TGSI_SEMANTIC_GENERIC };
  756.       const uint semantic_indexes[] = { 0, 0, 0 };
  757.       st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
  758.                                                           semantic_names,
  759.                                                           semantic_indexes);
  760.    }
  761.  
  762.    if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
  763.       return;
  764.  
  765.    pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
  766.    if (pt) {
  767.       struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt);
  768.  
  769.       assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
  770.  
  771.       if (sv) {
  772.          draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
  773.                           width, height, sv,
  774.                           st->ctx->Current.RasterColor);
  775.  
  776.          pipe_sampler_view_reference(&sv, NULL);
  777.       }
  778.  
  779.       /* release/free the texture */
  780.       pipe_resource_reference(&pt, NULL);
  781.    }
  782. }
  783.  
  784.  
  785. /** Per-context init */
  786. void
  787. st_init_bitmap_functions(struct dd_function_table *functions)
  788. {
  789.    functions->Bitmap = st_Bitmap;
  790. }
  791.  
  792.  
  793. /** Per-context init */
  794. void
  795. st_init_bitmap(struct st_context *st)
  796. {
  797.    struct pipe_sampler_state *sampler = &st->bitmap.samplers[0];
  798.    struct pipe_context *pipe = st->pipe;
  799.    struct pipe_screen *screen = pipe->screen;
  800.  
  801.    /* init sampler state once */
  802.    memset(sampler, 0, sizeof(*sampler));
  803.    sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
  804.    sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
  805.    sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
  806.    sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
  807.    sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  808.    sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
  809.    st->bitmap.samplers[1] = *sampler;
  810.    st->bitmap.samplers[1].normalized_coords = 1;
  811.  
  812.    /* init baseline rasterizer state once */
  813.    memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
  814.    st->bitmap.rasterizer.gl_rasterization_rules = 1;
  815.  
  816.    /* find a usable texture format */
  817.    if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D, 0,
  818.                                    PIPE_BIND_SAMPLER_VIEW, 0)) {
  819.       st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
  820.    }
  821.    else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, PIPE_TEXTURE_2D, 0,
  822.                                         PIPE_BIND_SAMPLER_VIEW, 0)) {
  823.       st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM;
  824.    }
  825.    else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, PIPE_TEXTURE_2D, 0,
  826.                                         PIPE_BIND_SAMPLER_VIEW, 0)) {
  827.       st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM;
  828.    }
  829.    else {
  830.       /* XXX support more formats */
  831.       assert(0);
  832.    }
  833.  
  834.    /* alloc bitmap cache object */
  835.    st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache);
  836.  
  837.    reset_cache(st);
  838. }
  839.  
  840.  
  841. /** Per-context tear-down */
  842. void
  843. st_destroy_bitmap(struct st_context *st)
  844. {
  845.    struct pipe_context *pipe = st->pipe;
  846.    struct bitmap_cache *cache = st->bitmap.cache;
  847.  
  848.  
  849.  
  850.    if (st->bitmap.vs) {
  851.       cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
  852.       st->bitmap.vs = NULL;
  853.    }
  854.  
  855.    if (st->bitmap.vbuf) {
  856.       pipe_resource_reference(&st->bitmap.vbuf, NULL);
  857.       st->bitmap.vbuf = NULL;
  858.    }
  859.  
  860.    if (cache) {
  861.       if (cache->trans) {
  862.          pipe_transfer_unmap(pipe, cache->trans);
  863.          pipe->transfer_destroy(pipe, cache->trans);
  864.       }
  865.       pipe_resource_reference(&st->bitmap.cache->texture, NULL);
  866.       free(st->bitmap.cache);
  867.       st->bitmap.cache = NULL;
  868.    }
  869. }
  870.  
  871. #endif /* FEATURE_drawpix */
  872.