mesa: create glBitmap textures while creating display lists
authorMarek Olšák <marek.olsak@amd.com>
Mon, 25 Jul 2022 00:47:26 +0000 (20:47 -0400)
committerMarge Bot <emma+marge@anholt.net>
Wed, 24 Aug 2022 18:13:02 +0000 (18:13 +0000)
This makes glCallList just a textured draw, which is blazingly fast.

Reviewed-by: Brian Paul <brianp@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17780>

src/mesa/main/dlist.c
src/mesa/main/draw.h
src/mesa/main/drawpix.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_bitmap.h

index c4cddad..594e9c5 100644 (file)
 #include "util/u_memory.h"
 #include "api_exec_decl.h"
 
+#include "state_tracker/st_context.h"
 #include "state_tracker/st_cb_texture.h"
 #include "state_tracker/st_cb_bitmap.h"
+#include "state_tracker/st_sampler_view.h"
 
 static bool
 _mesa_glthread_should_execute_list(struct gl_context *ctx,
@@ -860,9 +862,11 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist)
          case OPCODE_DRAW_PIXELS:
             free(get_pointer(&n[5]));
             break;
-         case OPCODE_BITMAP:
-            free(get_pointer(&n[7]));
+         case OPCODE_BITMAP: {
+            struct pipe_resource *tex = get_pointer(&n[7]);
+            pipe_resource_reference(&tex, NULL);
             break;
+         }
          case OPCODE_POLYGON_STIPPLE:
             free(get_pointer(&n[1]));
             break;
@@ -1336,21 +1340,32 @@ save_Bitmap(GLsizei width, GLsizei height,
    GET_CURRENT_CONTEXT(ctx);
    Node *n;
    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+   struct pipe_resource *tex =
+      st_make_bitmap_texture(ctx, width, height, &ctx->Unpack, pixels);
+
+   if (!tex) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glNewList -> glBitmap");
+      return;
+   }
+
    n = alloc_instruction(ctx, OPCODE_BITMAP, 6 + POINTER_DWORDS);
-   if (n) {
-      n[1].i = (GLint) width;
-      n[2].i = (GLint) height;
-      n[3].f = xorig;
-      n[4].f = yorig;
-      n[5].f = xmove;
-      n[6].f = ymove;
-      save_pointer(&n[7],
-                   unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX,
-                                GL_BITMAP, pixels, &ctx->Unpack));
+   if (!n) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glNewList -> glBitmap (3)");
+      pipe_resource_reference(&tex, NULL);
+      return;
    }
+
+   n[1].i = (GLint) width;
+   n[2].i = (GLint) height;
+   n[3].f = xorig;
+   n[4].f = yorig;
+   n[5].f = xmove;
+   n[6].f = ymove;
+   save_pointer(&n[7], tex);
+
    if (ctx->ExecuteFlag) {
-      CALL_Bitmap(ctx->Exec, (width, height,
-                              xorig, yorig, xmove, ymove, pixels));
+      ASSERT_OUTSIDE_BEGIN_END(ctx);
+      _mesa_bitmap(ctx, width, height, xorig, yorig, xmove, ymove, NULL, tex);
    }
 }
 
@@ -10853,13 +10868,12 @@ execute_list(struct gl_context *ctx, GLuint list)
             CALL_BindTexture(ctx->Exec, (n[1].e, n[2].ui));
             break;
          case OPCODE_BITMAP:
-            {
-               const struct gl_pixelstore_attrib save = ctx->Unpack;
-               ctx->Unpack = ctx->DefaultPacking;
-               CALL_Bitmap(ctx->Exec, ((GLsizei) n[1].i, (GLsizei) n[2].i,
-                                       n[3].f, n[4].f, n[5].f, n[6].f,
-                                       get_pointer(&n[7])));
-               ctx->Unpack = save;      /* restore */
+            if (_mesa_inside_begin_end(ctx)) {
+               _mesa_error(ctx, GL_INVALID_OPERATION,
+                           "glCallList -> glBitmap inside Begin/End");
+            } else {
+               _mesa_bitmap(ctx, n[1].i, n[2].i, n[3].f, n[4].f, n[5].f,
+                            n[6].f, NULL, get_pointer(&n[7]));
             }
             break;
          case OPCODE_BLEND_COLOR:
index 7a59964..aa65745 100644 (file)
@@ -101,6 +101,11 @@ _mesa_draw_gallium_multimode_fallback(struct gl_context *ctx,
                                      const unsigned char *mode,
                                      unsigned num_draws);
 
+void
+_mesa_bitmap(struct gl_context *ctx, GLsizei width, GLsizei height,
+             GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+             const GLubyte *bitmap, struct pipe_resource *tex);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 15c60f2..627330d 100644 (file)
@@ -316,13 +316,11 @@ end:
 }
 
 
-void GLAPIENTRY
-_mesa_Bitmap( GLsizei width, GLsizei height,
-              GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
-              const GLubyte *bitmap )
+void
+_mesa_bitmap(struct gl_context *ctx, GLsizei width, GLsizei height,
+             GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+             const GLubyte *bitmap, struct pipe_resource *tex)
 {
-   GET_CURRENT_CONTEXT(ctx);
-
    FLUSH_VERTICES(ctx, 0, 0);
 
    if (width < 0 || height < 0) {
@@ -354,7 +352,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
          GLint x = util_ifloor(ctx->Current.RasterPos[0] + epsilon - xorig);
          GLint y = util_ifloor(ctx->Current.RasterPos[1] + epsilon - yorig);
 
-         if (ctx->Unpack.BufferObj) {
+         if (!tex && ctx->Unpack.BufferObj) {
             /* unpack from PBO */
             if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height,
                                            1, GL_COLOR_INDEX, GL_BITMAP,
@@ -371,7 +369,7 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
             }
          }
 
-         st_Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
+         st_Bitmap(ctx, x, y, width, height, &ctx->Unpack, bitmap, tex);
       }
    }
    else if (ctx->RenderMode == GL_FEEDBACK) {
@@ -396,3 +394,13 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
       _mesa_flush(ctx);
    }
 }
+
+void GLAPIENTRY
+_mesa_Bitmap(GLsizei width, GLsizei height,
+             GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+             const GLubyte *bitmap)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   _mesa_bitmap(ctx, width, height, xorig, yorig, xmove, ymove, bitmap, NULL);
+}
index 48c28ea..8cc8b8f 100644 (file)
@@ -88,6 +88,8 @@ static GLboolean UseBitmapCache = GL_TRUE;
 /** Epsilon for Z comparisons */
 #define Z_EPSILON 1e-06
 
+static void
+init_bitmap_state(struct st_context *st);
 
 /**
  * Copy user-provide bitmap bits into texture buffer, expanding
@@ -114,10 +116,10 @@ unpack_bitmap(struct st_context *st,
 /**
  * Create a texture which represents a bitmap image.
  */
-static struct pipe_resource *
-make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
-                    const struct gl_pixelstore_attrib *unpack,
-                    const GLubyte *bitmap)
+struct pipe_resource *
+st_make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
+                       const struct gl_pixelstore_attrib *unpack,
+                       const GLubyte *bitmap)
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
@@ -125,6 +127,9 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
    ubyte *dest;
    struct pipe_resource *pt;
 
+   if (!st->bitmap.tex_format)
+      init_bitmap_state(st);
+
    /* PBO source... */
    bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
    if (!bitmap) {
@@ -283,12 +288,13 @@ restore_render_state(struct gl_context *ctx)
 
 /**
  * Render a glBitmap by drawing a textured quad
+ *
+ * take_ownership means the callee will be resposible for unreferencing sv.
  */
 static void
 draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
                  GLsizei width, GLsizei height,
-                 struct pipe_sampler_view *sv,
-                 const GLfloat *color)
+                 struct pipe_sampler_view *sv, const GLfloat *color)
 {
    struct st_context *st = st_context(ctx);
    const float fb_width = (float) st->state.fb_width;
@@ -589,15 +595,17 @@ init_bitmap_state(struct st_context *st)
 void
 st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
           GLsizei width, GLsizei height,
-          const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap)
+          const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap,
+          struct pipe_resource *tex)
 {
    struct st_context *st = st_context(ctx);
-   struct pipe_resource *pt;
 
    assert(width > 0);
    assert(height > 0);
 
    st_invalidate_readpix_cache(st);
+   if (tex)
+      st_flush_bitmap_cache(st);
 
    if (!st->bitmap.tex_format) {
       init_bitmap_state(st);
@@ -613,23 +621,30 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
       st_validate_state(st, ST_PIPELINE_META);
    }
 
-   if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap))
-      return;
+   struct pipe_sampler_view *view = NULL;
 
-   pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
-   if (pt) {
-      struct pipe_sampler_view *sv =
-         st_create_texture_sampler_view(st->pipe, pt);
+   if (!tex) {
+      if (UseBitmapCache && accum_bitmap(ctx, x, y, width, height, unpack, bitmap))
+         return;
 
-      assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
+      struct pipe_resource *pt =
+         st_make_bitmap_texture(ctx, width, height, unpack, bitmap);
+      if (!pt)
+         return;
 
-      if (sv) {
-         draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
-                          width, height, sv, ctx->Current.RasterColor);
-      }
+      assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
 
-      /* release/free the texture */
+      view = st_create_texture_sampler_view(st->pipe, pt);
+      /* unreference the texture because it's referenced by sv */
       pipe_resource_reference(&pt, NULL);
+   } else {
+      /* tex comes from a display list. */
+      view = st_create_texture_sampler_view(st->pipe, tex);
+   }
+
+   if (view) {
+      draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
+                       width, height, view, ctx->Current.RasterColor);
    }
 }
 
index 8a75886..936d49d 100644 (file)
@@ -45,8 +45,14 @@ st_destroy_bitmap(struct st_context *st);
 extern void
 st_flush_bitmap_cache(struct st_context *st);
 
+struct pipe_resource *
+st_make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
+                       const struct gl_pixelstore_attrib *unpack,
+                       const GLubyte *bitmap);
+
 void st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
                GLsizei width, GLsizei height,
-               const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+               const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap,
+               struct pipe_resource *tex);
 
 #endif /* ST_CB_BITMAP_H */