st/mesa: fix the glBitmap cache wrt FS, scissor, and clamp color changes
authorMarek Olšák <marek.olsak@amd.com>
Fri, 18 Nov 2022 15:20:17 +0000 (10:20 -0500)
committerMarge Bot <emma+marge@anholt.net>
Wed, 7 Dec 2022 09:12:41 +0000 (09:12 +0000)
We need to track those states in the cache and flush the cache
if the next glBitmap call uses different states.

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19859>

src/mesa/main/enable.c
src/mesa/main/scissor.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_context.h

index 5696aa1..22ca9a3 100644 (file)
@@ -868,8 +868,6 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
             GLbitfield newEnabled =
                state * ((1 << ctx->Const.MaxViewports) - 1);
             if (newEnabled != ctx->Scissor.EnableFlags) {
-               st_flush_bitmap_cache(st_context(ctx));
-
                FLUSH_VERTICES(ctx, 0,
                               GL_SCISSOR_BIT | GL_ENABLE_BIT);
                ctx->NewDriverState |= ST_NEW_SCISSOR | ST_NEW_RASTERIZER;
@@ -1404,8 +1402,6 @@ _mesa_set_enablei(struct gl_context *ctx, GLenum cap,
          return;
       }
       if (((ctx->Scissor.EnableFlags >> index) & 1) != state) {
-         st_flush_bitmap_cache(st_context(ctx));
-
          FLUSH_VERTICES(ctx, 0,
                         GL_SCISSOR_BIT | GL_ENABLE_BIT);
          ctx->NewDriverState |= ST_NEW_SCISSOR | ST_NEW_RASTERIZER;
index c4bff66..a3bf2ae 100644 (file)
@@ -51,9 +51,6 @@ set_scissor_no_notify(struct gl_context *ctx, unsigned idx,
        height == ctx->Scissor.ScissorArray[idx].Height)
       return;
 
-   if (ctx->Scissor.EnableFlags)
-      st_flush_bitmap_cache(st_context(ctx));
-
    FLUSH_VERTICES(ctx, 0, GL_SCISSOR_BIT);
    ctx->NewDriverState |= ST_NEW_SCISSOR;
 
index 7b2433e..86cd6cc 100644 (file)
@@ -170,7 +170,8 @@ st_make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
 static void
 setup_render_state(struct gl_context *ctx,
                    struct pipe_sampler_view *sv,
-                   const GLfloat *color)
+                   const GLfloat *color, struct gl_program *fp,
+                   bool scissor_enabled, bool clamp_frag_color)
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
@@ -182,10 +183,10 @@ setup_render_state(struct gl_context *ctx,
    key.st = st->has_shareable_shaders ? NULL : st;
    key.bitmap = GL_TRUE;
    key.clamp_color = st->clamp_frag_color_in_shader &&
-                     ctx->Color._ClampFragmentColor;
+                     clamp_frag_color;
    key.lower_alpha_func = COMPARE_FUNC_ALWAYS;
 
-   fpv = st_get_fp_variant(st, st->fp, &key);
+   fpv = st_get_fp_variant(st, fp, &key);
 
    /* As an optimization, Mesa's fragment programs will sometimes get the
     * primary color from a statevar/constant rather than a varying variable.
@@ -198,7 +199,7 @@ setup_render_state(struct gl_context *ctx,
       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, st->fp, MESA_SHADER_FRAGMENT);
+      st_upload_constants(st, fp, MESA_SHADER_FRAGMENT);
       COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
    }
 
@@ -211,7 +212,7 @@ setup_render_state(struct gl_context *ctx,
 
 
    /* rasterizer state: just scissor */
-   st->bitmap.rasterizer.scissor = ctx->Scissor.EnableFlags & 1;
+   st->bitmap.rasterizer.scissor = scissor_enabled;
    cso_set_rasterizer(cso, &st->bitmap.rasterizer);
 
    /* fragment shader state: TEX lookup program */
@@ -243,8 +244,7 @@ setup_render_state(struct gl_context *ctx,
    {
       struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
       unsigned num_views =
-         st_get_sampler_views(st, PIPE_SHADER_FRAGMENT,
-                              ctx->FragmentProgram._Current, sampler_views);
+         st_get_sampler_views(st, PIPE_SHADER_FRAGMENT, fp, sampler_views);
 
       num_views = MAX2(fpv->bitmap_sampler + 1, num_views);
       sampler_views[fpv->bitmap_sampler] = sv;
@@ -294,7 +294,9 @@ restore_render_state(struct gl_context *ctx)
 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 gl_program *fp, bool scissor_enabled,
+                 bool clamp_frag_color)
 {
    struct st_context *st = st_context(ctx);
    const float fb_width = (float) st->state.fb_width;
@@ -327,7 +329,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
       tBot = (float) height;
    }
 
-   setup_render_state(ctx, sv, color);
+   setup_render_state(ctx, sv, color, fp, scissor_enabled, clamp_frag_color);
 
    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
    z = z * 2.0f - 1.0f;
@@ -357,6 +359,8 @@ reset_cache(struct st_context *st)
    cache->ymin = 1000000;
    cache->ymax = -1000000;
 
+   _mesa_reference_program(st->ctx, &cache->fp, NULL);
+
    assert(!cache->texture);
 
    /* allocate a new texture */
@@ -453,7 +457,10 @@ st_flush_bitmap_cache(struct st_context *st)
                           cache->zpos,
                           BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
                           sv,
-                          cache->color);
+                          cache->color,
+                          cache->fp,
+                          cache->scissor_enabled,
+                          cache->clamp_frag_color);
       }
 
       /* release/free the texture */
@@ -483,12 +490,18 @@ accum_bitmap(struct gl_context *ctx,
        height > BITMAP_CACHE_HEIGHT)
       return GL_FALSE; /* too big to cache */
 
+   bool scissor_enabled = ctx->Scissor.EnableFlags & 0x1;
+   bool clamp_frag_color = ctx->Color._ClampFragmentColor;
+
    if (!cache->empty) {
       px = x - cache->xpos;  /* pos in buffer */
       py = y - cache->ypos;
       if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
           py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
           !TEST_EQ_4V(ctx->Current.RasterColor, cache->color) ||
+          ctx->FragmentProgram._Current != cache->fp ||
+          scissor_enabled != cache->scissor_enabled ||
+          clamp_frag_color != cache->clamp_frag_color ||
           ((fabsf(z - cache->zpos) > Z_EPSILON))) {
          /* This bitmap would extend beyond cache bounds, or the bitmap
           * color is changing
@@ -507,6 +520,9 @@ accum_bitmap(struct gl_context *ctx,
       cache->zpos = z;
       cache->empty = GL_FALSE;
       COPY_4FV(cache->color, ctx->Current.RasterColor);
+      _mesa_reference_program(ctx, &cache->fp, ctx->FragmentProgram._Current);
+      cache->scissor_enabled = scissor_enabled;
+      cache->clamp_frag_color = clamp_frag_color;
    }
 
    assert(px != -999);
@@ -645,7 +661,10 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
 
    if (view) {
       draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
-                       width, height, view, ctx->Current.RasterColor);
+                       width, height, view, ctx->Current.RasterColor,
+                       ctx->FragmentProgram._Current,
+                       ctx->Scissor.EnableFlags & 0x1,
+                       ctx->Color._ClampFragmentColor);
    }
 }
 
@@ -660,4 +679,5 @@ st_destroy_bitmap(struct st_context *st)
       pipe_texture_unmap(pipe, cache->trans);
    }
    pipe_resource_reference(&st->bitmap.cache.texture, NULL);
+   _mesa_reference_program(st->ctx, &st->bitmap.cache.fp, NULL);
 }
index cc95295..2a70cd0 100644 (file)
@@ -62,6 +62,10 @@ struct st_bitmap_cache
    /** Bounds of region used in window coords */
    GLint xmin, ymin, xmax, ymax;
 
+   /** GL states */
+   struct gl_program *fp;
+   bool scissor_enabled;
+   bool clamp_frag_color;
    GLfloat color[4];
 
    /** Bitmap's Z position */