replace _mesa_logbase2 with util_logbase2
[mesa.git] / src / mesa / state_tracker / st_atom_image.c
index f8a0044c24215f9d333c7f44b13d892de90f0353..598109d24f469f2f81b448524c9c767d7520feea 100644 (file)
@@ -24,7 +24,7 @@
  *
  **************************************************************************/
 
-#include "main/imports.h"
+#include "util/imports.h"
 #include "main/shaderimage.h"
 #include "program/prog_parameter.h"
 #include "program/prog_print.h"
@@ -36,6 +36,7 @@
 #include "util/u_surface.h"
 #include "cso_cache/cso_context.h"
 
+#include "st_cb_bufferobjects.h"
 #include "st_cb_texture.h"
 #include "st_debug.h"
 #include "st_texture.h"
 #include "st_program.h"
 #include "st_format.h"
 
-static void
-st_bind_images(struct st_context *st, struct gl_shader *shader,
-              unsigned shader_type)
+/**
+ * Convert a gl_image_unit object to a pipe_image_view object.
+ */
+void
+st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
+                 struct pipe_image_view *img, unsigned shader_access)
 {
-   unsigned i;
-   struct pipe_image_view images[MAX_IMAGE_UNIFORMS];
-   struct gl_program_constants *c;
+   struct st_texture_object *stObj = st_texture_object(u->TexObj);
+
+   img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat);
+
+   switch (u->Access) {
+   case GL_READ_ONLY:
+      img->access = PIPE_IMAGE_ACCESS_READ;
+      break;
+   case GL_WRITE_ONLY:
+      img->access = PIPE_IMAGE_ACCESS_WRITE;
+      break;
+   case GL_READ_WRITE:
+      img->access = PIPE_IMAGE_ACCESS_READ_WRITE;
+      break;
+   default:
+      unreachable("bad gl_image_unit::Access");
+   }
 
-   if (!shader || !st->pipe->set_shader_images)
-      return;
+   switch (shader_access) {
+   case GL_NONE:
+      img->shader_access = 0;
+      break;
+   case GL_READ_ONLY:
+      img->shader_access = PIPE_IMAGE_ACCESS_READ;
+      break;
+   case GL_WRITE_ONLY:
+      img->shader_access = PIPE_IMAGE_ACCESS_WRITE;
+      break;
+   case GL_READ_WRITE:
+      img->shader_access = PIPE_IMAGE_ACCESS_READ_WRITE;
+      break;
+   default:
+      unreachable("bad gl_image_unit::Access");
+   }
 
-   c = &st->ctx->Const.Program[shader->Stage];
+   if (stObj->base.Target == GL_TEXTURE_BUFFER) {
+      struct st_buffer_object *stbuf =
+         st_buffer_object(stObj->base.BufferObject);
+      unsigned base, size;
 
-   for (i = 0; i < shader->NumImages; i++) {
-      struct gl_image_unit *u = &st->ctx->ImageUnits[shader->ImageUnits[i]];
-      struct st_texture_object *stObj = st_texture_object(u->TexObj);
-      struct pipe_image_view *img = &images[i];
+      if (!stbuf || !stbuf->buffer) {
+         memset(img, 0, sizeof(*img));
+         return;
+      }
+      struct pipe_resource *buf = stbuf->buffer;
+
+      base = stObj->base.BufferOffset;
+      assert(base < buf->width0);
+      size = MIN2(buf->width0 - base, (unsigned)stObj->base.BufferSize);
 
-      if (!_mesa_is_image_unit_valid(st->ctx, u) ||
-          !st_finalize_texture(st->ctx, st->pipe, u->TexObj) ||
+      img->resource = stbuf->buffer;
+      img->u.buf.offset = base;
+      img->u.buf.size = size;
+   } else {
+      if (!st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) ||
           !stObj->pt) {
          memset(img, 0, sizeof(*img));
-         continue;
+         return;
       }
 
       img->resource = stObj->pt;
-      img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat);
-
-      switch (u->Access) {
-      case GL_READ_ONLY:
-         img->access = PIPE_IMAGE_ACCESS_READ;
-         break;
-      case GL_WRITE_ONLY:
-         img->access = PIPE_IMAGE_ACCESS_WRITE;
-         break;
-      case GL_READ_WRITE:
-         img->access = PIPE_IMAGE_ACCESS_READ_WRITE;
-         break;
-      default:
-         unreachable("bad gl_image_unit::Access");
-      }
-
-      if (stObj->pt->target == PIPE_BUFFER) {
-         unsigned base, size;
-         unsigned f, n;
-         const struct util_format_description *desc
-            = util_format_description(img->format);
-
-         base = stObj->base.BufferOffset;
-         assert(base < stObj->pt->width0);
-         size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
-
-         f = (base / (desc->block.bits / 8)) * desc->block.width;
-         n = (size / (desc->block.bits / 8)) * desc->block.width;
-         assert(n > 0);
-         img->u.buf.first_element = f;
-         img->u.buf.last_element  = f + (n - 1);
-      } else {
-         img->u.tex.level = u->Level + stObj->base.MinLevel;
-         if (stObj->pt->target == PIPE_TEXTURE_3D) {
-            if (u->Layered) {
-               img->u.tex.first_layer = 0;
-               img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
-            } else {
-               img->u.tex.first_layer = u->_Layer;
-               img->u.tex.last_layer = u->_Layer;
-            }
+      img->u.tex.level = u->Level + stObj->base.MinLevel;
+      assert(img->u.tex.level <= img->resource->last_level);
+      if (stObj->pt->target == PIPE_TEXTURE_3D) {
+         if (u->Layered) {
+            img->u.tex.first_layer = 0;
+            img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
          } else {
-            img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer;
-            img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer;
-            if (u->Layered && img->resource->array_size > 1) {
-               if (stObj->base.Immutable)
-                  img->u.tex.last_layer += stObj->base.NumLayers - 1;
-               else
-                  img->u.tex.last_layer += img->resource->array_size - 1;
-            }
+            img->u.tex.first_layer = u->_Layer;
+            img->u.tex.last_layer = u->_Layer;
+         }
+      } else {
+         img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer;
+         img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer;
+         if (u->Layered && img->resource->array_size > 1) {
+            if (stObj->base.Immutable)
+               img->u.tex.last_layer += stObj->base.NumLayers - 1;
+            else
+               img->u.tex.last_layer += img->resource->array_size - 1;
          }
       }
    }
-   cso_set_shader_images(st->cso_context, shader_type, 0, shader->NumImages,
-                         images);
-   /* clear out any stale shader images */
-   if (shader->NumImages < c->MaxImageUniforms)
-      cso_set_shader_images(
-            st->cso_context, shader_type,
-            shader->NumImages,
-            c->MaxImageUniforms - shader->NumImages,
-            NULL);
 }
 
-static void bind_vs_images(struct st_context *st)
+/**
+ * Get a pipe_image_view object from an image unit.
+ */
+void
+st_convert_image_from_unit(const struct st_context *st,
+                           struct pipe_image_view *img,
+                           GLuint imgUnit,
+                           unsigned shader_access)
 {
-   struct gl_shader_program *prog =
-      st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
+   struct gl_image_unit *u = &st->ctx->ImageUnits[imgUnit];
 
-   if (!prog)
+   if (!_mesa_is_image_unit_valid(st->ctx, u)) {
+      memset(img, 0, sizeof(*img));
       return;
+   }
 
-   st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_VERTEX], PIPE_SHADER_VERTEX);
+   st_convert_image(st, u, img, shader_access);
 }
 
-const struct st_tracked_state st_bind_vs_images = {
-   "st_bind_vs_images",
-   {
-      _NEW_TEXTURE,
-      ST_NEW_VERTEX_PROGRAM | ST_NEW_IMAGE_UNITS,
-   },
-   bind_vs_images
-};
-
-static void bind_fs_images(struct st_context *st)
+static void
+st_bind_images(struct st_context *st, struct gl_program *prog,
+               enum pipe_shader_type shader_type)
 {
-   struct gl_shader_program *prog =
-      st->ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
+   unsigned i;
+   struct pipe_image_view images[MAX_IMAGE_UNIFORMS];
+   struct gl_program_constants *c;
 
-   if (!prog)
+   if (!prog || !st->pipe->set_shader_images)
       return;
 
-   st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_FRAGMENT], PIPE_SHADER_FRAGMENT);
-}
+   c = &st->ctx->Const.Program[prog->info.stage];
 
-const struct st_tracked_state st_bind_fs_images = {
-   "st_bind_fs_images",
-   {
-      _NEW_TEXTURE,
-      ST_NEW_FRAGMENT_PROGRAM | ST_NEW_IMAGE_UNITS,
-   },
-   bind_fs_images
-};
+   for (i = 0; i < prog->info.num_images; i++) {
+      struct pipe_image_view *img = &images[i];
 
-static void bind_gs_images(struct st_context *st)
+      st_convert_image_from_unit(st, img, prog->sh.ImageUnits[i],
+                                 prog->sh.ImageAccess[i]);
+   }
+   cso_set_shader_images(st->cso_context, shader_type, 0,
+                         prog->info.num_images, images);
+   /* clear out any stale shader images */
+   if (prog->info.num_images < c->MaxImageUniforms)
+      cso_set_shader_images(
+            st->cso_context, shader_type, prog->info.num_images,
+            c->MaxImageUniforms - prog->info.num_images, NULL);
+}
+
+void st_bind_vs_images(struct st_context *st)
 {
-   struct gl_shader_program *prog =
-      st->ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
+   struct gl_program *prog =
+      st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
 
-   if (!prog)
-      return;
+   st_bind_images(st, prog, PIPE_SHADER_VERTEX);
+}
+
+void st_bind_fs_images(struct st_context *st)
+{
+   struct gl_program *prog =
+      st->ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
 
-   st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_GEOMETRY], PIPE_SHADER_GEOMETRY);
+   st_bind_images(st, prog, PIPE_SHADER_FRAGMENT);
 }
 
-const struct st_tracked_state st_bind_gs_images = {
-   "st_bind_gs_images",
-   {
-      _NEW_TEXTURE,
-      ST_NEW_GEOMETRY_PROGRAM | ST_NEW_IMAGE_UNITS,
-   },
-   bind_gs_images
-};
+void st_bind_gs_images(struct st_context *st)
+{
+   struct gl_program *prog =
+      st->ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
+
+   st_bind_images(st, prog, PIPE_SHADER_GEOMETRY);
+}
 
-static void bind_tcs_images(struct st_context *st)
+void st_bind_tcs_images(struct st_context *st)
 {
-   struct gl_shader_program *prog =
+   struct gl_program *prog =
       st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
 
-   if (!prog)
-      return;
-
-   st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_TESS_CTRL], PIPE_SHADER_TESS_CTRL);
+   st_bind_images(st, prog, PIPE_SHADER_TESS_CTRL);
 }
 
-const struct st_tracked_state st_bind_tcs_images = {
-   "st_bind_tcs_images",
-   {
-      _NEW_TEXTURE,
-      ST_NEW_TESSCTRL_PROGRAM | ST_NEW_IMAGE_UNITS,
-   },
-   bind_tcs_images
-};
-
-static void bind_tes_images(struct st_context *st)
+void st_bind_tes_images(struct st_context *st)
 {
-   struct gl_shader_program *prog =
+   struct gl_program *prog =
       st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
 
-   if (!prog)
-      return;
-
-   st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_TESS_EVAL], PIPE_SHADER_TESS_EVAL);
+   st_bind_images(st, prog, PIPE_SHADER_TESS_EVAL);
 }
 
-const struct st_tracked_state st_bind_tes_images = {
-   "st_bind_tes_images",
-   {
-      _NEW_TEXTURE,
-      ST_NEW_TESSEVAL_PROGRAM | ST_NEW_IMAGE_UNITS,
-   },
-   bind_tes_images
-};
-
-static void bind_cs_images(struct st_context *st)
+void st_bind_cs_images(struct st_context *st)
 {
-   struct gl_shader_program *prog =
+   struct gl_program *prog =
       st->ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
 
-   if (!prog)
-      return;
-
-   st_bind_images(st, prog->_LinkedShaders[MESA_SHADER_COMPUTE], PIPE_SHADER_COMPUTE);
+   st_bind_images(st, prog, PIPE_SHADER_COMPUTE);
 }
-
-const struct st_tracked_state st_bind_cs_images = {
-   "st_bind_cs_images",
-   {
-      _NEW_TEXTURE,
-      ST_NEW_COMPUTE_PROGRAM | ST_NEW_IMAGE_UNITS,
-   },
-   bind_cs_images
-};