1/**************************************************************************
2 *
3 * Copyright 2016 Ilia Mirkin. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27#include "main/imports.h"
28#include "main/shaderimage.h"
29#include "program/prog_parameter.h"
30#include "program/prog_print.h"
31#include "compiler/glsl/ir_uniform.h"
32
33#include "pipe/p_context.h"
34#include "pipe/p_defines.h"
35#include "util/u_inlines.h"
36#include "util/u_surface.h"
37#include "cso_cache/cso_context.h"
38
39#include "st_cb_bufferobjects.h"
40#include "st_cb_texture.h"
41#include "st_debug.h"
42#include "st_texture.h"
43#include "st_context.h"
44#include "st_atom.h"
45#include "st_program.h"
46#include "st_format.h"
47
48/**
49 * Convert a gl_image_unit object to a pipe_image_view object.
50 */
51void
52st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
53                 struct pipe_image_view *img, unsigned shader_access)
54{
55   struct st_texture_object *stObj = st_texture_object(u->TexObj);
56
57   img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat);
58
59   switch (u->Access) {
60   case GL_READ_ONLY:
61      img->access = PIPE_IMAGE_ACCESS_READ;
62      break;
63   case GL_WRITE_ONLY:
64      img->access = PIPE_IMAGE_ACCESS_WRITE;
65      break;
66   case GL_READ_WRITE:
67      img->access = PIPE_IMAGE_ACCESS_READ_WRITE;
68      break;
69   default:
70      unreachable("bad gl_image_unit::Access");
71   }
72
73   switch (shader_access) {
74   case GL_NONE:
75      img->shader_access = 0;
76      break;
77   case GL_READ_ONLY:
78      img->shader_access = PIPE_IMAGE_ACCESS_READ;
79      break;
80   case GL_WRITE_ONLY:
81      img->shader_access = PIPE_IMAGE_ACCESS_WRITE;
82      break;
83   case GL_READ_WRITE:
84      img->shader_access = PIPE_IMAGE_ACCESS_READ_WRITE;
85      break;
86   default:
87      unreachable("bad gl_image_unit::Access");
88   }
89
90   if (stObj->base.Target == GL_TEXTURE_BUFFER) {
91      struct st_buffer_object *stbuf =
92         st_buffer_object(stObj->base.BufferObject);
93      unsigned base, size;
94
95      if (!stbuf || !stbuf->buffer) {
96         memset(img, 0, sizeof(*img));
97         return;
98      }
99      struct pipe_resource *buf = stbuf->buffer;
100
101      base = stObj->base.BufferOffset;
102      assert(base < buf->width0);
103      size = MIN2(buf->width0 - base, (unsigned)stObj->base.BufferSize);
104
105      img->resource = stbuf->buffer;
106      img->u.buf.offset = base;
107      img->u.buf.size = size;
108   } else {
109      if (!st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) ||
110          !stObj->pt) {
111         memset(img, 0, sizeof(*img));
112         return;
113      }
114
115      img->resource = stObj->pt;
116      img->u.tex.level = u->Level + stObj->base.MinLevel;
117      assert(img->u.tex.level <= img->resource->last_level);
118      if (stObj->pt->target == PIPE_TEXTURE_3D) {
119         if (u->Layered) {
120            img->u.tex.first_layer = 0;
121            img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
122         } else {
123            img->u.tex.first_layer = u->_Layer;
124            img->u.tex.last_layer = u->_Layer;
125         }
126      } else {
127         img->u.tex.first_layer = u->_Layer + stObj->base.MinLayer;
128         img->u.tex.last_layer = u->_Layer + stObj->base.MinLayer;
129         if (u->Layered && img->resource->array_size > 1) {
130            if (stObj->base.Immutable)
131               img->u.tex.last_layer += stObj->base.NumLayers - 1;
132            else
133               img->u.tex.last_layer += img->resource->array_size - 1;
134         }
135      }
136   }
137}
138
139/**
140 * Get a pipe_image_view object from an image unit.
141 */
142void
143st_convert_image_from_unit(const struct st_context *st,
144                           struct pipe_image_view *img,
145                           GLuint imgUnit,
146                           unsigned shader_access)
147{
148   struct gl_image_unit *u = &st->ctx->ImageUnits[imgUnit];
149
150   if (!_mesa_is_image_unit_valid(st->ctx, u)) {
151      memset(img, 0, sizeof(*img));
152      return;
153   }
154
155   st_convert_image(st, u, img, shader_access);
156}
157
158static void
159st_bind_images(struct st_context *st, struct gl_program *prog,
160               enum pipe_shader_type shader_type)
161{
162   unsigned i;
163   struct pipe_image_view images[MAX_IMAGE_UNIFORMS];
164   struct gl_program_constants *c;
165
166   if (!prog || !st->pipe->set_shader_images)
167      return;
168
169   c = &st->ctx->Const.Program[prog->info.stage];
170
171   for (i = 0; i < prog->info.num_images; i++) {
172      struct pipe_image_view *img = &images[i];
173
174      st_convert_image_from_unit(st, img, prog->sh.ImageUnits[i],
175                                 prog->sh.ImageAccess[i]);
176   }
177   cso_set_shader_images(st->cso_context, shader_type, 0,
178                         prog->info.num_images, images);
179   /* clear out any stale shader images */
180   if (prog->info.num_images < c->MaxImageUniforms)
181      cso_set_shader_images(
182            st->cso_context, shader_type, prog->info.num_images,
183            c->MaxImageUniforms - prog->info.num_images, NULL);
184}
185
186void st_bind_vs_images(struct st_context *st)
187{
188   struct gl_program *prog =
189      st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
190
191   st_bind_images(st, prog, PIPE_SHADER_VERTEX);
192}
193
194void st_bind_fs_images(struct st_context *st)
195{
196   struct gl_program *prog =
197      st->ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
198
199   st_bind_images(st, prog, PIPE_SHADER_FRAGMENT);
200}
201
202void st_bind_gs_images(struct st_context *st)
203{
204   struct gl_program *prog =
205      st->ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
206
207   st_bind_images(st, prog, PIPE_SHADER_GEOMETRY);
208}
209
210void st_bind_tcs_images(struct st_context *st)
211{
212   struct gl_program *prog =
213      st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL];
214
215   st_bind_images(st, prog, PIPE_SHADER_TESS_CTRL);
216}
217
218void st_bind_tes_images(struct st_context *st)
219{
220   struct gl_program *prog =
221      st->ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
222
223   st_bind_images(st, prog, PIPE_SHADER_TESS_EVAL);
224}
225
226void st_bind_cs_images(struct st_context *st)
227{
228   struct gl_program *prog =
229      st->ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
230
231   st_bind_images(st, prog, PIPE_SHADER_COMPUTE);
232}
233