Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | 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 "main/pbo.h"
  38. #include "program/program.h"
  39. #include "program/prog_print.h"
  40.  
  41. #include "st_context.h"
  42. #include "st_atom.h"
  43. #include "st_atom_constbuf.h"
  44. #include "st_program.h"
  45. #include "st_cb_bitmap.h"
  46. #include "st_texture.h"
  47.  
  48. #include "pipe/p_context.h"
  49. #include "pipe/p_defines.h"
  50. #include "pipe/p_shader_tokens.h"
  51. #include "util/u_inlines.h"
  52. #include "util/u_draw_quad.h"
  53. #include "util/u_simple_shaders.h"
  54. #include "util/u_upload_mgr.h"
  55. #include "program/prog_instruction.h"
  56. #include "cso_cache/cso_context.h"
  57.  
  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 = VARYING_SLOT_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 = VARYING_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 struct gl_program *
  174. make_bitmap_fragment_program_glsl(struct st_context *st,
  175.                                   struct st_fragment_program *orig,
  176.                                   GLuint samplerIndex)
  177. {
  178.    struct gl_context *ctx = st->ctx;
  179.    struct st_fragment_program *fp = (struct st_fragment_program *)
  180.       ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
  181.  
  182.    if (!fp)
  183.       return NULL;
  184.    
  185.    get_bitmap_visitor(fp, orig->glsl_to_tgsi, samplerIndex);
  186.    return &fp->Base.Base;
  187. }
  188.  
  189.  
  190. static int
  191. find_free_bit(uint bitfield)
  192. {
  193.    int i;
  194.    for (i = 0; i < 32; i++) {
  195.       if ((bitfield & (1 << i)) == 0) {
  196.          return i;
  197.       }
  198.    }
  199.    return -1;
  200. }
  201.  
  202.  
  203. /**
  204.  * Combine basic bitmap fragment program with the user-defined program.
  205.  * \param st  current context
  206.  * \param fpIn  the incoming fragment program
  207.  * \param fpOut  the new fragment program which does fragment culling
  208.  * \param bitmap_sampler  sampler number for the bitmap texture
  209.  */
  210. void
  211. st_make_bitmap_fragment_program(struct st_context *st,
  212.                                 struct gl_fragment_program *fpIn,
  213.                                 struct gl_fragment_program **fpOut,
  214.                                 GLuint *bitmap_sampler)
  215. {
  216.    struct st_fragment_program *bitmap_prog;
  217.    struct st_fragment_program *stfpIn = (struct st_fragment_program *) fpIn;
  218.    struct gl_program *newProg;
  219.    uint sampler;
  220.  
  221.    /*
  222.     * Generate new program which is the user-defined program prefixed
  223.     * with the bitmap sampler/kill instructions.
  224.     */
  225.    sampler = find_free_bit(fpIn->Base.SamplersUsed);
  226.    
  227.    if (stfpIn->glsl_to_tgsi)
  228.       newProg = make_bitmap_fragment_program_glsl(st, stfpIn, sampler);
  229.    else {
  230.       bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler);
  231.  
  232.       newProg = _mesa_combine_programs(st->ctx,
  233.                                        &bitmap_prog->Base.Base,
  234.                                        &fpIn->Base);
  235.       /* done with this after combining */
  236.       st_reference_fragprog(st, &bitmap_prog, NULL);
  237.    }
  238.  
  239. #if 0
  240.    {
  241.       printf("Combined bitmap program:\n");
  242.       _mesa_print_program(newProg);
  243.       printf("InputsRead: 0x%x\n", newProg->InputsRead);
  244.       printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten);
  245.       _mesa_print_parameter_list(newProg->Parameters);
  246.    }
  247. #endif
  248.  
  249.    /* return results */
  250.    *fpOut = (struct gl_fragment_program *) newProg;
  251.    *bitmap_sampler = sampler;
  252. }
  253.  
  254.  
  255. /**
  256.  * Copy user-provide bitmap bits into texture buffer, expanding
  257.  * bits into texels.
  258.  * "On" bits will set texels to 0x0.
  259.  * "Off" bits will not modify texels.
  260.  * Note that the image is actually going to be upside down in
  261.  * the texture.  We deal with that with texcoords.
  262.  */
  263. static void
  264. unpack_bitmap(struct st_context *st,
  265.               GLint px, GLint py, GLsizei width, GLsizei height,
  266.               const struct gl_pixelstore_attrib *unpack,
  267.               const GLubyte *bitmap,
  268.               ubyte *destBuffer, uint destStride)
  269. {
  270.    destBuffer += py * destStride + px;
  271.  
  272.    _mesa_expand_bitmap(width, height, unpack, bitmap,
  273.                        destBuffer, destStride, 0x0);
  274. }
  275.  
  276.  
  277. /**
  278.  * Create a texture which represents a bitmap image.
  279.  */
  280. static struct pipe_resource *
  281. make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
  282.                     const struct gl_pixelstore_attrib *unpack,
  283.                     const GLubyte *bitmap)
  284. {
  285.    struct st_context *st = st_context(ctx);
  286.    struct pipe_context *pipe = st->pipe;
  287.    struct pipe_transfer *transfer;
  288.    ubyte *dest;
  289.    struct pipe_resource *pt;
  290.  
  291.    /* PBO source... */
  292.    bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
  293.    if (!bitmap) {
  294.       return NULL;
  295.    }
  296.  
  297.    /**
  298.     * Create texture to hold bitmap pattern.
  299.     */
  300.    pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
  301.                           0, width, height, 1, 1, 0,
  302.                           PIPE_BIND_SAMPLER_VIEW);
  303.    if (!pt) {
  304.       _mesa_unmap_pbo_source(ctx, unpack);
  305.       return NULL;
  306.    }
  307.  
  308.    dest = pipe_transfer_map(st->pipe, pt, 0, 0,
  309.                             PIPE_TRANSFER_WRITE,
  310.                             0, 0, width, height, &transfer);
  311.  
  312.    /* Put image into texture transfer */
  313.    memset(dest, 0xff, height * transfer->stride);
  314.    unpack_bitmap(st, 0, 0, width, height, unpack, bitmap,
  315.                  dest, transfer->stride);
  316.  
  317.    _mesa_unmap_pbo_source(ctx, unpack);
  318.  
  319.    /* Release transfer */
  320.    pipe_transfer_unmap(pipe, transfer);
  321.    return pt;
  322. }
  323.  
  324. static void
  325. setup_bitmap_vertex_data(struct st_context *st, bool normalized,
  326.                          int x, int y, int width, int height,
  327.                          float z, const float color[4],
  328.                          struct pipe_resource **vbuf,
  329.                          unsigned *vbuf_offset)
  330. {
  331.    const GLfloat fb_width = (GLfloat)st->state.framebuffer.width;
  332.    const GLfloat fb_height = (GLfloat)st->state.framebuffer.height;
  333.    const GLfloat x0 = (GLfloat)x;
  334.    const GLfloat x1 = (GLfloat)(x + width);
  335.    const GLfloat y0 = (GLfloat)y;
  336.    const GLfloat y1 = (GLfloat)(y + height);
  337.    GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
  338.    GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
  339.    const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
  340.    const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
  341.    const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
  342.    const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
  343.    GLuint i;
  344.    float (*vertices)[3][4];  /**< vertex pos + color + texcoord */
  345.  
  346.    if(!normalized)
  347.    {
  348.       sRight = (GLfloat) width;
  349.       tBot = (GLfloat) height;
  350.    }
  351.  
  352.    if (u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]),
  353.                       vbuf_offset, vbuf, (void **) &vertices) != PIPE_OK) {
  354.       return;
  355.    }
  356.  
  357.    /* Positions are in clip coords since we need to do clipping in case
  358.     * the bitmap quad goes beyond the window bounds.
  359.     */
  360.    vertices[0][0][0] = clip_x0;
  361.    vertices[0][0][1] = clip_y0;
  362.    vertices[0][2][0] = sLeft;
  363.    vertices[0][2][1] = tTop;
  364.  
  365.    vertices[1][0][0] = clip_x1;
  366.    vertices[1][0][1] = clip_y0;
  367.    vertices[1][2][0] = sRight;
  368.    vertices[1][2][1] = tTop;
  369.    
  370.    vertices[2][0][0] = clip_x1;
  371.    vertices[2][0][1] = clip_y1;
  372.    vertices[2][2][0] = sRight;
  373.    vertices[2][2][1] = tBot;
  374.    
  375.    vertices[3][0][0] = clip_x0;
  376.    vertices[3][0][1] = clip_y1;
  377.    vertices[3][2][0] = sLeft;
  378.    vertices[3][2][1] = tBot;
  379.    
  380.    /* same for all verts: */
  381.    for (i = 0; i < 4; i++) {
  382.       vertices[i][0][2] = z;
  383.       vertices[i][0][3] = 1.0f;
  384.       vertices[i][1][0] = color[0];
  385.       vertices[i][1][1] = color[1];
  386.       vertices[i][1][2] = color[2];
  387.       vertices[i][1][3] = color[3];
  388.       vertices[i][2][2] = 0.0; /*R*/
  389.       vertices[i][2][3] = 1.0; /*Q*/
  390.    }
  391.  
  392.    u_upload_unmap(st->uploader);
  393. }
  394.  
  395.  
  396.  
  397. /**
  398.  * Render a glBitmap by drawing a textured quad
  399.  */
  400. static void
  401. draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
  402.                  GLsizei width, GLsizei height,
  403.                  struct pipe_sampler_view *sv,
  404.                  const GLfloat *color)
  405. {
  406.    struct st_context *st = st_context(ctx);
  407.    struct pipe_context *pipe = st->pipe;
  408.    struct cso_context *cso = st->cso_context;
  409.    struct st_fp_variant *fpv;
  410.    struct st_fp_variant_key key;
  411.    GLuint maxSize;
  412.    GLuint offset;
  413.    struct pipe_resource *vbuf = NULL;
  414.  
  415.    memset(&key, 0, sizeof(key));
  416.    key.st = st;
  417.    key.bitmap = GL_TRUE;
  418.    key.clamp_color = st->clamp_frag_color_in_shader &&
  419.                      st->ctx->Color._ClampFragmentColor;
  420.  
  421.    fpv = st_get_fp_variant(st, st->fp, &key);
  422.  
  423.    /* As an optimization, Mesa's fragment programs will sometimes get the
  424.     * primary color from a statevar/constant rather than a varying variable.
  425.     * when that's the case, we need to ensure that we use the 'color'
  426.     * parameter and not the current attribute color (which may have changed
  427.     * through glRasterPos and state validation.
  428.     * So, we force the proper color here.  Not elegant, but it works.
  429.     */
  430.    {
  431.       GLfloat colorSave[4];
  432.       COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
  433.       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
  434.       st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
  435.       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
  436.    }
  437.  
  438.  
  439.    /* limit checks */
  440.    /* XXX if the bitmap is larger than the max texture size, break
  441.     * it up into chunks.
  442.     */
  443.    maxSize = 1 << (pipe->screen->get_param(pipe->screen,
  444.                                     PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
  445.    assert(width <= (GLsizei)maxSize);
  446.    assert(height <= (GLsizei)maxSize);
  447.  
  448.    cso_save_rasterizer(cso);
  449.    cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
  450.    cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
  451.    cso_save_viewport(cso);
  452.    cso_save_fragment_shader(cso);
  453.    cso_save_stream_outputs(cso);
  454.    cso_save_vertex_shader(cso);
  455.    cso_save_geometry_shader(cso);
  456.    cso_save_vertex_elements(cso);
  457.    cso_save_aux_vertex_buffer_slot(cso);
  458.  
  459.    /* rasterizer state: just scissor */
  460.    st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
  461.    cso_set_rasterizer(cso, &st->bitmap.rasterizer);
  462.  
  463.    /* fragment shader state: TEX lookup program */
  464.    cso_set_fragment_shader_handle(cso, fpv->driver_shader);
  465.  
  466.    /* vertex shader state: position + texcoord pass-through */
  467.    cso_set_vertex_shader_handle(cso, st->bitmap.vs);
  468.  
  469.    /* geometry shader state: disabled */
  470.    cso_set_geometry_shader_handle(cso, NULL);
  471.  
  472.    /* user samplers, plus our bitmap sampler */
  473.    {
  474.       struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
  475.       uint num = MAX2(fpv->bitmap_sampler + 1,
  476.                       st->state.num_samplers[PIPE_SHADER_FRAGMENT]);
  477.       uint i;
  478.       for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++) {
  479.          samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i];
  480.       }
  481.       samplers[fpv->bitmap_sampler] =
  482.          &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
  483.       cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num,
  484.                        (const struct pipe_sampler_state **) samplers);
  485.    }
  486.  
  487.    /* user textures, plus the bitmap texture */
  488.    {
  489.       struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
  490.       uint num = MAX2(fpv->bitmap_sampler + 1,
  491.                       st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
  492.       memcpy(sampler_views, st->state.sampler_views[PIPE_SHADER_FRAGMENT],
  493.              sizeof(sampler_views));
  494.       sampler_views[fpv->bitmap_sampler] = sv;
  495.       cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num, sampler_views);
  496.    }
  497.  
  498.    /* viewport state: viewport matching window dims */
  499.    {
  500.       const GLboolean invert = st->state.fb_orientation == Y_0_TOP;
  501.       const GLfloat width = (GLfloat)st->state.framebuffer.width;
  502.       const GLfloat height = (GLfloat)st->state.framebuffer.height;
  503.       struct pipe_viewport_state vp;
  504.       vp.scale[0] =  0.5f * width;
  505.       vp.scale[1] = height * (invert ? -0.5f : 0.5f);
  506.       vp.scale[2] = 0.5f;
  507.       vp.scale[3] = 1.0f;
  508.       vp.translate[0] = 0.5f * width;
  509.       vp.translate[1] = 0.5f * height;
  510.       vp.translate[2] = 0.5f;
  511.       vp.translate[3] = 0.0f;
  512.       cso_set_viewport(cso, &vp);
  513.    }
  514.  
  515.    cso_set_vertex_elements(cso, 3, st->velems_util_draw);
  516.    cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
  517.  
  518.    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
  519.    z = z * 2.0f - 1.0f;
  520.  
  521.    /* draw textured quad */
  522.    setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT,
  523.                             x, y, width, height, z, color, &vbuf, &offset);
  524.  
  525.    if (vbuf) {
  526.       util_draw_vertex_buffer(pipe, st->cso_context, vbuf,
  527.                               cso_get_aux_vertex_buffer_slot(st->cso_context),
  528.                               offset,
  529.                               PIPE_PRIM_TRIANGLE_FAN,
  530.                               4,  /* verts */
  531.                               3); /* attribs/vert */
  532.    }
  533.  
  534.    /* restore state */
  535.    cso_restore_rasterizer(cso);
  536.    cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
  537.    cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
  538.    cso_restore_viewport(cso);
  539.    cso_restore_fragment_shader(cso);
  540.    cso_restore_vertex_shader(cso);
  541.    cso_restore_geometry_shader(cso);
  542.    cso_restore_vertex_elements(cso);
  543.    cso_restore_aux_vertex_buffer_slot(cso);
  544.    cso_restore_stream_outputs(cso);
  545.  
  546.    pipe_resource_reference(&vbuf, NULL);
  547. }
  548.  
  549.  
  550. static void
  551. reset_cache(struct st_context *st)
  552. {
  553.    struct bitmap_cache *cache = st->bitmap.cache;
  554.  
  555.    /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/
  556.    cache->empty = GL_TRUE;
  557.  
  558.    cache->xmin = 1000000;
  559.    cache->xmax = -1000000;
  560.    cache->ymin = 1000000;
  561.    cache->ymax = -1000000;
  562.  
  563.    assert(!cache->texture);
  564.  
  565.    /* allocate a new texture */
  566.    cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
  567.                                       st->bitmap.tex_format, 0,
  568.                                       BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
  569.                                       1, 1, 0,
  570.                                       PIPE_BIND_SAMPLER_VIEW);
  571. }
  572.  
  573.  
  574. /** Print bitmap image to stdout (debug) */
  575. static void
  576. print_cache(const struct bitmap_cache *cache)
  577. {
  578.    int i, j, k;
  579.  
  580.    for (i = 0; i < BITMAP_CACHE_HEIGHT; i++) {
  581.       k = BITMAP_CACHE_WIDTH * (BITMAP_CACHE_HEIGHT - i - 1);
  582.       for (j = 0; j < BITMAP_CACHE_WIDTH; j++) {
  583.          if (cache->buffer[k])
  584.             printf("X");
  585.          else
  586.             printf(" ");
  587.          k++;
  588.       }
  589.       printf("\n");
  590.    }
  591. }
  592.  
  593.  
  594. /**
  595.  * Create gallium pipe_transfer object for the bitmap cache.
  596.  */
  597. static void
  598. create_cache_trans(struct st_context *st)
  599. {
  600.    struct pipe_context *pipe = st->pipe;
  601.    struct bitmap_cache *cache = st->bitmap.cache;
  602.  
  603.    if (cache->trans)
  604.       return;
  605.  
  606.    /* Map the texture transfer.
  607.     * Subsequent glBitmap calls will write into the texture image.
  608.     */
  609.    cache->buffer = pipe_transfer_map(pipe, cache->texture, 0, 0,
  610.                                      PIPE_TRANSFER_WRITE, 0, 0,
  611.                                      BITMAP_CACHE_WIDTH,
  612.                                      BITMAP_CACHE_HEIGHT, &cache->trans);
  613.  
  614.    /* init image to all 0xff */
  615.    memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
  616. }
  617.  
  618.  
  619. /**
  620.  * If there's anything in the bitmap cache, draw/flush it now.
  621.  */
  622. void
  623. st_flush_bitmap_cache(struct st_context *st)
  624. {
  625.    if (!st->bitmap.cache->empty) {
  626.       struct bitmap_cache *cache = st->bitmap.cache;
  627.  
  628.       struct pipe_context *pipe = st->pipe;
  629.       struct pipe_sampler_view *sv;
  630.  
  631.       assert(cache->xmin <= cache->xmax);
  632.  
  633. /*    printf("flush size %d x %d  at %d, %d\n",
  634.              cache->xmax - cache->xmin,
  635.              cache->ymax - cache->ymin,
  636.              cache->xpos, cache->ypos);
  637. */
  638.  
  639.       /* The texture transfer has been mapped until now.
  640.           * So unmap and release the texture transfer before drawing.
  641.           */
  642.       if (cache->trans && cache->buffer) {
  643.          if (0)
  644.             print_cache(cache);
  645.          pipe_transfer_unmap(pipe, cache->trans);
  646.          cache->buffer = NULL;
  647.          cache->trans = NULL;
  648.       }
  649.  
  650.       sv = st_create_texture_sampler_view(st->pipe, cache->texture);
  651.       if (sv) {
  652.          draw_bitmap_quad(st->ctx,
  653.                           cache->xpos,
  654.                           cache->ypos,
  655.                           cache->zpos,
  656.                           BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
  657.                           sv,
  658.                           cache->color);
  659.  
  660.          pipe_sampler_view_reference(&sv, NULL);
  661.       }
  662.  
  663.       /* release/free the texture */
  664.       pipe_resource_reference(&cache->texture, NULL);
  665.  
  666.       reset_cache(st);
  667.    }
  668. }
  669.  
  670.  
  671. /**
  672.  * Try to accumulate this glBitmap call in the bitmap cache.
  673.  * \return  GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
  674.  */
  675. static GLboolean
  676. accum_bitmap(struct gl_context *ctx,
  677.              GLint x, GLint y, GLsizei width, GLsizei height,
  678.              const struct gl_pixelstore_attrib *unpack,
  679.              const GLubyte *bitmap )
  680. {
  681.    struct st_context *st = ctx->st;
  682.    struct bitmap_cache *cache = st->bitmap.cache;
  683.    int px = -999, py = -999;
  684.    const GLfloat z = st->ctx->Current.RasterPos[2];
  685.  
  686.    if (width > BITMAP_CACHE_WIDTH ||
  687.        height > BITMAP_CACHE_HEIGHT)
  688.       return GL_FALSE; /* too big to cache */
  689.  
  690.    if (!cache->empty) {
  691.       px = x - cache->xpos;  /* pos in buffer */
  692.       py = y - cache->ypos;
  693.       if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
  694.           py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
  695.           !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
  696.           ((fabs(z - cache->zpos) > Z_EPSILON))) {
  697.          /* This bitmap would extend beyond cache bounds, or the bitmap
  698.           * color is changing
  699.           * so flush and continue.
  700.           */
  701.          st_flush_bitmap_cache(st);
  702.       }
  703.    }
  704.  
  705.    if (cache->empty) {
  706.       /* Initialize.  Center bitmap vertically in the buffer. */
  707.       px = 0;
  708.       py = (BITMAP_CACHE_HEIGHT - height) / 2;
  709.       cache->xpos = x;
  710.       cache->ypos = y - py;
  711.       cache->zpos = z;
  712.       cache->empty = GL_FALSE;
  713.       COPY_4FV(cache->color, st->ctx->Current.RasterColor);
  714.    }
  715.  
  716.    assert(px != -999);
  717.    assert(py != -999);
  718.  
  719.    if (x < cache->xmin)
  720.       cache->xmin = x;
  721.    if (y < cache->ymin)
  722.       cache->ymin = y;
  723.    if (x + width > cache->xmax)
  724.       cache->xmax = x + width;
  725.    if (y + height > cache->ymax)
  726.       cache->ymax = y + height;
  727.  
  728.    /* create the transfer if needed */
  729.    create_cache_trans(st);
  730.  
  731.    /* PBO source... */
  732.    bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
  733.    if (!bitmap) {
  734.       return FALSE;
  735.    }
  736.  
  737.    unpack_bitmap(st, px, py, width, height, unpack, bitmap,
  738.                  cache->buffer, BITMAP_CACHE_WIDTH);
  739.  
  740.    _mesa_unmap_pbo_source(ctx, unpack);
  741.  
  742.    return GL_TRUE; /* accumulated */
  743. }
  744.  
  745.  
  746.  
  747. /**
  748.  * Called via ctx->Driver.Bitmap()
  749.  */
  750. static void
  751. st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
  752.           GLsizei width, GLsizei height,
  753.           const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
  754. {
  755.    struct st_context *st = st_context(ctx);
  756.    struct pipe_resource *pt;
  757.  
  758.    if (width == 0 || height == 0)
  759.       return;
  760.  
  761.    st_validate_state(st);
  762.  
  763.    if (!st->bitmap.vs) {
  764.       /* create pass-through vertex shader now */
  765.       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
  766.                                       TGSI_SEMANTIC_COLOR,
  767.         st->needs_texcoord_semantic ? TGSI_SEMANTIC_TEXCOORD :
  768.                                       TGSI_SEMANTIC_GENERIC };
  769.       const uint semantic_indexes[] = { 0, 0, 0 };
  770.       st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
  771.                                                           semantic_names,
  772.                                                           semantic_indexes);
  773.    }
  774.  
  775.    if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap))
  776.       return;
  777.  
  778.    pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
  779.    if (pt) {
  780.       struct pipe_sampler_view *sv =
  781.          st_create_texture_sampler_view(st->pipe, pt);
  782.  
  783.       assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
  784.  
  785.       if (sv) {
  786.          draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
  787.                           width, height, sv,
  788.                           st->ctx->Current.RasterColor);
  789.  
  790.          pipe_sampler_view_reference(&sv, NULL);
  791.       }
  792.  
  793.       /* release/free the texture */
  794.       pipe_resource_reference(&pt, NULL);
  795.    }
  796. }
  797.  
  798.  
  799. /** Per-context init */
  800. void
  801. st_init_bitmap_functions(struct dd_function_table *functions)
  802. {
  803.    functions->Bitmap = st_Bitmap;
  804. }
  805.  
  806.  
  807. /** Per-context init */
  808. void
  809. st_init_bitmap(struct st_context *st)
  810. {
  811.    struct pipe_sampler_state *sampler = &st->bitmap.samplers[0];
  812.    struct pipe_context *pipe = st->pipe;
  813.    struct pipe_screen *screen = pipe->screen;
  814.  
  815.    /* init sampler state once */
  816.    memset(sampler, 0, sizeof(*sampler));
  817.    sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
  818.    sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
  819.    sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
  820.    sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
  821.    sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  822.    sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
  823.    st->bitmap.samplers[1] = *sampler;
  824.    st->bitmap.samplers[1].normalized_coords = 1;
  825.  
  826.    /* init baseline rasterizer state once */
  827.    memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
  828.    st->bitmap.rasterizer.half_pixel_center = 1;
  829.    st->bitmap.rasterizer.bottom_edge_rule = 1;
  830.    st->bitmap.rasterizer.depth_clip = 1;
  831.  
  832.    /* find a usable texture format */
  833.    if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM,
  834.                                    PIPE_TEXTURE_2D, 0,
  835.                                    PIPE_BIND_SAMPLER_VIEW)) {
  836.       st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
  837.    }
  838.    else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM,
  839.                                         PIPE_TEXTURE_2D, 0,
  840.                                         PIPE_BIND_SAMPLER_VIEW)) {
  841.       st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM;
  842.    }
  843.    else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM,
  844.                                         PIPE_TEXTURE_2D, 0,
  845.                                         PIPE_BIND_SAMPLER_VIEW)) {
  846.       st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM;
  847.    }
  848.    else {
  849.       /* XXX support more formats */
  850.       assert(0);
  851.    }
  852.  
  853.    /* alloc bitmap cache object */
  854.    st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache);
  855.  
  856.    reset_cache(st);
  857. }
  858.  
  859.  
  860. /** Per-context tear-down */
  861. void
  862. st_destroy_bitmap(struct st_context *st)
  863. {
  864.    struct pipe_context *pipe = st->pipe;
  865.    struct bitmap_cache *cache = st->bitmap.cache;
  866.  
  867.    if (st->bitmap.vs) {
  868.       cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
  869.       st->bitmap.vs = NULL;
  870.    }
  871.  
  872.    if (cache) {
  873.       if (cache->trans && cache->buffer) {
  874.          pipe_transfer_unmap(pipe, cache->trans);
  875.       }
  876.       pipe_resource_reference(&st->bitmap.cache->texture, NULL);
  877.       free(st->bitmap.cache);
  878.       st->bitmap.cache = NULL;
  879.    }
  880. }
  881.