mesa/st/glsl_to_tgsi:rename lifetime to register_live_range
[mesa.git] / src / mesa / state_tracker / st_cb_drawpixels.c
index 33d10f67e26fa990ba4652113a74092d30b5632c..b8895684bc26dc0952b0ce5faac458b8a3576c80 100644 (file)
@@ -30,6 +30,7 @@
   *   Brian Paul
   */
 
+#include "main/errors.h"
 #include "main/imports.h"
 #include "main/image.h"
 #include "main/bufferobj.h"
@@ -41,6 +42,7 @@
 #include "main/pack.h"
 #include "main/pbo.h"
 #include "main/readpix.h"
+#include "main/state.h"
 #include "main/texformat.h"
 #include "main/teximage.h"
 #include "main/texstore.h"
@@ -195,7 +197,7 @@ static void *
 make_passthrough_vertex_shader(struct st_context *st, 
                                GLboolean passColor)
 {
-   const unsigned texcoord_semantic = st->needs_texcoord_semantic ?
+   const enum tgsi_semantic texcoord_semantic = st->needs_texcoord_semantic ?
       TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
 
    if (!st->drawpix.vert_shaders[passColor]) {
@@ -373,6 +375,130 @@ alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
 }
 
 
+/**
+ * Search the cache for an image which matches the given parameters.
+ * \return  pipe_resource pointer if found, NULL if not found.
+ */
+static struct pipe_resource *
+search_drawpixels_cache(struct st_context *st,
+                        GLsizei width, GLsizei height,
+                        GLenum format, GLenum type,
+                        const struct gl_pixelstore_attrib *unpack,
+                        const void *pixels)
+{
+   struct pipe_resource *pt = NULL;
+   const GLint bpp = _mesa_bytes_per_pixel(format, type);
+   unsigned i;
+
+   if ((unpack->RowLength != 0 && unpack->RowLength != width) ||
+       unpack->SkipPixels != 0 ||
+       unpack->SkipRows != 0 ||
+       unpack->SwapBytes ||
+       _mesa_is_bufferobj(unpack->BufferObj)) {
+      /* we don't allow non-default pixel unpacking values */
+      return NULL;
+   }
+
+   /* Search cache entries for a match */
+   for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
+      struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
+
+      if (width == entry->width &&
+          height == entry->height &&
+          format == entry->format &&
+          type == entry->type &&
+          pixels == entry->user_pointer &&
+          entry->image) {
+         assert(entry->texture);
+
+         /* check if the pixel data is the same */
+         if (memcmp(pixels, entry->image, width * height * bpp) == 0) {
+            /* Success - found a cache match */
+            pipe_resource_reference(&pt, entry->texture);
+            /* refcount of returned texture should be at least two here.  One
+             * reference for the cache to hold on to, one for the caller (which
+             * it will release), and possibly more held by the driver.
+             */
+            assert(pt->reference.count >= 2);
+
+            /* update the age of this entry */
+            entry->age = ++st->drawpix_cache.age;
+
+            return pt;
+         }
+      }
+   }
+
+   /* no cache match found */
+   return NULL;
+}
+
+
+/**
+ * Find the oldest entry in the glDrawPixels cache.  We'll replace this
+ * one when we need to store a new image.
+ */
+static struct drawpix_cache_entry *
+find_oldest_drawpixels_cache_entry(struct st_context *st)
+{
+   unsigned oldest_age = ~0u, oldest_index = ~0u;
+   unsigned i;
+
+   /* Find entry with oldest (lowest) age */
+   for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
+      const struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
+      if (entry->age < oldest_age) {
+         oldest_age = entry->age;
+         oldest_index = i;
+      }
+   }
+
+   assert(oldest_index != ~0u);
+
+   return &st->drawpix_cache.entries[oldest_index];
+}
+
+
+/**
+ * Try to save the given glDrawPixels image in the cache.
+ */
+static void
+cache_drawpixels_image(struct st_context *st,
+                       GLsizei width, GLsizei height,
+                       GLenum format, GLenum type,
+                       const struct gl_pixelstore_attrib *unpack,
+                       const void *pixels,
+                       struct pipe_resource *pt)
+{
+   if ((unpack->RowLength == 0 || unpack->RowLength == width) &&
+       unpack->SkipPixels == 0 &&
+       unpack->SkipRows == 0) {
+      const GLint bpp = _mesa_bytes_per_pixel(format, type);
+      struct drawpix_cache_entry *entry =
+         find_oldest_drawpixels_cache_entry(st);
+      assert(entry);
+      entry->width = width;
+      entry->height = height;
+      entry->format = format;
+      entry->type = type;
+      entry->user_pointer = pixels;
+      free(entry->image);
+      entry->image = malloc(width * height * bpp);
+      if (entry->image) {
+         memcpy(entry->image, pixels, width * height * bpp);
+         pipe_resource_reference(&entry->texture, pt);
+         entry->age = ++st->drawpix_cache.age;
+      }
+      else {
+         /* out of memory, free/disable cached texture */
+         entry->width = 0;
+         entry->height = 0;
+         pipe_resource_reference(&entry->texture, NULL);
+      }
+   }
+}
+
+
 /**
  * Make texture containing an image for glDrawPixels image.
  * If 'pixels' is NULL, leave the texture image data undefined.
@@ -391,44 +517,11 @@ make_texture(struct st_context *st,
    GLenum baseInternalFormat;
 
 #if USE_DRAWPIXELS_CACHE
-   const GLint bpp = _mesa_bytes_per_pixel(format, type);
-
-   /* Check if the glDrawPixels() parameters and state matches the cache */
-   if (width == st->drawpix_cache.width &&
-       height == st->drawpix_cache.height &&
-       format == st->drawpix_cache.format &&
-       type == st->drawpix_cache.type &&
-       pixels == st->drawpix_cache.user_pointer &&
-       !_mesa_is_bufferobj(unpack->BufferObj) &&
-       (unpack->RowLength == 0 || unpack->RowLength == width) &&
-       unpack->SkipPixels == 0 &&
-       unpack->SkipRows == 0 &&
-       unpack->SwapBytes == GL_FALSE &&
-       st->drawpix_cache.image) {
-      assert(st->drawpix_cache.texture);
-
-      /* check if the pixel data is the same */
-      if (memcmp(pixels, st->drawpix_cache.image, width * height * bpp) == 0) {
-         /* OK, re-use the cached texture */
-         pipe_resource_reference(&pt, st->drawpix_cache.texture);
-         /* refcount of returned texture should be at least two here.  One
-          * reference for the cache to hold on to, one for the caller (which
-          * it will release), and possibly more held by the driver.
-          */
-         assert(pt->reference.count >= 2);
-         return pt;
-      }
+   pt = search_drawpixels_cache(st, width, height, format, type,
+                                unpack, pixels);
+   if (pt) {
+      return pt;
    }
-
-   /* discard the cached image and texture (if there is one) */
-   st->drawpix_cache.width = 0;
-   st->drawpix_cache.height = 0;
-   st->drawpix_cache.user_pointer = NULL;
-   if (st->drawpix_cache.image) {
-      free(st->drawpix_cache.image);
-      st->drawpix_cache.image = NULL;
-   }
-   pipe_resource_reference(&st->drawpix_cache.texture, NULL);
 #endif
 
    /* Choose a pixel format for the temp texture which will hold the
@@ -442,7 +535,7 @@ make_texture(struct st_context *st,
       GLenum intFormat = internal_format(ctx, format, type);
 
       pipeFormat = st_choose_format(st, intFormat, format, type,
-                                    st->internal_target, 0,
+                                    st->internal_target, 0, 0,
                                     PIPE_BIND_SAMPLER_VIEW, FALSE);
       assert(pipeFormat != PIPE_FORMAT_NONE);
    }
@@ -463,7 +556,6 @@ make_texture(struct st_context *st,
 
    {
       struct pipe_transfer *transfer;
-      GLboolean success;
       GLubyte *dest;
       const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
 
@@ -496,9 +588,9 @@ make_texture(struct st_context *st,
                               format, type,     /* src format/type */
                               pixels,           /* data source */
                               unpack);
-         success = GL_TRUE;
       }
       else {
+         bool MAYBE_UNUSED success;
          success = _mesa_texstore(ctx, 2,           /* dims */
                                   baseInternalFormat, /* baseInternalFormat */
                                   mformat,          /* mesa_format */
@@ -508,13 +600,13 @@ make_texture(struct st_context *st,
                                   format, type,     /* src format/type */
                                   pixels,           /* data source */
                                   unpack);
+
+         assert(success);
       }
 
       /* unmap */
       pipe_transfer_unmap(pipe, transfer);
 
-      assert(success);
-
       /* restore */
       ctx->_ImageTransferState = imageTransferStateSave;
    }
@@ -522,28 +614,7 @@ make_texture(struct st_context *st,
    _mesa_unmap_pbo_source(ctx, unpack);
 
 #if USE_DRAWPIXELS_CACHE
-   /* Save the glDrawPixels parameter and image in the cache */
-   if ((unpack->RowLength == 0 || unpack->RowLength == width) &&
-       unpack->SkipPixels == 0 &&
-       unpack->SkipRows == 0) {
-      st->drawpix_cache.width = width;
-      st->drawpix_cache.height = height;
-      st->drawpix_cache.format = format;
-      st->drawpix_cache.type = type;
-      st->drawpix_cache.user_pointer = pixels;
-      assert(!st->drawpix_cache.image);
-      st->drawpix_cache.image = malloc(width * height * bpp);
-      if (st->drawpix_cache.image) {
-         memcpy(st->drawpix_cache.image, pixels, width * height * bpp);
-         pipe_resource_reference(&st->drawpix_cache.texture, pt);
-      }
-      else {
-         /* out of memory, free/disable cached texture */
-         st->drawpix_cache.width = 0;
-         st->drawpix_cache.height = 0;
-         pipe_resource_reference(&st->drawpix_cache.texture, NULL);
-      }
-   }
+   cache_drawpixels_image(st, width, height, format, type, unpack, pixels, pt);
 #endif
 
    return pt;
@@ -569,7 +640,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    const unsigned fb_width = _mesa_geometric_width(ctx->DrawBuffer);
    const unsigned fb_height = _mesa_geometric_height(ctx->DrawBuffer);
    GLfloat x0, y0, x1, y1;
-   GLsizei maxSize;
+   GLsizei MAYBE_UNUSED maxSize;
    boolean normalized = sv[0]->texture->target == PIPE_TEXTURE_2D;
    unsigned cso_state_mask;
 
@@ -666,11 +737,11 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
          const struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
          uint num = MAX3(fpv->drawpix_sampler + 1,
                          fpv->pixelmap_sampler + 1,
-                         st->state.num_samplers[PIPE_SHADER_FRAGMENT]);
+                         st->state.num_frag_samplers);
          uint i;
 
-         for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++)
-            samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i];
+         for (i = 0; i < st->state.num_frag_samplers; i++)
+            samplers[i] = &st->state.frag_samplers[i];
 
          samplers[fpv->drawpix_sampler] = &sampler;
          if (sv[1])
@@ -693,7 +764,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
                       fpv->pixelmap_sampler + 1,
                       st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
 
-      memcpy(sampler_views, st->state.sampler_views[PIPE_SHADER_FRAGMENT],
+      memcpy(sampler_views, st->state.frag_sampler_views,
              sizeof(sampler_views));
 
       sampler_views[fpv->drawpix_sampler] = sv[0];
@@ -1072,10 +1143,12 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
    /* Mesa state should be up to date by now */
    assert(ctx->NewState == 0x0);
 
+   _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
+
    st_flush_bitmap_cache(st);
    st_invalidate_readpix_cache(st);
 
-   st_validate_state(st, ST_PIPELINE_RENDER);
+   st_validate_state(st, ST_PIPELINE_META);
 
    /* Limit the size of the glDrawPixels to the max texture size.
     * Strictly speaking, that's not correct but since we don't handle
@@ -1317,7 +1390,7 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
        !ctx->FragmentProgram.Enabled &&
        !ctx->VertexProgram.Enabled &&
        !ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT] &&
-       !ctx->ATIFragmentShader._Enabled &&
+       !_mesa_ati_fragment_shader_enabled(ctx) &&
        ctx->DrawBuffer->_NumColorDrawBuffers == 1 &&
        !ctx->Query.CondRenderQuery &&
        !ctx->Query.CurrentOcclusionObject) {
@@ -1402,10 +1475,12 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
          if (screen->is_format_supported(screen, blit.src.format,
                                          blit.src.resource->target,
                                          blit.src.resource->nr_samples,
+                                         blit.src.resource->nr_storage_samples,
                                          PIPE_BIND_SAMPLER_VIEW) &&
              screen->is_format_supported(screen, blit.dst.format,
                                          blit.dst.resource->target,
                                          blit.dst.resource->nr_samples,
+                                         blit.dst.resource->nr_storage_samples,
                                          PIPE_BIND_RENDER_TARGET)) {
             pipe->blit(pipe, &blit);
             return GL_TRUE;
@@ -1437,10 +1512,12 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    GLint readX, readY, readW, readH;
    struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
 
+   _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
+
    st_flush_bitmap_cache(st);
    st_invalidate_readpix_cache(st);
 
-   st_validate_state(st, ST_PIPELINE_RENDER);
+   st_validate_state(st, ST_PIPELINE_META);
 
    if (type == GL_DEPTH_STENCIL) {
       /* XXX make this more efficient */
@@ -1503,11 +1580,11 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
       (type == GL_COLOR ? PIPE_BIND_RENDER_TARGET : PIPE_BIND_DEPTH_STENCIL);
 
    if (!screen->is_format_supported(screen, srcFormat, st->internal_target, 0,
-                                    srcBind)) {
+                                    0, srcBind)) {
       /* srcFormat is non-renderable. Find a compatible renderable format. */
       if (type == GL_DEPTH) {
          srcFormat = st_choose_format(st, GL_DEPTH_COMPONENT, GL_NONE,
-                                      GL_NONE, st->internal_target, 0,
+                                      GL_NONE, st->internal_target, 0, 0,
                                       srcBind, FALSE);
       }
       else {
@@ -1515,27 +1592,27 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
 
          if (util_format_is_float(srcFormat)) {
             srcFormat = st_choose_format(st, GL_RGBA32F, GL_NONE,
-                                         GL_NONE, st->internal_target, 0,
+                                         GL_NONE, st->internal_target, 0, 0,
                                          srcBind, FALSE);
          }
          else if (util_format_is_pure_sint(srcFormat)) {
             srcFormat = st_choose_format(st, GL_RGBA32I, GL_NONE,
-                                         GL_NONE, st->internal_target, 0,
+                                         GL_NONE, st->internal_target, 0, 0,
                                          srcBind, FALSE);
          }
          else if (util_format_is_pure_uint(srcFormat)) {
             srcFormat = st_choose_format(st, GL_RGBA32UI, GL_NONE,
-                                         GL_NONE, st->internal_target, 0,
+                                         GL_NONE, st->internal_target, 0, 0,
                                          srcBind, FALSE);
          }
          else if (util_format_is_snorm(srcFormat)) {
             srcFormat = st_choose_format(st, GL_RGBA16_SNORM, GL_NONE,
-                                         GL_NONE, st->internal_target, 0,
+                                         GL_NONE, st->internal_target, 0, 0,
                                          srcBind, FALSE);
          }
          else {
             srcFormat = st_choose_format(st, GL_RGBA, GL_NONE,
-                                         GL_NONE, st->internal_target, 0,
+                                         GL_NONE, st->internal_target, 0, 0,
                                          srcBind, FALSE);
          }
       }
@@ -1654,4 +1731,11 @@ st_destroy_drawpix(struct st_context *st)
       cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[0]);
    if (st->drawpix.vert_shaders[1])
       cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[1]);
+
+   /* Free cache data */
+   for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
+      struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
+      free(entry->image);
+      pipe_resource_reference(&entry->texture, NULL);
+   }
 }