shaderimage.c revision b9abf16e
1af69d88dSmrg/*
2af69d88dSmrg * Copyright 2013 Intel Corporation
3af69d88dSmrg *
4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5af69d88dSmrg * copy of this software and associated documentation files (the "Software"),
6af69d88dSmrg * to deal in the Software without restriction, including without limitation
7af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the
9af69d88dSmrg * Software is furnished to do so, subject to the following conditions:
10af69d88dSmrg *
11af69d88dSmrg * The above copyright notice and this permission notice (including the next
12af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the
13af69d88dSmrg * Software.
14af69d88dSmrg *
15af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20af69d88dSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21af69d88dSmrg * DEALINGS IN THE SOFTWARE.
22af69d88dSmrg *
23af69d88dSmrg * Authors:
24af69d88dSmrg *    Francisco Jerez <currojerez@riseup.net>
25af69d88dSmrg */
26af69d88dSmrg
27af69d88dSmrg#include <assert.h>
28af69d88dSmrg
29af69d88dSmrg#include "shaderimage.h"
30af69d88dSmrg#include "mtypes.h"
31af69d88dSmrg#include "formats.h"
32af69d88dSmrg#include "errors.h"
3301e04c3fSmrg#include "hash.h"
34af69d88dSmrg#include "context.h"
35af69d88dSmrg#include "texobj.h"
36af69d88dSmrg#include "teximage.h"
37af69d88dSmrg#include "enums.h"
38af69d88dSmrg
39af69d88dSmrg/*
40af69d88dSmrg * Define endian-invariant aliases for some mesa formats that are
41af69d88dSmrg * defined in terms of their channel layout from LSB to MSB in a
42af69d88dSmrg * 32-bit word.  The actual byte offsets matter here because the user
43af69d88dSmrg * is allowed to bit-cast one format into another and get predictable
44af69d88dSmrg * results.
45af69d88dSmrg */
46af69d88dSmrg#ifdef MESA_BIG_ENDIAN
47af69d88dSmrg# define MESA_FORMAT_RGBA_8 MESA_FORMAT_A8B8G8R8_UNORM
48af69d88dSmrg# define MESA_FORMAT_RG_16 MESA_FORMAT_G16R16_UNORM
49af69d88dSmrg# define MESA_FORMAT_RG_8 MESA_FORMAT_G8R8_UNORM
50af69d88dSmrg# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_A8B8G8R8_SNORM
51af69d88dSmrg# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_G16R16_SNORM
52af69d88dSmrg# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_G8R8_SNORM
53af69d88dSmrg#else
54af69d88dSmrg# define MESA_FORMAT_RGBA_8 MESA_FORMAT_R8G8B8A8_UNORM
55af69d88dSmrg# define MESA_FORMAT_RG_16 MESA_FORMAT_R16G16_UNORM
56af69d88dSmrg# define MESA_FORMAT_RG_8 MESA_FORMAT_R8G8_UNORM
57af69d88dSmrg# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_R8G8B8A8_SNORM
58af69d88dSmrg# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_R16G16_SNORM
59af69d88dSmrg# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_R8G8_SNORM
60af69d88dSmrg#endif
61af69d88dSmrg
6201e04c3fSmrgmesa_format
6301e04c3fSmrg_mesa_get_shader_image_format(GLenum format)
64af69d88dSmrg{
65af69d88dSmrg   switch (format) {
66af69d88dSmrg   case GL_RGBA32F:
67af69d88dSmrg      return MESA_FORMAT_RGBA_FLOAT32;
68af69d88dSmrg
69af69d88dSmrg   case GL_RGBA16F:
70af69d88dSmrg      return MESA_FORMAT_RGBA_FLOAT16;
71af69d88dSmrg
72af69d88dSmrg   case GL_RG32F:
73af69d88dSmrg      return MESA_FORMAT_RG_FLOAT32;
74af69d88dSmrg
75af69d88dSmrg   case GL_RG16F:
76af69d88dSmrg      return MESA_FORMAT_RG_FLOAT16;
77af69d88dSmrg
78af69d88dSmrg   case GL_R11F_G11F_B10F:
79af69d88dSmrg      return MESA_FORMAT_R11G11B10_FLOAT;
80af69d88dSmrg
81af69d88dSmrg   case GL_R32F:
82af69d88dSmrg      return MESA_FORMAT_R_FLOAT32;
83af69d88dSmrg
84af69d88dSmrg   case GL_R16F:
85af69d88dSmrg      return MESA_FORMAT_R_FLOAT16;
86af69d88dSmrg
87af69d88dSmrg   case GL_RGBA32UI:
88af69d88dSmrg      return MESA_FORMAT_RGBA_UINT32;
89af69d88dSmrg
90af69d88dSmrg   case GL_RGBA16UI:
91af69d88dSmrg      return MESA_FORMAT_RGBA_UINT16;
92af69d88dSmrg
93af69d88dSmrg   case GL_RGB10_A2UI:
94af69d88dSmrg      return MESA_FORMAT_R10G10B10A2_UINT;
95af69d88dSmrg
96af69d88dSmrg   case GL_RGBA8UI:
97af69d88dSmrg      return MESA_FORMAT_RGBA_UINT8;
98af69d88dSmrg
99af69d88dSmrg   case GL_RG32UI:
100af69d88dSmrg      return MESA_FORMAT_RG_UINT32;
101af69d88dSmrg
102af69d88dSmrg   case GL_RG16UI:
103af69d88dSmrg      return MESA_FORMAT_RG_UINT16;
104af69d88dSmrg
105af69d88dSmrg   case GL_RG8UI:
106af69d88dSmrg      return MESA_FORMAT_RG_UINT8;
107af69d88dSmrg
108af69d88dSmrg   case GL_R32UI:
109af69d88dSmrg      return MESA_FORMAT_R_UINT32;
110af69d88dSmrg
111af69d88dSmrg   case GL_R16UI:
112af69d88dSmrg      return MESA_FORMAT_R_UINT16;
113af69d88dSmrg
114af69d88dSmrg   case GL_R8UI:
115af69d88dSmrg      return MESA_FORMAT_R_UINT8;
116af69d88dSmrg
117af69d88dSmrg   case GL_RGBA32I:
118af69d88dSmrg      return MESA_FORMAT_RGBA_SINT32;
119af69d88dSmrg
120af69d88dSmrg   case GL_RGBA16I:
121af69d88dSmrg      return MESA_FORMAT_RGBA_SINT16;
122af69d88dSmrg
123af69d88dSmrg   case GL_RGBA8I:
124af69d88dSmrg      return MESA_FORMAT_RGBA_SINT8;
125af69d88dSmrg
126af69d88dSmrg   case GL_RG32I:
127af69d88dSmrg      return MESA_FORMAT_RG_SINT32;
128af69d88dSmrg
129af69d88dSmrg   case GL_RG16I:
130af69d88dSmrg      return MESA_FORMAT_RG_SINT16;
131af69d88dSmrg
132af69d88dSmrg   case GL_RG8I:
133af69d88dSmrg      return MESA_FORMAT_RG_SINT8;
134af69d88dSmrg
135af69d88dSmrg   case GL_R32I:
136af69d88dSmrg      return MESA_FORMAT_R_SINT32;
137af69d88dSmrg
138af69d88dSmrg   case GL_R16I:
139af69d88dSmrg      return MESA_FORMAT_R_SINT16;
140af69d88dSmrg
141af69d88dSmrg   case GL_R8I:
142af69d88dSmrg      return MESA_FORMAT_R_SINT8;
143af69d88dSmrg
144af69d88dSmrg   case GL_RGBA16:
145af69d88dSmrg      return MESA_FORMAT_RGBA_UNORM16;
146af69d88dSmrg
147af69d88dSmrg   case GL_RGB10_A2:
148af69d88dSmrg      return MESA_FORMAT_R10G10B10A2_UNORM;
149af69d88dSmrg
150af69d88dSmrg   case GL_RGBA8:
151af69d88dSmrg      return MESA_FORMAT_RGBA_8;
152af69d88dSmrg
153af69d88dSmrg   case GL_RG16:
154af69d88dSmrg      return MESA_FORMAT_RG_16;
155af69d88dSmrg
156af69d88dSmrg   case GL_RG8:
157af69d88dSmrg      return MESA_FORMAT_RG_8;
158af69d88dSmrg
159af69d88dSmrg   case GL_R16:
160af69d88dSmrg      return MESA_FORMAT_R_UNORM16;
161af69d88dSmrg
162af69d88dSmrg   case GL_R8:
163af69d88dSmrg      return MESA_FORMAT_R_UNORM8;
164af69d88dSmrg
165af69d88dSmrg   case GL_RGBA16_SNORM:
166af69d88dSmrg      return MESA_FORMAT_RGBA_SNORM16;
167af69d88dSmrg
168af69d88dSmrg   case GL_RGBA8_SNORM:
169af69d88dSmrg      return MESA_FORMAT_SIGNED_RGBA_8;
170af69d88dSmrg
171af69d88dSmrg   case GL_RG16_SNORM:
172af69d88dSmrg      return MESA_FORMAT_SIGNED_RG_16;
173af69d88dSmrg
174af69d88dSmrg   case GL_RG8_SNORM:
175af69d88dSmrg      return MESA_FORMAT_SIGNED_RG_8;
176af69d88dSmrg
177af69d88dSmrg   case GL_R16_SNORM:
178af69d88dSmrg      return MESA_FORMAT_R_SNORM16;
179af69d88dSmrg
180af69d88dSmrg   case GL_R8_SNORM:
181af69d88dSmrg      return MESA_FORMAT_R_SNORM8;
182af69d88dSmrg
183af69d88dSmrg   default:
184af69d88dSmrg      return MESA_FORMAT_NONE;
185af69d88dSmrg   }
186af69d88dSmrg}
187af69d88dSmrg
188af69d88dSmrgenum image_format_class
189af69d88dSmrg{
190af69d88dSmrg   /** Not a valid image format. */
191af69d88dSmrg   IMAGE_FORMAT_CLASS_NONE = 0,
192af69d88dSmrg
193af69d88dSmrg   /** Classes of image formats you can cast into each other. */
194af69d88dSmrg   /** \{ */
195af69d88dSmrg   IMAGE_FORMAT_CLASS_1X8,
196af69d88dSmrg   IMAGE_FORMAT_CLASS_1X16,
197af69d88dSmrg   IMAGE_FORMAT_CLASS_1X32,
198af69d88dSmrg   IMAGE_FORMAT_CLASS_2X8,
199af69d88dSmrg   IMAGE_FORMAT_CLASS_2X16,
200af69d88dSmrg   IMAGE_FORMAT_CLASS_2X32,
201af69d88dSmrg   IMAGE_FORMAT_CLASS_10_11_11,
202af69d88dSmrg   IMAGE_FORMAT_CLASS_4X8,
203af69d88dSmrg   IMAGE_FORMAT_CLASS_4X16,
204af69d88dSmrg   IMAGE_FORMAT_CLASS_4X32,
205af69d88dSmrg   IMAGE_FORMAT_CLASS_2_10_10_10
206af69d88dSmrg   /** \} */
207af69d88dSmrg};
208af69d88dSmrg
209af69d88dSmrgstatic enum image_format_class
210af69d88dSmrgget_image_format_class(mesa_format format)
211af69d88dSmrg{
212af69d88dSmrg   switch (format) {
213af69d88dSmrg   case MESA_FORMAT_RGBA_FLOAT32:
214af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X32;
215af69d88dSmrg
216af69d88dSmrg   case MESA_FORMAT_RGBA_FLOAT16:
217af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
218af69d88dSmrg
219af69d88dSmrg   case MESA_FORMAT_RG_FLOAT32:
220af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X32;
221af69d88dSmrg
222af69d88dSmrg   case MESA_FORMAT_RG_FLOAT16:
223af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
224af69d88dSmrg
225af69d88dSmrg   case MESA_FORMAT_R11G11B10_FLOAT:
226af69d88dSmrg      return IMAGE_FORMAT_CLASS_10_11_11;
227af69d88dSmrg
228af69d88dSmrg   case MESA_FORMAT_R_FLOAT32:
229af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X32;
230af69d88dSmrg
231af69d88dSmrg   case MESA_FORMAT_R_FLOAT16:
232af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
233af69d88dSmrg
234af69d88dSmrg   case MESA_FORMAT_RGBA_UINT32:
235af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X32;
236af69d88dSmrg
237af69d88dSmrg   case MESA_FORMAT_RGBA_UINT16:
238af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
239af69d88dSmrg
240af69d88dSmrg   case MESA_FORMAT_R10G10B10A2_UINT:
241af69d88dSmrg      return IMAGE_FORMAT_CLASS_2_10_10_10;
242af69d88dSmrg
243af69d88dSmrg   case MESA_FORMAT_RGBA_UINT8:
244af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
245af69d88dSmrg
246af69d88dSmrg   case MESA_FORMAT_RG_UINT32:
247af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X32;
248af69d88dSmrg
249af69d88dSmrg   case MESA_FORMAT_RG_UINT16:
250af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
251af69d88dSmrg
252af69d88dSmrg   case MESA_FORMAT_RG_UINT8:
253af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
254af69d88dSmrg
255af69d88dSmrg   case MESA_FORMAT_R_UINT32:
256af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X32;
257af69d88dSmrg
258af69d88dSmrg   case MESA_FORMAT_R_UINT16:
259af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
260af69d88dSmrg
261af69d88dSmrg   case MESA_FORMAT_R_UINT8:
262af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
263af69d88dSmrg
264af69d88dSmrg   case MESA_FORMAT_RGBA_SINT32:
265af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X32;
266af69d88dSmrg
267af69d88dSmrg   case MESA_FORMAT_RGBA_SINT16:
268af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
269af69d88dSmrg
270af69d88dSmrg   case MESA_FORMAT_RGBA_SINT8:
271af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
272af69d88dSmrg
273af69d88dSmrg   case MESA_FORMAT_RG_SINT32:
274af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X32;
275af69d88dSmrg
276af69d88dSmrg   case MESA_FORMAT_RG_SINT16:
277af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
278af69d88dSmrg
279af69d88dSmrg   case MESA_FORMAT_RG_SINT8:
280af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
281af69d88dSmrg
282af69d88dSmrg   case MESA_FORMAT_R_SINT32:
283af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X32;
284af69d88dSmrg
285af69d88dSmrg   case MESA_FORMAT_R_SINT16:
286af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
287af69d88dSmrg
288af69d88dSmrg   case MESA_FORMAT_R_SINT8:
289af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
290af69d88dSmrg
291af69d88dSmrg   case MESA_FORMAT_RGBA_UNORM16:
292af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
293af69d88dSmrg
294af69d88dSmrg   case MESA_FORMAT_R10G10B10A2_UNORM:
295af69d88dSmrg      return IMAGE_FORMAT_CLASS_2_10_10_10;
296af69d88dSmrg
297af69d88dSmrg   case MESA_FORMAT_RGBA_8:
298af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
299af69d88dSmrg
300af69d88dSmrg   case MESA_FORMAT_RG_16:
301af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
302af69d88dSmrg
303af69d88dSmrg   case MESA_FORMAT_RG_8:
304af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
305af69d88dSmrg
306af69d88dSmrg   case MESA_FORMAT_R_UNORM16:
307af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
308af69d88dSmrg
309af69d88dSmrg   case MESA_FORMAT_R_UNORM8:
310af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
311af69d88dSmrg
312af69d88dSmrg   case MESA_FORMAT_RGBA_SNORM16:
313af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
314af69d88dSmrg
315af69d88dSmrg   case MESA_FORMAT_SIGNED_RGBA_8:
316af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
317af69d88dSmrg
318af69d88dSmrg   case MESA_FORMAT_SIGNED_RG_16:
319af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
320af69d88dSmrg
321af69d88dSmrg   case MESA_FORMAT_SIGNED_RG_8:
322af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
323af69d88dSmrg
324af69d88dSmrg   case MESA_FORMAT_R_SNORM16:
325af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
326af69d88dSmrg
327af69d88dSmrg   case MESA_FORMAT_R_SNORM8:
328af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
329af69d88dSmrg
330af69d88dSmrg   default:
331af69d88dSmrg      return IMAGE_FORMAT_CLASS_NONE;
332af69d88dSmrg   }
333af69d88dSmrg}
334af69d88dSmrg
33501e04c3fSmrgstatic GLenum
33601e04c3fSmrg_image_format_class_to_glenum(enum image_format_class class)
33701e04c3fSmrg{
33801e04c3fSmrg   switch (class) {
33901e04c3fSmrg   case IMAGE_FORMAT_CLASS_NONE:
34001e04c3fSmrg      return GL_NONE;
34101e04c3fSmrg   case IMAGE_FORMAT_CLASS_1X8:
34201e04c3fSmrg      return GL_IMAGE_CLASS_1_X_8;
34301e04c3fSmrg   case IMAGE_FORMAT_CLASS_1X16:
34401e04c3fSmrg      return GL_IMAGE_CLASS_1_X_16;
34501e04c3fSmrg   case IMAGE_FORMAT_CLASS_1X32:
34601e04c3fSmrg      return GL_IMAGE_CLASS_1_X_32;
34701e04c3fSmrg   case IMAGE_FORMAT_CLASS_2X8:
34801e04c3fSmrg      return GL_IMAGE_CLASS_2_X_8;
34901e04c3fSmrg   case IMAGE_FORMAT_CLASS_2X16:
35001e04c3fSmrg      return GL_IMAGE_CLASS_2_X_16;
35101e04c3fSmrg   case IMAGE_FORMAT_CLASS_2X32:
35201e04c3fSmrg      return GL_IMAGE_CLASS_2_X_32;
35301e04c3fSmrg   case IMAGE_FORMAT_CLASS_10_11_11:
35401e04c3fSmrg      return GL_IMAGE_CLASS_11_11_10;
35501e04c3fSmrg   case IMAGE_FORMAT_CLASS_4X8:
35601e04c3fSmrg      return GL_IMAGE_CLASS_4_X_8;
35701e04c3fSmrg   case IMAGE_FORMAT_CLASS_4X16:
35801e04c3fSmrg      return GL_IMAGE_CLASS_4_X_16;
35901e04c3fSmrg   case IMAGE_FORMAT_CLASS_4X32:
36001e04c3fSmrg      return GL_IMAGE_CLASS_4_X_32;
36101e04c3fSmrg   case IMAGE_FORMAT_CLASS_2_10_10_10:
36201e04c3fSmrg      return GL_IMAGE_CLASS_10_10_10_2;
36301e04c3fSmrg   default:
36401e04c3fSmrg      assert(!"Invalid image_format_class");
36501e04c3fSmrg      return GL_NONE;
36601e04c3fSmrg   }
36701e04c3fSmrg}
36801e04c3fSmrg
36901e04c3fSmrgGLenum
37001e04c3fSmrg_mesa_get_image_format_class(GLenum format)
37101e04c3fSmrg{
37201e04c3fSmrg   mesa_format tex_format = _mesa_get_shader_image_format(format);
37301e04c3fSmrg   if (tex_format == MESA_FORMAT_NONE)
37401e04c3fSmrg      return GL_NONE;
37501e04c3fSmrg
37601e04c3fSmrg   enum image_format_class class = get_image_format_class(tex_format);
37701e04c3fSmrg   return _image_format_class_to_glenum(class);
37801e04c3fSmrg}
37901e04c3fSmrg
38001e04c3fSmrgbool
38101e04c3fSmrg_mesa_is_shader_image_format_supported(const struct gl_context *ctx,
38201e04c3fSmrg                                       GLenum format)
38301e04c3fSmrg{
38401e04c3fSmrg   switch (format) {
38501e04c3fSmrg   /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the
38601e04c3fSmrg    * OpenGL ES 3.1 specification.
38701e04c3fSmrg    */
38801e04c3fSmrg   case GL_RGBA32F:
38901e04c3fSmrg   case GL_RGBA16F:
39001e04c3fSmrg   case GL_R32F:
39101e04c3fSmrg   case GL_RGBA32UI:
39201e04c3fSmrg   case GL_RGBA16UI:
39301e04c3fSmrg   case GL_RGBA8UI:
39401e04c3fSmrg   case GL_R32UI:
39501e04c3fSmrg   case GL_RGBA32I:
39601e04c3fSmrg   case GL_RGBA16I:
39701e04c3fSmrg   case GL_RGBA8I:
39801e04c3fSmrg   case GL_R32I:
39901e04c3fSmrg   case GL_RGBA8:
40001e04c3fSmrg   case GL_RGBA8_SNORM:
40101e04c3fSmrg      return true;
40201e04c3fSmrg
40301e04c3fSmrg   /* Formats supported on unextended desktop GL and the original
40401e04c3fSmrg    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
40501e04c3fSmrg    * specification or by GLES 3.1 with GL_NV_image_formats extension.
40601e04c3fSmrg    */
40701e04c3fSmrg   case GL_RG32F:
40801e04c3fSmrg   case GL_RG16F:
40901e04c3fSmrg   case GL_R11F_G11F_B10F:
41001e04c3fSmrg   case GL_R16F:
41101e04c3fSmrg   case GL_RGB10_A2UI:
41201e04c3fSmrg   case GL_RG32UI:
41301e04c3fSmrg   case GL_RG16UI:
41401e04c3fSmrg   case GL_RG8UI:
41501e04c3fSmrg   case GL_R16UI:
41601e04c3fSmrg   case GL_R8UI:
41701e04c3fSmrg   case GL_RG32I:
41801e04c3fSmrg   case GL_RG16I:
41901e04c3fSmrg   case GL_RG8I:
42001e04c3fSmrg   case GL_R16I:
42101e04c3fSmrg   case GL_R8I:
42201e04c3fSmrg   case GL_RGB10_A2:
42301e04c3fSmrg   case GL_RG8:
42401e04c3fSmrg   case GL_R8:
42501e04c3fSmrg   case GL_RG8_SNORM:
42601e04c3fSmrg   case GL_R8_SNORM:
42701e04c3fSmrg      return true;
42801e04c3fSmrg
42901e04c3fSmrg   /* Formats supported on unextended desktop GL and the original
43001e04c3fSmrg    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
43101e04c3fSmrg    * specification.
43201e04c3fSmrg    *
43301e04c3fSmrg    * Following formats are supported by GLES 3.1 with GL_NV_image_formats &
43401e04c3fSmrg    * GL_EXT_texture_norm16 extensions.
43501e04c3fSmrg    */
43601e04c3fSmrg   case GL_RGBA16:
43701e04c3fSmrg   case GL_RGBA16_SNORM:
43801e04c3fSmrg   case GL_RG16:
43901e04c3fSmrg   case GL_RG16_SNORM:
44001e04c3fSmrg   case GL_R16:
44101e04c3fSmrg   case GL_R16_SNORM:
44201e04c3fSmrg      return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx);
44301e04c3fSmrg
44401e04c3fSmrg   default:
44501e04c3fSmrg      return false;
44601e04c3fSmrg   }
44701e04c3fSmrg}
44801e04c3fSmrg
44901e04c3fSmrgstruct gl_image_unit
45001e04c3fSmrg_mesa_default_image_unit(struct gl_context *ctx)
45101e04c3fSmrg{
45201e04c3fSmrg   const GLenum format = _mesa_is_desktop_gl(ctx) ? GL_R8 : GL_R32UI;
45301e04c3fSmrg   const struct gl_image_unit u = {
45401e04c3fSmrg      .Access = GL_READ_ONLY,
45501e04c3fSmrg      .Format = format,
45601e04c3fSmrg      ._ActualFormat = _mesa_get_shader_image_format(format)
45701e04c3fSmrg   };
45801e04c3fSmrg   return u;
45901e04c3fSmrg}
46001e04c3fSmrg
46101e04c3fSmrgvoid
46201e04c3fSmrg_mesa_init_image_units(struct gl_context *ctx)
46301e04c3fSmrg{
46401e04c3fSmrg   unsigned i;
46501e04c3fSmrg
46601e04c3fSmrg   ASSERT_BITFIELD_SIZE(struct gl_image_unit, Format, MESA_FORMAT_COUNT);
46701e04c3fSmrg
46801e04c3fSmrg   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
46901e04c3fSmrg      ctx->ImageUnits[i] = _mesa_default_image_unit(ctx);
47001e04c3fSmrg}
47101e04c3fSmrg
472b9abf16eSmaya
473b9abf16eSmayavoid
474b9abf16eSmaya_mesa_free_image_textures(struct gl_context *ctx)
475b9abf16eSmaya{
476b9abf16eSmaya   unsigned i;
477b9abf16eSmaya
478b9abf16eSmaya   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
479b9abf16eSmaya      _mesa_reference_texobj(&ctx->ImageUnits[i].TexObj, NULL);
480b9abf16eSmaya}
481b9abf16eSmaya
48201e04c3fSmrgGLboolean
48301e04c3fSmrg_mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u)
484af69d88dSmrg{
485af69d88dSmrg   struct gl_texture_object *t = u->TexObj;
48601e04c3fSmrg   mesa_format tex_format;
487af69d88dSmrg
48801e04c3fSmrg   if (!t)
489af69d88dSmrg      return GL_FALSE;
490af69d88dSmrg
49101e04c3fSmrg   if (!t->_BaseComplete && !t->_MipmapComplete)
49201e04c3fSmrg       _mesa_test_texobj_completeness(ctx, t);
493af69d88dSmrg
49401e04c3fSmrg   if (u->Level < t->BaseLevel ||
49501e04c3fSmrg       u->Level > t->_MaxLevel ||
49601e04c3fSmrg       (u->Level == t->BaseLevel && !t->_BaseComplete) ||
497af69d88dSmrg       (u->Level != t->BaseLevel && !t->_MipmapComplete))
498af69d88dSmrg      return GL_FALSE;
499af69d88dSmrg
500af69d88dSmrg   if (_mesa_tex_target_is_layered(t->Target) &&
50101e04c3fSmrg       u->_Layer >= _mesa_get_texture_layers(t, u->Level))
502af69d88dSmrg      return GL_FALSE;
503af69d88dSmrg
50401e04c3fSmrg   if (t->Target == GL_TEXTURE_BUFFER) {
50501e04c3fSmrg      tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat);
50601e04c3fSmrg
50701e04c3fSmrg   } else {
50801e04c3fSmrg      struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ?
50901e04c3fSmrg                                      t->Image[u->_Layer][u->Level] :
51001e04c3fSmrg                                      t->Image[0][u->Level]);
51101e04c3fSmrg
51201e04c3fSmrg      if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples)
51301e04c3fSmrg         return GL_FALSE;
51401e04c3fSmrg
51501e04c3fSmrg      tex_format = _mesa_get_shader_image_format(img->InternalFormat);
51601e04c3fSmrg   }
517af69d88dSmrg
51801e04c3fSmrg   if (!tex_format)
519af69d88dSmrg      return GL_FALSE;
520af69d88dSmrg
521af69d88dSmrg   switch (t->ImageFormatCompatibilityType) {
522af69d88dSmrg   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE:
52301e04c3fSmrg      if (_mesa_get_format_bytes(tex_format) !=
524af69d88dSmrg          _mesa_get_format_bytes(u->_ActualFormat))
525af69d88dSmrg         return GL_FALSE;
526af69d88dSmrg      break;
527af69d88dSmrg
528af69d88dSmrg   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS:
52901e04c3fSmrg      if (get_image_format_class(tex_format) !=
530af69d88dSmrg          get_image_format_class(u->_ActualFormat))
531af69d88dSmrg         return GL_FALSE;
532af69d88dSmrg      break;
533af69d88dSmrg
534af69d88dSmrg   default:
535af69d88dSmrg      assert(!"Unexpected image format compatibility type");
536af69d88dSmrg   }
537af69d88dSmrg
538af69d88dSmrg   return GL_TRUE;
539af69d88dSmrg}
540af69d88dSmrg
541af69d88dSmrgstatic GLboolean
542af69d88dSmrgvalidate_bind_image_texture(struct gl_context *ctx, GLuint unit,
54301e04c3fSmrg                            GLuint texture, GLint level, GLint layer,
54401e04c3fSmrg                            GLenum access, GLenum format)
545af69d88dSmrg{
546af69d88dSmrg   assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS);
547af69d88dSmrg
548af69d88dSmrg   if (unit >= ctx->Const.MaxImageUnits) {
549af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)");
550af69d88dSmrg      return GL_FALSE;
551af69d88dSmrg   }
552af69d88dSmrg
553af69d88dSmrg   if (level < 0) {
554af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)");
555af69d88dSmrg      return GL_FALSE;
556af69d88dSmrg   }
557af69d88dSmrg
558af69d88dSmrg   if (layer < 0) {
559af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)");
560af69d88dSmrg      return GL_FALSE;
561af69d88dSmrg   }
562af69d88dSmrg
563af69d88dSmrg   if (access != GL_READ_ONLY &&
564af69d88dSmrg       access != GL_WRITE_ONLY &&
565af69d88dSmrg       access != GL_READ_WRITE) {
566af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)");
567af69d88dSmrg      return GL_FALSE;
568af69d88dSmrg   }
569af69d88dSmrg
57001e04c3fSmrg   if (!_mesa_is_shader_image_format_supported(ctx, format)) {
571af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
572af69d88dSmrg      return GL_FALSE;
573af69d88dSmrg   }
574af69d88dSmrg
575af69d88dSmrg   return GL_TRUE;
576af69d88dSmrg}
577af69d88dSmrg
57801e04c3fSmrgstatic void
57901e04c3fSmrgset_image_binding(struct gl_image_unit *u, struct gl_texture_object *texObj,
58001e04c3fSmrg                  GLint level, GLboolean layered, GLint layer, GLenum access,
58101e04c3fSmrg                  GLenum format)
582af69d88dSmrg{
58301e04c3fSmrg   u->Level = level;
58401e04c3fSmrg   u->Access = access;
58501e04c3fSmrg   u->Format = format;
58601e04c3fSmrg   u->_ActualFormat = _mesa_get_shader_image_format(format);
58701e04c3fSmrg
58801e04c3fSmrg   if (texObj && _mesa_tex_target_is_layered(texObj->Target)) {
58901e04c3fSmrg      u->Layered = layered;
59001e04c3fSmrg      u->Layer = layer;
59101e04c3fSmrg      u->_Layer = (u->Layered ? 0 : u->Layer);
59201e04c3fSmrg   } else {
59301e04c3fSmrg      u->Layered = GL_FALSE;
59401e04c3fSmrg      u->Layer = 0;
59501e04c3fSmrg   }
596af69d88dSmrg
59701e04c3fSmrg   _mesa_reference_texobj(&u->TexObj, texObj);
59801e04c3fSmrg}
59901e04c3fSmrg
60001e04c3fSmrgstatic void
60101e04c3fSmrgbind_image_texture(struct gl_context *ctx, struct gl_texture_object *texObj,
60201e04c3fSmrg                   GLuint unit, GLint level, GLboolean layered, GLint layer,
60301e04c3fSmrg                   GLenum access, GLenum format)
60401e04c3fSmrg{
60501e04c3fSmrg   struct gl_image_unit *u;
606af69d88dSmrg
607af69d88dSmrg   u = &ctx->ImageUnits[unit];
608af69d88dSmrg
609af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
610af69d88dSmrg   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
611af69d88dSmrg
61201e04c3fSmrg   set_image_binding(u, texObj, level, layered, layer, access, format);
61301e04c3fSmrg}
614af69d88dSmrg
61501e04c3fSmrgvoid GLAPIENTRY
61601e04c3fSmrg_mesa_BindImageTexture_no_error(GLuint unit, GLuint texture, GLint level,
61701e04c3fSmrg                                GLboolean layered, GLint layer, GLenum access,
61801e04c3fSmrg                                GLenum format)
61901e04c3fSmrg{
62001e04c3fSmrg   struct gl_texture_object *texObj = NULL;
621af69d88dSmrg
62201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
623af69d88dSmrg
62401e04c3fSmrg   if (texture)
62501e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, texture);
626af69d88dSmrg
62701e04c3fSmrg   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
628af69d88dSmrg}
629af69d88dSmrg
630af69d88dSmrgvoid GLAPIENTRY
63101e04c3fSmrg_mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
63201e04c3fSmrg                       GLboolean layered, GLint layer, GLenum access,
63301e04c3fSmrg                       GLenum format)
634af69d88dSmrg{
63501e04c3fSmrg   struct gl_texture_object *texObj = NULL;
63601e04c3fSmrg
637af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
638af69d88dSmrg
63901e04c3fSmrg   if (!validate_bind_image_texture(ctx, unit, texture, level, layer, access,
64001e04c3fSmrg                                    format))
641af69d88dSmrg      return;
642af69d88dSmrg
64301e04c3fSmrg   if (texture) {
64401e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, texture);
64501e04c3fSmrg
64601e04c3fSmrg      if (!texObj) {
64701e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)");
64801e04c3fSmrg         return;
64901e04c3fSmrg      }
65001e04c3fSmrg
65101e04c3fSmrg      /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES
65201e04c3fSmrg       * 3.1 spec:
653af69d88dSmrg       *
65401e04c3fSmrg       * "An INVALID_OPERATION error is generated if texture is not the name
65501e04c3fSmrg       *  of an immutable texture object."
65601e04c3fSmrg       *
65701e04c3fSmrg       * However note that issue 7 of the GL_OES_texture_buffer spec
65801e04c3fSmrg       * recognizes that there is no way to create immutable buffer textures,
65901e04c3fSmrg       * so those are excluded from this requirement.
660af69d88dSmrg       */
66101e04c3fSmrg      if (_mesa_is_gles(ctx) && !texObj->Immutable &&
66201e04c3fSmrg          texObj->Target != GL_TEXTURE_BUFFER) {
66301e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
66401e04c3fSmrg                     "glBindImageTexture(!immutable)");
66501e04c3fSmrg         return;
66601e04c3fSmrg      }
667af69d88dSmrg   }
668af69d88dSmrg
66901e04c3fSmrg   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
67001e04c3fSmrg}
67101e04c3fSmrg
67201e04c3fSmrgstatic ALWAYS_INLINE void
67301e04c3fSmrgbind_image_textures(struct gl_context *ctx, GLuint first, GLuint count,
67401e04c3fSmrg                    const GLuint *textures, bool no_error)
67501e04c3fSmrg{
67601e04c3fSmrg   int i;
67701e04c3fSmrg
678af69d88dSmrg   /* Assume that at least one binding will be changed */
679af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
680af69d88dSmrg   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
681af69d88dSmrg
682af69d88dSmrg   /* Note that the error semantics for multi-bind commands differ from
683af69d88dSmrg    * those of other GL commands.
684af69d88dSmrg    *
685af69d88dSmrg    * The Issues section in the ARB_multi_bind spec says:
686af69d88dSmrg    *
687af69d88dSmrg    *    "(11) Typically, OpenGL specifies that if an error is generated by
688af69d88dSmrg    *          a command, that command has no effect.  This is somewhat
689af69d88dSmrg    *          unfortunate for multi-bind commands, because it would require
690af69d88dSmrg    *          a first pass to scan the entire list of bound objects for
691af69d88dSmrg    *          errors and then a second pass to actually perform the
692af69d88dSmrg    *          bindings.  Should we have different error semantics?
693af69d88dSmrg    *
694af69d88dSmrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
695af69d88dSmrg    *       one of the <count> binding points are invalid, that binding
696af69d88dSmrg    *       point is not updated and an error will be generated.  However,
697af69d88dSmrg    *       other binding points in the same command will be updated if
698af69d88dSmrg    *       their parameters are valid and no other error occurs."
699af69d88dSmrg    */
700af69d88dSmrg
70101e04c3fSmrg   _mesa_HashLockMutex(ctx->Shared->TexObjects);
702af69d88dSmrg
703af69d88dSmrg   for (i = 0; i < count; i++) {
704af69d88dSmrg      struct gl_image_unit *u = &ctx->ImageUnits[first + i];
705af69d88dSmrg      const GLuint texture = textures ? textures[i] : 0;
706af69d88dSmrg
70701e04c3fSmrg      if (texture) {
70801e04c3fSmrg         struct gl_texture_object *texObj = u->TexObj;
70901e04c3fSmrg         GLenum tex_format;
710af69d88dSmrg
71101e04c3fSmrg         if (!texObj || texObj->Name != texture) {
712af69d88dSmrg            texObj = _mesa_lookup_texture_locked(ctx, texture);
71301e04c3fSmrg            if (!no_error && !texObj) {
714af69d88dSmrg               /* The ARB_multi_bind spec says:
715af69d88dSmrg                *
716af69d88dSmrg                *    "An INVALID_OPERATION error is generated if any value
717af69d88dSmrg                *     in <textures> is not zero or the name of an existing
718af69d88dSmrg                *     texture object (per binding)."
719af69d88dSmrg                */
720af69d88dSmrg               _mesa_error(ctx, GL_INVALID_OPERATION,
721af69d88dSmrg                           "glBindImageTextures(textures[%d]=%u "
722af69d88dSmrg                           "is not zero or the name of an existing texture "
723af69d88dSmrg                           "object)", i, texture);
724af69d88dSmrg               continue;
725af69d88dSmrg            }
726af69d88dSmrg         }
727af69d88dSmrg
72801e04c3fSmrg         if (texObj->Target == GL_TEXTURE_BUFFER) {
72901e04c3fSmrg            tex_format = texObj->BufferObjectFormat;
73001e04c3fSmrg         } else {
73101e04c3fSmrg            struct gl_texture_image *image = texObj->Image[0][0];
732af69d88dSmrg
73301e04c3fSmrg            if (!no_error && (!image || image->Width == 0 ||
73401e04c3fSmrg                              image->Height == 0 || image->Depth == 0)) {
73501e04c3fSmrg               /* The ARB_multi_bind spec says:
73601e04c3fSmrg                *
73701e04c3fSmrg                *    "An INVALID_OPERATION error is generated if the width,
73801e04c3fSmrg                *     height, or depth of the level zero texture image of
73901e04c3fSmrg                *     any texture in <textures> is zero (per binding)."
74001e04c3fSmrg                */
74101e04c3fSmrg               _mesa_error(ctx, GL_INVALID_OPERATION,
74201e04c3fSmrg                           "glBindImageTextures(the width, height or depth "
74301e04c3fSmrg                           "of the level zero texture image of "
74401e04c3fSmrg                           "textures[%d]=%u is zero)", i, texture);
74501e04c3fSmrg               continue;
74601e04c3fSmrg            }
747af69d88dSmrg
74801e04c3fSmrg            tex_format = image->InternalFormat;
74901e04c3fSmrg         }
750af69d88dSmrg
75101e04c3fSmrg         if (!no_error &&
75201e04c3fSmrg             !_mesa_is_shader_image_format_supported(ctx, tex_format)) {
753af69d88dSmrg            /* The ARB_multi_bind spec says:
754af69d88dSmrg             *
755af69d88dSmrg             *   "An INVALID_OPERATION error is generated if the internal
756af69d88dSmrg             *    format of the level zero texture image of any texture
757af69d88dSmrg             *    in <textures> is not found in table 8.33 (per binding)."
758af69d88dSmrg             */
759af69d88dSmrg            _mesa_error(ctx, GL_INVALID_OPERATION,
760af69d88dSmrg                        "glBindImageTextures(the internal format %s of "
761af69d88dSmrg                        "the level zero texture image of textures[%d]=%u "
762af69d88dSmrg                        "is not supported)",
76301e04c3fSmrg                        _mesa_enum_to_string(tex_format),
764af69d88dSmrg                        i, texture);
765af69d88dSmrg            continue;
766af69d88dSmrg         }
767af69d88dSmrg
768af69d88dSmrg         /* Update the texture binding */
76901e04c3fSmrg         set_image_binding(u, texObj, 0,
77001e04c3fSmrg                           _mesa_tex_target_is_layered(texObj->Target),
77101e04c3fSmrg                           0, GL_READ_WRITE, tex_format);
772af69d88dSmrg      } else {
773af69d88dSmrg         /* Unbind the texture from the unit */
77401e04c3fSmrg         set_image_binding(u, NULL, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
775af69d88dSmrg      }
776af69d88dSmrg   }
777af69d88dSmrg
77801e04c3fSmrg   _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
77901e04c3fSmrg}
78001e04c3fSmrg
78101e04c3fSmrgvoid GLAPIENTRY
78201e04c3fSmrg_mesa_BindImageTextures_no_error(GLuint first, GLsizei count,
78301e04c3fSmrg                                 const GLuint *textures)
78401e04c3fSmrg{
78501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
78601e04c3fSmrg
78701e04c3fSmrg   bind_image_textures(ctx, first, count, textures, true);
788af69d88dSmrg}
789af69d88dSmrg
790af69d88dSmrgvoid GLAPIENTRY
79101e04c3fSmrg_mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
792af69d88dSmrg{
793af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
794af69d88dSmrg
79501e04c3fSmrg   if (!ctx->Extensions.ARB_shader_image_load_store) {
79601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()");
79701e04c3fSmrg      return;
79801e04c3fSmrg   }
79901e04c3fSmrg
80001e04c3fSmrg   if (first + count > ctx->Const.MaxImageUnits) {
80101e04c3fSmrg      /* The ARB_multi_bind spec says:
80201e04c3fSmrg       *
80301e04c3fSmrg       *    "An INVALID_OPERATION error is generated if <first> + <count>
80401e04c3fSmrg       *     is greater than the number of image units supported by
80501e04c3fSmrg       *     the implementation."
80601e04c3fSmrg       */
80701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
80801e04c3fSmrg                  "glBindImageTextures(first=%u + count=%d > the value of "
80901e04c3fSmrg                  "GL_MAX_IMAGE_UNITS=%u)",
81001e04c3fSmrg                  first, count, ctx->Const.MaxImageUnits);
81101e04c3fSmrg      return;
81201e04c3fSmrg   }
81301e04c3fSmrg
81401e04c3fSmrg   bind_image_textures(ctx, first, count, textures, false);
815af69d88dSmrg}
816