Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[mesa.git] / src / mesa / state_tracker / st_cb_bitmap.c
index eecedc20f0265e3251299f7a616cedaa00b2a788..1960d171bf64ed12fe5763701e98d24cafb31ac2 100644 (file)
@@ -47,6 +47,8 @@
 #include "st_cb_program.h"
 #include "st_mesa_to_tgsi.h"
 #include "st_texture.h"
+#include "st_inlines.h"
+
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_inlines.h"
@@ -92,6 +94,9 @@ struct bitmap_cache
 
    GLfloat color[4];
 
+   /** Bitmap's Z position */
+   GLfloat zpos;
+
    struct pipe_texture *texture;
    struct pipe_transfer *trans;
 
@@ -102,6 +107,8 @@ struct bitmap_cache
 };
 
 
+/** Epsilon for Z comparisons */
+#define Z_EPSILON 1e-06
 
 
 /**
@@ -147,7 +154,7 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
       p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
 
    p->Instructions[ic].SrcReg[0].Index = 0;
-   p->Instructions[ic].SrcReg[0].NegateBase = NEGATE_XYZW;
+   p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
    ic++;
 
    /* END; */
@@ -234,7 +241,7 @@ combined_bitmap_fragment_program(GLcontext *ctx)
 /**
  * Copy user-provide bitmap bits into texture buffer, expanding
  * bits into texels.
- * "On" bits will set texels to 0xff.
+ * "On" bits will set texels to 0x0.
  * "Off" bits will not modify texels.
  * Note that the image is actually going to be upside down in
  * the texture.  We deal with that with texcoords.
@@ -246,63 +253,10 @@ unpack_bitmap(struct st_context *st,
               const GLubyte *bitmap,
               ubyte *destBuffer, uint destStride)
 {
-   GLint row, col;
-
-#define SET_PIXEL(COL, ROW) \
-   destBuffer[(py + (ROW)) * destStride + px + (COL)] = 0x0;
-
-   for (row = 0; row < height; row++) {
-      const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
-                 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
-
-      if (unpack->LsbFirst) {
-         /* Lsb first */
-         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
-         for (col = 0; col < width; col++) {
-
-            if (*src & mask) {
-               SET_PIXEL(col, row);
-            }
-
-            if (mask == 128U) {
-               src++;
-               mask = 1U;
-            }
-            else {
-               mask = mask << 1;
-            }
-         }
-
-         /* get ready for next row */
-         if (mask != 1)
-            src++;
-      }
-      else {
-         /* Msb first */
-         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
-         for (col = 0; col < width; col++) {
-
-            if (*src & mask) {
-               SET_PIXEL(col, row);
-            }
-
-            if (mask == 1U) {
-               src++;
-               mask = 128U;
-            }
-            else {
-               mask = mask >> 1;
-            }
-         }
-
-         /* get ready for next row */
-         if (mask != 128)
-            src++;
-      }
-
-   } /* row */
+   destBuffer += py * destStride + px;
 
-#undef SET_PIXEL
+   _mesa_expand_bitmap(width, height, unpack, bitmap,
+                       destBuffer, destStride, 0x0);
 }
 
 
@@ -321,7 +275,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
    struct pipe_texture *pt;
 
    /* PBO source... */
-   bitmap = _mesa_map_bitmap_pbo(ctx, unpack, bitmap);
+   bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
    if (!bitmap) {
       return NULL;
    }
@@ -330,15 +284,16 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
     * Create texture to hold bitmap pattern.
     */
    pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format,
-                          0, width, height, 1, 0,
+                          0, width, height, 1,
                           PIPE_TEXTURE_USAGE_SAMPLER);
    if (!pt) {
-      _mesa_unmap_bitmap_pbo(ctx, unpack);
+      _mesa_unmap_pbo_source(ctx, unpack);
       return NULL;
    }
 
-   transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
-                                       0, 0, width, height);
+   transfer = st_no_flush_get_tex_transfer(st_context(ctx), pt, 0, 0, 0,
+                                          PIPE_TRANSFER_WRITE,
+                                          0, 0, width, height);
 
    dest = screen->transfer_map(screen, transfer);
 
@@ -347,7 +302,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
    unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
                  dest, transfer->stride);
 
-   _mesa_unmap_bitmap_pbo(ctx, unpack);
+   _mesa_unmap_pbo_source(ctx, unpack);
 
    /* Release transfer */
    screen->transfer_unmap(screen, transfer);
@@ -375,7 +330,18 @@ setup_bitmap_vertex_data(struct st_context *st,
    const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
    const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
    const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
-   const GLuint max_slots = 4096 / sizeof(st->bitmap.vertices);
+
+   /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
+    * no_flush) updates to buffers where we know there is no conflict
+    * with previous data.  Currently using max_slots > 1 will cause
+    * synchronous rendering if the driver flushes its command buffers
+    * between one bitmap and the next.  Our flush hook below isn't
+    * sufficient to catch this as the driver doesn't tell us when it
+    * flushes its own command buffers.  Until this gets fixed, pay the
+    * price of allocating a new buffer for each bitmap cache-flush to
+    * avoid synchronous rendering.
+    */
+   const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
    GLuint i;
 
    if (st->bitmap.vbuf_slot >= max_slots) {
@@ -425,11 +391,11 @@ setup_bitmap_vertex_data(struct st_context *st,
    }
 
    /* put vertex data into vbuf */
-   pipe_buffer_write(pipe->screen, 
-                     st->bitmap.vbuf, 
-                     st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
-                     sizeof st->bitmap.vertices,
-                     st->bitmap.vertices);
+   st_no_flush_pipe_buffer_write(st,
+                                st->bitmap.vbuf,
+                                st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
+                                sizeof st->bitmap.vertices,
+                                st->bitmap.vertices);
 
    return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
 }
@@ -535,9 +501,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    }
 
    /* draw textured quad */
-   offset = setup_bitmap_vertex_data(st, x, y, width, height,
-                                     ctx->Current.RasterPos[2],
-                                     color);
+   offset = setup_bitmap_vertex_data(st, x, y, width, height, z, color);
 
    util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
@@ -562,7 +526,7 @@ reset_cache(struct st_context *st)
    struct pipe_screen *screen = pipe->screen;
    struct bitmap_cache *cache = st->bitmap.cache;
 
-   //memset(cache->buffer, 0xff, sizeof(cache->buffer));
+   /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/
    cache->empty = GL_TRUE;
 
    cache->xmin = 1000000;
@@ -570,8 +534,10 @@ reset_cache(struct st_context *st)
    cache->ymin = 1000000;
    cache->ymax = -1000000;
 
-   if (cache->trans)
+   if (cache->trans) {
       screen->tex_transfer_destroy(cache->trans);
+      cache->trans = NULL;
+   }
 
    assert(!cache->texture);
 
@@ -579,16 +545,27 @@ reset_cache(struct st_context *st)
    cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
                                       st->bitmap.tex_format, 0,
                                       BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
-                                      1, 0,
-                                      PIPE_TEXTURE_USAGE_SAMPLER);
+                                      1, PIPE_TEXTURE_USAGE_SAMPLER);
+
+}
+
+static void
+create_cache_trans(struct st_context *st)
+{
+   struct pipe_context *pipe = st->pipe;
+   struct pipe_screen *screen = pipe->screen;
+   struct bitmap_cache *cache = st->bitmap.cache;
+
+   if (cache->trans)
+      return;
 
    /* Map the texture transfer.
     * Subsequent glBitmap calls will write into the texture image.
     */
-   cache->trans = screen->get_tex_transfer(screen, cache->texture, 0, 0, 0,
-                                           PIPE_TRANSFER_WRITE, 0, 0,
-                                           BITMAP_CACHE_WIDTH,
-                                           BITMAP_CACHE_HEIGHT);
+   cache->trans = st_no_flush_get_tex_transfer(st, cache->texture, 0, 0, 0,
+                                              PIPE_TRANSFER_WRITE, 0, 0,
+                                              BITMAP_CACHE_WIDTH,
+                                              BITMAP_CACHE_HEIGHT);
    cache->buffer = screen->transfer_map(screen, cache->trans);
 
    /* init image to all 0xff */
@@ -620,16 +597,18 @@ st_flush_bitmap_cache(struct st_context *st)
          /* The texture transfer has been mapped until now.
           * So unmap and release the texture transfer before drawing.
           */
-         screen->transfer_unmap(screen, cache->trans);
-         cache->buffer = NULL;
+         if (cache->trans) {
+            screen->transfer_unmap(screen, cache->trans);
+            cache->buffer = NULL;
 
-         screen->tex_transfer_destroy(cache->trans);
-         cache->trans = NULL;
+            screen->tex_transfer_destroy(cache->trans);
+            cache->trans = NULL;
+         }
 
          draw_bitmap_quad(st->ctx,
                           cache->xpos,
                           cache->ypos,
-                          st->ctx->Current.RasterPos[2],
+                          cache->zpos,
                           BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
                           cache->texture,
                           cache->color);
@@ -669,6 +648,7 @@ accum_bitmap(struct st_context *st,
 {
    struct bitmap_cache *cache = st->bitmap.cache;
    int px = -999, py;
+   const GLfloat z = st->ctx->Current.RasterPos[2];
 
    if (width > BITMAP_CACHE_WIDTH ||
        height > BITMAP_CACHE_HEIGHT)
@@ -679,7 +659,8 @@ accum_bitmap(struct st_context *st,
       py = y - cache->ypos;
       if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
           py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
-          !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color)) {
+          !TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
+          ((fabs(z - cache->zpos) > Z_EPSILON))) {
          /* This bitmap would extend beyond cache bounds, or the bitmap
           * color is changing
           * so flush and continue.
@@ -694,6 +675,7 @@ accum_bitmap(struct st_context *st,
       py = (BITMAP_CACHE_HEIGHT - height) / 2;
       cache->xpos = x;
       cache->ypos = y - py;
+      cache->zpos = z;
       cache->empty = GL_FALSE;
       COPY_4FV(cache->color, st->ctx->Current.RasterColor);
    }
@@ -709,6 +691,9 @@ accum_bitmap(struct st_context *st,
    if (y + height > cache->ymax)
       cache->ymax = y + height;
 
+   /* create the transfer if needed */
+   create_cache_trans(st);
+
    unpack_bitmap(st, px, py, width, height, unpack, bitmap,
                  cache->buffer, BITMAP_CACHE_WIDTH);
 
@@ -740,8 +725,7 @@ st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
       const uint semantic_indexes[] = { 0, 0, 0 };
       st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
                                                           semantic_names,
-                                                          semantic_indexes,
-                                                          &st->bitmap.vert_shader);
+                                                          semantic_indexes);
    }
 
    if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
@@ -788,13 +772,16 @@ st_init_bitmap(struct st_context *st)
    /* init baseline rasterizer state once */
    memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
    st->bitmap.rasterizer.gl_rasterization_rules = 1;
-   st->bitmap.rasterizer.bypass_vs = 1;
 
    /* find a usable texture format */
    if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D, 
                                    PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
       st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
    }
+   else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, PIPE_TEXTURE_2D, 
+                                        PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+      st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM;
+   }
    else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, PIPE_TEXTURE_2D, 
                                         PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
       st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM;
@@ -819,21 +806,23 @@ st_destroy_bitmap(struct st_context *st)
    struct pipe_screen *screen = pipe->screen;
    struct bitmap_cache *cache = st->bitmap.cache;
 
-   screen->transfer_unmap(screen, cache->trans);
-   screen->tex_transfer_destroy(cache->trans);
+
 
    if (st->bitmap.vs) {
       cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
       st->bitmap.vs = NULL;
    }
-   util_free_shader(&st->bitmap.vert_shader);
 
    if (st->bitmap.vbuf) {
       pipe_buffer_reference(&st->bitmap.vbuf, NULL);
       st->bitmap.vbuf = NULL;
    }
 
-   if (st->bitmap.cache) {
+   if (cache) {
+      if (cache->trans) {
+         screen->transfer_unmap(screen, cache->trans);
+         screen->tex_transfer_destroy(cache->trans);
+      }
       pipe_texture_reference(&st->bitmap.cache->texture, NULL);
       _mesa_free(st->bitmap.cache);
       st->bitmap.cache = NULL;