intel / DRI2: When available, use DRI2GetBuffersWithFormat
[mesa.git] / src / mesa / state_tracker / st_cb_bitmap.c
index 694104f9cfb10734406b030c8d8a1a1cd07ae02c..8709633557cc6bc4a66e34b959d25f266add23d6 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"
@@ -93,7 +95,7 @@ struct bitmap_cache
    GLfloat color[4];
 
    struct pipe_texture *texture;
-   struct pipe_surface *surf;
+   struct pipe_transfer *trans;
 
    GLboolean empty;
 
@@ -142,8 +144,12 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
    /* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
    p->Instructions[ic].Opcode = OPCODE_KIL;
    p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
+
+   if (ctx->st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
+      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; */
@@ -157,7 +163,11 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
 
    stfp = (struct st_fragment_program *) p;
    stfp->Base.UsesKill = GL_TRUE;
-   st_translate_fragment_program(ctx->st, stfp, NULL);
+
+   /* No need to send this incomplete program down to hardware:
+    *
+    * st_translate_fragment_program(ctx->st, stfp, NULL);
+    */
 
    return stfp;
 }
@@ -219,11 +229,6 @@ combined_bitmap_fragment_program(GLcontext *ctx)
       st_translate_fragment_program(st, stfp->bitmap_program, NULL);
    }
 
-   /* Ideally we'd have updated the pipe constants during the normal
-    * st/atom mechanism.  But we can't since this is specific to glBitmap.
-    */
-   st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
-
    return stfp->bitmap_program;
 }
 
@@ -313,7 +318,7 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
 {
    struct pipe_context *pipe = ctx->st->pipe;
    struct pipe_screen *screen = pipe->screen;
-   struct pipe_surface *surface;
+   struct pipe_transfer *transfer;
    ubyte *dest;
    struct pipe_texture *pt;
 
@@ -327,35 +332,34 @@ 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);
       return NULL;
    }
 
-   surface = screen->get_tex_surface(screen, pt, 0, 0, 0,
-                                     PIPE_BUFFER_USAGE_CPU_WRITE);
+   transfer = st_no_flush_get_tex_transfer(st_context(ctx), pt, 0, 0, 0,
+                                          PIPE_TRANSFER_WRITE,
+                                          0, 0, width, height);
 
-   /* map texture surface */
-   dest = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE);
+   dest = screen->transfer_map(screen, transfer);
 
-   /* Put image into texture surface */
-   memset(dest, 0xff, height * surface->stride);
+   /* Put image into texture transfer */
+   memset(dest, 0xff, height * transfer->stride);
    unpack_bitmap(ctx->st, 0, 0, width, height, unpack, bitmap,
-                 dest, surface->stride);
+                 dest, transfer->stride);
 
    _mesa_unmap_bitmap_pbo(ctx, unpack);
 
-   /* Release surface */
-   screen->surface_unmap(screen, surface);
-   pipe_surface_reference(&surface, NULL);
+   /* Release transfer */
+   screen->transfer_unmap(screen, transfer);
+   screen->tex_transfer_destroy(transfer);
 
    return pt;
 }
 
-
-static void
+static GLuint
 setup_bitmap_vertex_data(struct st_context *st,
                          int x, int y, int width, int height,
                          float z, const float color[4])
@@ -374,12 +378,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);
    GLuint i;
-   void *buf;
+
+   if (st->bitmap.vbuf_slot >= max_slots) {
+      pipe_buffer_reference(&st->bitmap.vbuf, NULL);
+      st->bitmap.vbuf_slot = 0;
+   }
 
    if (!st->bitmap.vbuf) {
-      st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
-                                           sizeof(st->bitmap.vertices));
+      st->bitmap.vbuf = pipe_buffer_create(pipe->screen, 32, 
+                                           PIPE_BUFFER_USAGE_VERTEX,
+                                           max_slots * sizeof(st->bitmap.vertices));
    }
 
    /* Positions are in clip coords since we need to do clipping in case
@@ -418,9 +428,13 @@ setup_bitmap_vertex_data(struct st_context *st,
    }
 
    /* put vertex data into vbuf */
-   buf = pipe_buffer_map(pipe->screen, st->bitmap.vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
-   memcpy(buf, st->bitmap.vertices, sizeof(st->bitmap.vertices));
-   pipe_buffer_unmap(pipe->screen, st->bitmap.vbuf);
+   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;
 }
 
 
@@ -439,9 +453,26 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    struct cso_context *cso = ctx->st->cso_context;
    struct st_fragment_program *stfp;
    GLuint maxSize;
+   GLuint offset;
 
    stfp = combined_bitmap_fragment_program(ctx);
 
+   /* As an optimization, Mesa's fragment programs will sometimes get the
+    * primary color from a statevar/constant rather than a varying variable.
+    * when that's the case, we need to ensure that we use the 'color'
+    * parameter and not the current attribute color (which may have changed
+    * through glRasterPos and state validation.
+    * So, we force the proper color here.  Not elegant, but it works.
+    */
+   {
+      GLfloat colorSave[4];
+      COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+      COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
+      st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
+      COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
+   }
+
+
    /* limit checks */
    /* XXX if the bitmap is larger than the max texture size, break
     * it up into chunks.
@@ -476,7 +507,8 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
          samplers[i] = &st->state.samplers[i];
       }
       samplers[stfp->bitmap_sampler] = &st->bitmap.sampler;
-      cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);   }
+      cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
+   }
 
    /* user textures, plus the bitmap texture */
    {
@@ -506,11 +538,11 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    }
 
    /* draw textured quad */
-   setup_bitmap_vertex_data(st, x, y, width, height,
-                            ctx->Current.RasterPos[2],
-                            color);
+   offset = setup_bitmap_vertex_data(st, x, y, width, height,
+                                     ctx->Current.RasterPos[2],
+                                     color);
 
-   util_draw_vertex_buffer(pipe, st->bitmap.vbuf,
+   util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
                            PIPE_PRIM_TRIANGLE_FAN,
                            4,  /* verts */
                            3); /* attribs/vert */
@@ -541,8 +573,10 @@ reset_cache(struct st_context *st)
    cache->ymin = 1000000;
    cache->ymax = -1000000;
 
-   if (cache->surf)
-      screen->tex_surface_release(screen, &cache->surf);
+   if (cache->trans) {
+      screen->tex_transfer_destroy(cache->trans);
+      cache->trans = NULL;
+   }
 
    assert(!cache->texture);
 
@@ -550,19 +584,31 @@ 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);
+
+}
 
-   /* Map the texture surface.
+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->surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0,
-                                         PIPE_BUFFER_USAGE_CPU_WRITE);
-   cache->buffer = screen->surface_map(screen, cache->surf,
-                                       PIPE_BUFFER_USAGE_CPU_WRITE);
+   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 */
-   memset(cache->buffer, 0xff, BITMAP_CACHE_WIDTH * BITMAP_CACHE_HEIGHT);
+   memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
 }
 
 
@@ -580,20 +626,23 @@ st_flush_bitmap_cache(struct st_context *st)
          struct pipe_screen *screen = pipe->screen;
 
          assert(cache->xmin <= cache->xmax);
-         /*
-         printf("flush size %d x %d  at %d, %d\n",
+/*         printf("flush size %d x %d  at %d, %d\n",
                 cache->xmax - cache->xmin,
                 cache->ymax - cache->ymin,
                 cache->xpos, cache->ypos);
-         */
+*/
 
-         /* The texture surface has been mapped until now.
-          * So unmap and release the texture surface before drawing.
+         /* The texture transfer has been mapped until now.
+          * So unmap and release the texture transfer before drawing.
           */
-         screen->surface_unmap(screen, cache->surf);
-         cache->buffer = NULL;
+         if (cache->trans) {
+            screen->transfer_unmap(screen, cache->trans);
+            cache->buffer = NULL;
 
-         screen->tex_surface_release(screen, &cache->surf);
+            screen->tex_transfer_destroy(cache->trans);
+            cache->trans = NULL;
+         }
 
          draw_bitmap_quad(st->ctx,
                           cache->xpos,
@@ -611,6 +660,20 @@ st_flush_bitmap_cache(struct st_context *st)
    }
 }
 
+/* Flush bitmap cache and release vertex buffer.
+ */
+void
+st_flush_bitmap( struct st_context *st )
+{
+   st_flush_bitmap_cache(st);
+
+   /* Release vertex buffer to avoid synchronous rendering if we were
+    * to map it in the next frame.
+    */
+   pipe_buffer_reference(&st->bitmap.vbuf, NULL);
+   st->bitmap.vbuf_slot = 0;
+}
+
 
 /**
  * Try to accumulate this glBitmap call in the bitmap cache.
@@ -664,6 +727,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);
 
@@ -695,8 +761,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))
@@ -743,20 +808,27 @@ 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;
+   }
    else {
       /* XXX support more formats */
       assert(0);
    }
 
    /* alloc bitmap cache object */
-   st->bitmap.cache = CALLOC_STRUCT(bitmap_cache);
+   st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache);
 
    reset_cache(st);
 }
@@ -770,8 +842,7 @@ st_destroy_bitmap(struct st_context *st)
    struct pipe_screen *screen = pipe->screen;
    struct bitmap_cache *cache = st->bitmap.cache;
 
-   screen->surface_unmap(screen, cache->surf);
-   screen->tex_surface_release(screen, &cache->surf);
+
 
    if (st->bitmap.vs) {
       cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
@@ -779,13 +850,17 @@ st_destroy_bitmap(struct st_context *st)
    }
 
    if (st->bitmap.vbuf) {
-      pipe_buffer_destroy(pipe->screen, st->bitmap.vbuf);
+      pipe_buffer_reference(&st->bitmap.vbuf, NULL);
       st->bitmap.vbuf = NULL;
    }
 
-   if (st->bitmap.cache) {
-      pipe_texture_release(&st->bitmap.cache->texture);
-      FREE(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;
    }
 }