shaderimage.c revision 7ec681f3
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
3901e04c3fSmrgmesa_format
4001e04c3fSmrg_mesa_get_shader_image_format(GLenum format)
41af69d88dSmrg{
42af69d88dSmrg   switch (format) {
43af69d88dSmrg   case GL_RGBA32F:
44af69d88dSmrg      return MESA_FORMAT_RGBA_FLOAT32;
45af69d88dSmrg
46af69d88dSmrg   case GL_RGBA16F:
47af69d88dSmrg      return MESA_FORMAT_RGBA_FLOAT16;
48af69d88dSmrg
49af69d88dSmrg   case GL_RG32F:
50af69d88dSmrg      return MESA_FORMAT_RG_FLOAT32;
51af69d88dSmrg
52af69d88dSmrg   case GL_RG16F:
53af69d88dSmrg      return MESA_FORMAT_RG_FLOAT16;
54af69d88dSmrg
55af69d88dSmrg   case GL_R11F_G11F_B10F:
56af69d88dSmrg      return MESA_FORMAT_R11G11B10_FLOAT;
57af69d88dSmrg
58af69d88dSmrg   case GL_R32F:
59af69d88dSmrg      return MESA_FORMAT_R_FLOAT32;
60af69d88dSmrg
61af69d88dSmrg   case GL_R16F:
62af69d88dSmrg      return MESA_FORMAT_R_FLOAT16;
63af69d88dSmrg
64af69d88dSmrg   case GL_RGBA32UI:
65af69d88dSmrg      return MESA_FORMAT_RGBA_UINT32;
66af69d88dSmrg
67af69d88dSmrg   case GL_RGBA16UI:
68af69d88dSmrg      return MESA_FORMAT_RGBA_UINT16;
69af69d88dSmrg
70af69d88dSmrg   case GL_RGB10_A2UI:
71af69d88dSmrg      return MESA_FORMAT_R10G10B10A2_UINT;
72af69d88dSmrg
73af69d88dSmrg   case GL_RGBA8UI:
74af69d88dSmrg      return MESA_FORMAT_RGBA_UINT8;
75af69d88dSmrg
76af69d88dSmrg   case GL_RG32UI:
77af69d88dSmrg      return MESA_FORMAT_RG_UINT32;
78af69d88dSmrg
79af69d88dSmrg   case GL_RG16UI:
80af69d88dSmrg      return MESA_FORMAT_RG_UINT16;
81af69d88dSmrg
82af69d88dSmrg   case GL_RG8UI:
83af69d88dSmrg      return MESA_FORMAT_RG_UINT8;
84af69d88dSmrg
85af69d88dSmrg   case GL_R32UI:
86af69d88dSmrg      return MESA_FORMAT_R_UINT32;
87af69d88dSmrg
88af69d88dSmrg   case GL_R16UI:
89af69d88dSmrg      return MESA_FORMAT_R_UINT16;
90af69d88dSmrg
91af69d88dSmrg   case GL_R8UI:
92af69d88dSmrg      return MESA_FORMAT_R_UINT8;
93af69d88dSmrg
94af69d88dSmrg   case GL_RGBA32I:
95af69d88dSmrg      return MESA_FORMAT_RGBA_SINT32;
96af69d88dSmrg
97af69d88dSmrg   case GL_RGBA16I:
98af69d88dSmrg      return MESA_FORMAT_RGBA_SINT16;
99af69d88dSmrg
100af69d88dSmrg   case GL_RGBA8I:
101af69d88dSmrg      return MESA_FORMAT_RGBA_SINT8;
102af69d88dSmrg
103af69d88dSmrg   case GL_RG32I:
104af69d88dSmrg      return MESA_FORMAT_RG_SINT32;
105af69d88dSmrg
106af69d88dSmrg   case GL_RG16I:
107af69d88dSmrg      return MESA_FORMAT_RG_SINT16;
108af69d88dSmrg
109af69d88dSmrg   case GL_RG8I:
110af69d88dSmrg      return MESA_FORMAT_RG_SINT8;
111af69d88dSmrg
112af69d88dSmrg   case GL_R32I:
113af69d88dSmrg      return MESA_FORMAT_R_SINT32;
114af69d88dSmrg
115af69d88dSmrg   case GL_R16I:
116af69d88dSmrg      return MESA_FORMAT_R_SINT16;
117af69d88dSmrg
118af69d88dSmrg   case GL_R8I:
119af69d88dSmrg      return MESA_FORMAT_R_SINT8;
120af69d88dSmrg
121af69d88dSmrg   case GL_RGBA16:
122af69d88dSmrg      return MESA_FORMAT_RGBA_UNORM16;
123af69d88dSmrg
124af69d88dSmrg   case GL_RGB10_A2:
125af69d88dSmrg      return MESA_FORMAT_R10G10B10A2_UNORM;
126af69d88dSmrg
127af69d88dSmrg   case GL_RGBA8:
1287ec681f3Smrg      return MESA_FORMAT_RGBA_UNORM8;
129af69d88dSmrg
130af69d88dSmrg   case GL_RG16:
1317ec681f3Smrg      return MESA_FORMAT_RG_UNORM16;
132af69d88dSmrg
133af69d88dSmrg   case GL_RG8:
1347ec681f3Smrg      return MESA_FORMAT_RG_UNORM8;
135af69d88dSmrg
136af69d88dSmrg   case GL_R16:
137af69d88dSmrg      return MESA_FORMAT_R_UNORM16;
138af69d88dSmrg
139af69d88dSmrg   case GL_R8:
140af69d88dSmrg      return MESA_FORMAT_R_UNORM8;
141af69d88dSmrg
142af69d88dSmrg   case GL_RGBA16_SNORM:
143af69d88dSmrg      return MESA_FORMAT_RGBA_SNORM16;
144af69d88dSmrg
145af69d88dSmrg   case GL_RGBA8_SNORM:
1467ec681f3Smrg      return MESA_FORMAT_RGBA_SNORM8;
147af69d88dSmrg
148af69d88dSmrg   case GL_RG16_SNORM:
1497ec681f3Smrg      return MESA_FORMAT_RG_SNORM16;
150af69d88dSmrg
151af69d88dSmrg   case GL_RG8_SNORM:
1527ec681f3Smrg      return MESA_FORMAT_RG_SNORM8;
153af69d88dSmrg
154af69d88dSmrg   case GL_R16_SNORM:
155af69d88dSmrg      return MESA_FORMAT_R_SNORM16;
156af69d88dSmrg
157af69d88dSmrg   case GL_R8_SNORM:
158af69d88dSmrg      return MESA_FORMAT_R_SNORM8;
159af69d88dSmrg
160af69d88dSmrg   default:
161af69d88dSmrg      return MESA_FORMAT_NONE;
162af69d88dSmrg   }
163af69d88dSmrg}
164af69d88dSmrg
165af69d88dSmrgenum image_format_class
166af69d88dSmrg{
167af69d88dSmrg   /** Not a valid image format. */
168af69d88dSmrg   IMAGE_FORMAT_CLASS_NONE = 0,
169af69d88dSmrg
170af69d88dSmrg   /** Classes of image formats you can cast into each other. */
171af69d88dSmrg   /** \{ */
172af69d88dSmrg   IMAGE_FORMAT_CLASS_1X8,
173af69d88dSmrg   IMAGE_FORMAT_CLASS_1X16,
174af69d88dSmrg   IMAGE_FORMAT_CLASS_1X32,
175af69d88dSmrg   IMAGE_FORMAT_CLASS_2X8,
176af69d88dSmrg   IMAGE_FORMAT_CLASS_2X16,
177af69d88dSmrg   IMAGE_FORMAT_CLASS_2X32,
178af69d88dSmrg   IMAGE_FORMAT_CLASS_10_11_11,
179af69d88dSmrg   IMAGE_FORMAT_CLASS_4X8,
180af69d88dSmrg   IMAGE_FORMAT_CLASS_4X16,
181af69d88dSmrg   IMAGE_FORMAT_CLASS_4X32,
182af69d88dSmrg   IMAGE_FORMAT_CLASS_2_10_10_10
183af69d88dSmrg   /** \} */
184af69d88dSmrg};
185af69d88dSmrg
186af69d88dSmrgstatic enum image_format_class
187af69d88dSmrgget_image_format_class(mesa_format format)
188af69d88dSmrg{
189af69d88dSmrg   switch (format) {
190af69d88dSmrg   case MESA_FORMAT_RGBA_FLOAT32:
191af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X32;
192af69d88dSmrg
193af69d88dSmrg   case MESA_FORMAT_RGBA_FLOAT16:
194af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
195af69d88dSmrg
196af69d88dSmrg   case MESA_FORMAT_RG_FLOAT32:
197af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X32;
198af69d88dSmrg
199af69d88dSmrg   case MESA_FORMAT_RG_FLOAT16:
200af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
201af69d88dSmrg
202af69d88dSmrg   case MESA_FORMAT_R11G11B10_FLOAT:
203af69d88dSmrg      return IMAGE_FORMAT_CLASS_10_11_11;
204af69d88dSmrg
205af69d88dSmrg   case MESA_FORMAT_R_FLOAT32:
206af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X32;
207af69d88dSmrg
208af69d88dSmrg   case MESA_FORMAT_R_FLOAT16:
209af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
210af69d88dSmrg
211af69d88dSmrg   case MESA_FORMAT_RGBA_UINT32:
212af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X32;
213af69d88dSmrg
214af69d88dSmrg   case MESA_FORMAT_RGBA_UINT16:
215af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
216af69d88dSmrg
217af69d88dSmrg   case MESA_FORMAT_R10G10B10A2_UINT:
218af69d88dSmrg      return IMAGE_FORMAT_CLASS_2_10_10_10;
219af69d88dSmrg
220af69d88dSmrg   case MESA_FORMAT_RGBA_UINT8:
221af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
222af69d88dSmrg
223af69d88dSmrg   case MESA_FORMAT_RG_UINT32:
224af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X32;
225af69d88dSmrg
226af69d88dSmrg   case MESA_FORMAT_RG_UINT16:
227af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
228af69d88dSmrg
229af69d88dSmrg   case MESA_FORMAT_RG_UINT8:
230af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
231af69d88dSmrg
232af69d88dSmrg   case MESA_FORMAT_R_UINT32:
233af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X32;
234af69d88dSmrg
235af69d88dSmrg   case MESA_FORMAT_R_UINT16:
236af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
237af69d88dSmrg
238af69d88dSmrg   case MESA_FORMAT_R_UINT8:
239af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
240af69d88dSmrg
241af69d88dSmrg   case MESA_FORMAT_RGBA_SINT32:
242af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X32;
243af69d88dSmrg
244af69d88dSmrg   case MESA_FORMAT_RGBA_SINT16:
245af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
246af69d88dSmrg
247af69d88dSmrg   case MESA_FORMAT_RGBA_SINT8:
248af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
249af69d88dSmrg
250af69d88dSmrg   case MESA_FORMAT_RG_SINT32:
251af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X32;
252af69d88dSmrg
253af69d88dSmrg   case MESA_FORMAT_RG_SINT16:
254af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
255af69d88dSmrg
256af69d88dSmrg   case MESA_FORMAT_RG_SINT8:
257af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
258af69d88dSmrg
259af69d88dSmrg   case MESA_FORMAT_R_SINT32:
260af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X32;
261af69d88dSmrg
262af69d88dSmrg   case MESA_FORMAT_R_SINT16:
263af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
264af69d88dSmrg
265af69d88dSmrg   case MESA_FORMAT_R_SINT8:
266af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
267af69d88dSmrg
268af69d88dSmrg   case MESA_FORMAT_RGBA_UNORM16:
269af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
270af69d88dSmrg
271af69d88dSmrg   case MESA_FORMAT_R10G10B10A2_UNORM:
272af69d88dSmrg      return IMAGE_FORMAT_CLASS_2_10_10_10;
273af69d88dSmrg
2747ec681f3Smrg   case MESA_FORMAT_RGBA_UNORM8:
275af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
276af69d88dSmrg
2777ec681f3Smrg   case MESA_FORMAT_RG_UNORM16:
278af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
279af69d88dSmrg
2807ec681f3Smrg   case MESA_FORMAT_RG_UNORM8:
281af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
282af69d88dSmrg
283af69d88dSmrg   case MESA_FORMAT_R_UNORM16:
284af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
285af69d88dSmrg
286af69d88dSmrg   case MESA_FORMAT_R_UNORM8:
287af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
288af69d88dSmrg
289af69d88dSmrg   case MESA_FORMAT_RGBA_SNORM16:
290af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X16;
291af69d88dSmrg
2927ec681f3Smrg   case MESA_FORMAT_RGBA_SNORM8:
293af69d88dSmrg      return IMAGE_FORMAT_CLASS_4X8;
294af69d88dSmrg
2957ec681f3Smrg   case MESA_FORMAT_RG_SNORM16:
296af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X16;
297af69d88dSmrg
2987ec681f3Smrg   case MESA_FORMAT_RG_SNORM8:
299af69d88dSmrg      return IMAGE_FORMAT_CLASS_2X8;
300af69d88dSmrg
301af69d88dSmrg   case MESA_FORMAT_R_SNORM16:
302af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X16;
303af69d88dSmrg
304af69d88dSmrg   case MESA_FORMAT_R_SNORM8:
305af69d88dSmrg      return IMAGE_FORMAT_CLASS_1X8;
306af69d88dSmrg
307af69d88dSmrg   default:
308af69d88dSmrg      return IMAGE_FORMAT_CLASS_NONE;
309af69d88dSmrg   }
310af69d88dSmrg}
311af69d88dSmrg
31201e04c3fSmrgstatic GLenum
31301e04c3fSmrg_image_format_class_to_glenum(enum image_format_class class)
31401e04c3fSmrg{
31501e04c3fSmrg   switch (class) {
31601e04c3fSmrg   case IMAGE_FORMAT_CLASS_NONE:
31701e04c3fSmrg      return GL_NONE;
31801e04c3fSmrg   case IMAGE_FORMAT_CLASS_1X8:
31901e04c3fSmrg      return GL_IMAGE_CLASS_1_X_8;
32001e04c3fSmrg   case IMAGE_FORMAT_CLASS_1X16:
32101e04c3fSmrg      return GL_IMAGE_CLASS_1_X_16;
32201e04c3fSmrg   case IMAGE_FORMAT_CLASS_1X32:
32301e04c3fSmrg      return GL_IMAGE_CLASS_1_X_32;
32401e04c3fSmrg   case IMAGE_FORMAT_CLASS_2X8:
32501e04c3fSmrg      return GL_IMAGE_CLASS_2_X_8;
32601e04c3fSmrg   case IMAGE_FORMAT_CLASS_2X16:
32701e04c3fSmrg      return GL_IMAGE_CLASS_2_X_16;
32801e04c3fSmrg   case IMAGE_FORMAT_CLASS_2X32:
32901e04c3fSmrg      return GL_IMAGE_CLASS_2_X_32;
33001e04c3fSmrg   case IMAGE_FORMAT_CLASS_10_11_11:
33101e04c3fSmrg      return GL_IMAGE_CLASS_11_11_10;
33201e04c3fSmrg   case IMAGE_FORMAT_CLASS_4X8:
33301e04c3fSmrg      return GL_IMAGE_CLASS_4_X_8;
33401e04c3fSmrg   case IMAGE_FORMAT_CLASS_4X16:
33501e04c3fSmrg      return GL_IMAGE_CLASS_4_X_16;
33601e04c3fSmrg   case IMAGE_FORMAT_CLASS_4X32:
33701e04c3fSmrg      return GL_IMAGE_CLASS_4_X_32;
33801e04c3fSmrg   case IMAGE_FORMAT_CLASS_2_10_10_10:
33901e04c3fSmrg      return GL_IMAGE_CLASS_10_10_10_2;
34001e04c3fSmrg   default:
34101e04c3fSmrg      assert(!"Invalid image_format_class");
34201e04c3fSmrg      return GL_NONE;
34301e04c3fSmrg   }
34401e04c3fSmrg}
34501e04c3fSmrg
34601e04c3fSmrgGLenum
34701e04c3fSmrg_mesa_get_image_format_class(GLenum format)
34801e04c3fSmrg{
34901e04c3fSmrg   mesa_format tex_format = _mesa_get_shader_image_format(format);
35001e04c3fSmrg   if (tex_format == MESA_FORMAT_NONE)
35101e04c3fSmrg      return GL_NONE;
35201e04c3fSmrg
35301e04c3fSmrg   enum image_format_class class = get_image_format_class(tex_format);
35401e04c3fSmrg   return _image_format_class_to_glenum(class);
35501e04c3fSmrg}
35601e04c3fSmrg
35701e04c3fSmrgbool
35801e04c3fSmrg_mesa_is_shader_image_format_supported(const struct gl_context *ctx,
35901e04c3fSmrg                                       GLenum format)
36001e04c3fSmrg{
36101e04c3fSmrg   switch (format) {
36201e04c3fSmrg   /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the
36301e04c3fSmrg    * OpenGL ES 3.1 specification.
36401e04c3fSmrg    */
36501e04c3fSmrg   case GL_RGBA32F:
36601e04c3fSmrg   case GL_RGBA16F:
36701e04c3fSmrg   case GL_R32F:
36801e04c3fSmrg   case GL_RGBA32UI:
36901e04c3fSmrg   case GL_RGBA16UI:
37001e04c3fSmrg   case GL_RGBA8UI:
37101e04c3fSmrg   case GL_R32UI:
37201e04c3fSmrg   case GL_RGBA32I:
37301e04c3fSmrg   case GL_RGBA16I:
37401e04c3fSmrg   case GL_RGBA8I:
37501e04c3fSmrg   case GL_R32I:
37601e04c3fSmrg   case GL_RGBA8:
37701e04c3fSmrg   case GL_RGBA8_SNORM:
37801e04c3fSmrg      return true;
37901e04c3fSmrg
38001e04c3fSmrg   /* Formats supported on unextended desktop GL and the original
38101e04c3fSmrg    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
38201e04c3fSmrg    * specification or by GLES 3.1 with GL_NV_image_formats extension.
38301e04c3fSmrg    */
38401e04c3fSmrg   case GL_RG32F:
38501e04c3fSmrg   case GL_RG16F:
38601e04c3fSmrg   case GL_R11F_G11F_B10F:
38701e04c3fSmrg   case GL_R16F:
38801e04c3fSmrg   case GL_RGB10_A2UI:
38901e04c3fSmrg   case GL_RG32UI:
39001e04c3fSmrg   case GL_RG16UI:
39101e04c3fSmrg   case GL_RG8UI:
39201e04c3fSmrg   case GL_R16UI:
39301e04c3fSmrg   case GL_R8UI:
39401e04c3fSmrg   case GL_RG32I:
39501e04c3fSmrg   case GL_RG16I:
39601e04c3fSmrg   case GL_RG8I:
39701e04c3fSmrg   case GL_R16I:
39801e04c3fSmrg   case GL_R8I:
39901e04c3fSmrg   case GL_RGB10_A2:
40001e04c3fSmrg   case GL_RG8:
40101e04c3fSmrg   case GL_R8:
40201e04c3fSmrg   case GL_RG8_SNORM:
40301e04c3fSmrg   case GL_R8_SNORM:
40401e04c3fSmrg      return true;
40501e04c3fSmrg
40601e04c3fSmrg   /* Formats supported on unextended desktop GL and the original
40701e04c3fSmrg    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
40801e04c3fSmrg    * specification.
40901e04c3fSmrg    *
41001e04c3fSmrg    * Following formats are supported by GLES 3.1 with GL_NV_image_formats &
41101e04c3fSmrg    * GL_EXT_texture_norm16 extensions.
41201e04c3fSmrg    */
41301e04c3fSmrg   case GL_RGBA16:
41401e04c3fSmrg   case GL_RGBA16_SNORM:
41501e04c3fSmrg   case GL_RG16:
41601e04c3fSmrg   case GL_RG16_SNORM:
41701e04c3fSmrg   case GL_R16:
41801e04c3fSmrg   case GL_R16_SNORM:
41901e04c3fSmrg      return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx);
42001e04c3fSmrg
42101e04c3fSmrg   default:
42201e04c3fSmrg      return false;
42301e04c3fSmrg   }
42401e04c3fSmrg}
42501e04c3fSmrg
42601e04c3fSmrgstruct gl_image_unit
42701e04c3fSmrg_mesa_default_image_unit(struct gl_context *ctx)
42801e04c3fSmrg{
42901e04c3fSmrg   const GLenum format = _mesa_is_desktop_gl(ctx) ? GL_R8 : GL_R32UI;
43001e04c3fSmrg   const struct gl_image_unit u = {
43101e04c3fSmrg      .Access = GL_READ_ONLY,
43201e04c3fSmrg      .Format = format,
43301e04c3fSmrg      ._ActualFormat = _mesa_get_shader_image_format(format)
43401e04c3fSmrg   };
43501e04c3fSmrg   return u;
43601e04c3fSmrg}
43701e04c3fSmrg
43801e04c3fSmrgvoid
43901e04c3fSmrg_mesa_init_image_units(struct gl_context *ctx)
44001e04c3fSmrg{
44101e04c3fSmrg   unsigned i;
44201e04c3fSmrg
44301e04c3fSmrg   ASSERT_BITFIELD_SIZE(struct gl_image_unit, Format, MESA_FORMAT_COUNT);
44401e04c3fSmrg
44501e04c3fSmrg   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
44601e04c3fSmrg      ctx->ImageUnits[i] = _mesa_default_image_unit(ctx);
44701e04c3fSmrg}
44801e04c3fSmrg
449b9abf16eSmaya
450b9abf16eSmayavoid
451b9abf16eSmaya_mesa_free_image_textures(struct gl_context *ctx)
452b9abf16eSmaya{
453b9abf16eSmaya   unsigned i;
454b9abf16eSmaya
455b9abf16eSmaya   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
456b9abf16eSmaya      _mesa_reference_texobj(&ctx->ImageUnits[i].TexObj, NULL);
457b9abf16eSmaya}
458b9abf16eSmaya
45901e04c3fSmrgGLboolean
46001e04c3fSmrg_mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u)
461af69d88dSmrg{
462af69d88dSmrg   struct gl_texture_object *t = u->TexObj;
46301e04c3fSmrg   mesa_format tex_format;
464af69d88dSmrg
46501e04c3fSmrg   if (!t)
466af69d88dSmrg      return GL_FALSE;
467af69d88dSmrg
46801e04c3fSmrg   if (!t->_BaseComplete && !t->_MipmapComplete)
46901e04c3fSmrg       _mesa_test_texobj_completeness(ctx, t);
470af69d88dSmrg
4717ec681f3Smrg   if (u->Level < t->Attrib.BaseLevel ||
47201e04c3fSmrg       u->Level > t->_MaxLevel ||
4737ec681f3Smrg       (u->Level == t->Attrib.BaseLevel && !t->_BaseComplete) ||
4747ec681f3Smrg       (u->Level != t->Attrib.BaseLevel && !t->_MipmapComplete))
475af69d88dSmrg      return GL_FALSE;
476af69d88dSmrg
477af69d88dSmrg   if (_mesa_tex_target_is_layered(t->Target) &&
47801e04c3fSmrg       u->_Layer >= _mesa_get_texture_layers(t, u->Level))
479af69d88dSmrg      return GL_FALSE;
480af69d88dSmrg
48101e04c3fSmrg   if (t->Target == GL_TEXTURE_BUFFER) {
48201e04c3fSmrg      tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat);
48301e04c3fSmrg
48401e04c3fSmrg   } else {
48501e04c3fSmrg      struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ?
48601e04c3fSmrg                                      t->Image[u->_Layer][u->Level] :
48701e04c3fSmrg                                      t->Image[0][u->Level]);
48801e04c3fSmrg
48901e04c3fSmrg      if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples)
49001e04c3fSmrg         return GL_FALSE;
49101e04c3fSmrg
49201e04c3fSmrg      tex_format = _mesa_get_shader_image_format(img->InternalFormat);
49301e04c3fSmrg   }
494af69d88dSmrg
49501e04c3fSmrg   if (!tex_format)
496af69d88dSmrg      return GL_FALSE;
497af69d88dSmrg
4987ec681f3Smrg   switch (t->Attrib.ImageFormatCompatibilityType) {
499af69d88dSmrg   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE:
50001e04c3fSmrg      if (_mesa_get_format_bytes(tex_format) !=
501af69d88dSmrg          _mesa_get_format_bytes(u->_ActualFormat))
502af69d88dSmrg         return GL_FALSE;
503af69d88dSmrg      break;
504af69d88dSmrg
505af69d88dSmrg   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS:
50601e04c3fSmrg      if (get_image_format_class(tex_format) !=
507af69d88dSmrg          get_image_format_class(u->_ActualFormat))
508af69d88dSmrg         return GL_FALSE;
509af69d88dSmrg      break;
510af69d88dSmrg
511af69d88dSmrg   default:
512af69d88dSmrg      assert(!"Unexpected image format compatibility type");
513af69d88dSmrg   }
514af69d88dSmrg
515af69d88dSmrg   return GL_TRUE;
516af69d88dSmrg}
517af69d88dSmrg
518af69d88dSmrgstatic GLboolean
519af69d88dSmrgvalidate_bind_image_texture(struct gl_context *ctx, GLuint unit,
52001e04c3fSmrg                            GLuint texture, GLint level, GLint layer,
5217ec681f3Smrg                            GLenum access, GLenum format, bool check_level_layer)
522af69d88dSmrg{
523af69d88dSmrg   assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS);
524af69d88dSmrg
525af69d88dSmrg   if (unit >= ctx->Const.MaxImageUnits) {
526af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)");
527af69d88dSmrg      return GL_FALSE;
528af69d88dSmrg   }
529af69d88dSmrg
5307ec681f3Smrg   if (check_level_layer) {
5317ec681f3Smrg      /* EXT_shader_image_load_store doesn't throw an error if level or
5327ec681f3Smrg       * layer is negative.
5337ec681f3Smrg       */
5347ec681f3Smrg      if (level < 0) {
5357ec681f3Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)");
5367ec681f3Smrg         return GL_FALSE;
5377ec681f3Smrg      }
538af69d88dSmrg
5397ec681f3Smrg         if (layer < 0) {
5407ec681f3Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)");
5417ec681f3Smrg            return GL_FALSE;
5427ec681f3Smrg      }
543af69d88dSmrg   }
544af69d88dSmrg
545af69d88dSmrg   if (access != GL_READ_ONLY &&
546af69d88dSmrg       access != GL_WRITE_ONLY &&
547af69d88dSmrg       access != GL_READ_WRITE) {
548af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)");
549af69d88dSmrg      return GL_FALSE;
550af69d88dSmrg   }
551af69d88dSmrg
55201e04c3fSmrg   if (!_mesa_is_shader_image_format_supported(ctx, format)) {
553af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
554af69d88dSmrg      return GL_FALSE;
555af69d88dSmrg   }
556af69d88dSmrg
557af69d88dSmrg   return GL_TRUE;
558af69d88dSmrg}
559af69d88dSmrg
56001e04c3fSmrgstatic void
56101e04c3fSmrgset_image_binding(struct gl_image_unit *u, struct gl_texture_object *texObj,
56201e04c3fSmrg                  GLint level, GLboolean layered, GLint layer, GLenum access,
56301e04c3fSmrg                  GLenum format)
564af69d88dSmrg{
56501e04c3fSmrg   u->Level = level;
56601e04c3fSmrg   u->Access = access;
56701e04c3fSmrg   u->Format = format;
56801e04c3fSmrg   u->_ActualFormat = _mesa_get_shader_image_format(format);
56901e04c3fSmrg
57001e04c3fSmrg   if (texObj && _mesa_tex_target_is_layered(texObj->Target)) {
57101e04c3fSmrg      u->Layered = layered;
57201e04c3fSmrg      u->Layer = layer;
57301e04c3fSmrg   } else {
57401e04c3fSmrg      u->Layered = GL_FALSE;
57501e04c3fSmrg      u->Layer = 0;
57601e04c3fSmrg   }
5777ec681f3Smrg   u->_Layer = (u->Layered ? 0 : u->Layer);
578af69d88dSmrg
57901e04c3fSmrg   _mesa_reference_texobj(&u->TexObj, texObj);
58001e04c3fSmrg}
58101e04c3fSmrg
58201e04c3fSmrgstatic void
58301e04c3fSmrgbind_image_texture(struct gl_context *ctx, struct gl_texture_object *texObj,
58401e04c3fSmrg                   GLuint unit, GLint level, GLboolean layered, GLint layer,
58501e04c3fSmrg                   GLenum access, GLenum format)
58601e04c3fSmrg{
58701e04c3fSmrg   struct gl_image_unit *u;
588af69d88dSmrg
589af69d88dSmrg   u = &ctx->ImageUnits[unit];
590af69d88dSmrg
5917ec681f3Smrg   FLUSH_VERTICES(ctx, 0, 0);
592af69d88dSmrg   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
593af69d88dSmrg
59401e04c3fSmrg   set_image_binding(u, texObj, level, layered, layer, access, format);
59501e04c3fSmrg}
596af69d88dSmrg
59701e04c3fSmrgvoid GLAPIENTRY
59801e04c3fSmrg_mesa_BindImageTexture_no_error(GLuint unit, GLuint texture, GLint level,
59901e04c3fSmrg                                GLboolean layered, GLint layer, GLenum access,
60001e04c3fSmrg                                GLenum format)
60101e04c3fSmrg{
60201e04c3fSmrg   struct gl_texture_object *texObj = NULL;
603af69d88dSmrg
60401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
605af69d88dSmrg
60601e04c3fSmrg   if (texture)
60701e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, texture);
608af69d88dSmrg
60901e04c3fSmrg   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
610af69d88dSmrg}
611af69d88dSmrg
612af69d88dSmrgvoid GLAPIENTRY
61301e04c3fSmrg_mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
61401e04c3fSmrg                       GLboolean layered, GLint layer, GLenum access,
61501e04c3fSmrg                       GLenum format)
616af69d88dSmrg{
61701e04c3fSmrg   struct gl_texture_object *texObj = NULL;
61801e04c3fSmrg
619af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
620af69d88dSmrg
62101e04c3fSmrg   if (!validate_bind_image_texture(ctx, unit, texture, level, layer, access,
6227ec681f3Smrg                                    format, true))
623af69d88dSmrg      return;
624af69d88dSmrg
62501e04c3fSmrg   if (texture) {
62601e04c3fSmrg      texObj = _mesa_lookup_texture(ctx, texture);
62701e04c3fSmrg
62801e04c3fSmrg      if (!texObj) {
62901e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)");
63001e04c3fSmrg         return;
63101e04c3fSmrg      }
63201e04c3fSmrg
63301e04c3fSmrg      /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES
63401e04c3fSmrg       * 3.1 spec:
635af69d88dSmrg       *
63601e04c3fSmrg       * "An INVALID_OPERATION error is generated if texture is not the name
63701e04c3fSmrg       *  of an immutable texture object."
63801e04c3fSmrg       *
63901e04c3fSmrg       * However note that issue 7 of the GL_OES_texture_buffer spec
64001e04c3fSmrg       * recognizes that there is no way to create immutable buffer textures,
64101e04c3fSmrg       * so those are excluded from this requirement.
6427ec681f3Smrg       *
6437ec681f3Smrg       * Additionally, issue 10 of the OES_EGL_image_external_essl3 spec
6447ec681f3Smrg       * states that glBindImageTexture must accept external texture objects.
645af69d88dSmrg       */
6467ec681f3Smrg      if (_mesa_is_gles(ctx) && !texObj->Immutable && !texObj->External &&
64701e04c3fSmrg          texObj->Target != GL_TEXTURE_BUFFER) {
64801e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
64901e04c3fSmrg                     "glBindImageTexture(!immutable)");
65001e04c3fSmrg         return;
65101e04c3fSmrg      }
652af69d88dSmrg   }
653af69d88dSmrg
65401e04c3fSmrg   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
65501e04c3fSmrg}
65601e04c3fSmrg
6577ec681f3Smrgvoid GLAPIENTRY
6587ec681f3Smrg_mesa_BindImageTextureEXT(GLuint index, GLuint texture, GLint level,
6597ec681f3Smrg                          GLboolean layered, GLint layer, GLenum access,
6607ec681f3Smrg                          GLint format)
6617ec681f3Smrg{
6627ec681f3Smrg   struct gl_texture_object *texObj = NULL;
6637ec681f3Smrg
6647ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
6657ec681f3Smrg
6667ec681f3Smrg   if (!validate_bind_image_texture(ctx, index, texture, level, layer, access,
6677ec681f3Smrg                                    format, false))
6687ec681f3Smrg      return;
6697ec681f3Smrg
6707ec681f3Smrg   if (texture) {
6717ec681f3Smrg      texObj = _mesa_lookup_texture(ctx, texture);
6727ec681f3Smrg
6737ec681f3Smrg      if (!texObj) {
6747ec681f3Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTextureEXT(texture)");
6757ec681f3Smrg         return;
6767ec681f3Smrg      }
6777ec681f3Smrg   }
6787ec681f3Smrg
6797ec681f3Smrg   bind_image_texture(ctx, texObj, index, level, layered, layer, access, format);
6807ec681f3Smrg}
6817ec681f3Smrg
68201e04c3fSmrgstatic ALWAYS_INLINE void
68301e04c3fSmrgbind_image_textures(struct gl_context *ctx, GLuint first, GLuint count,
68401e04c3fSmrg                    const GLuint *textures, bool no_error)
68501e04c3fSmrg{
68601e04c3fSmrg   int i;
68701e04c3fSmrg
688af69d88dSmrg   /* Assume that at least one binding will be changed */
6897ec681f3Smrg   FLUSH_VERTICES(ctx, 0, 0);
690af69d88dSmrg   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
691af69d88dSmrg
692af69d88dSmrg   /* Note that the error semantics for multi-bind commands differ from
693af69d88dSmrg    * those of other GL commands.
694af69d88dSmrg    *
695af69d88dSmrg    * The Issues section in the ARB_multi_bind spec says:
696af69d88dSmrg    *
697af69d88dSmrg    *    "(11) Typically, OpenGL specifies that if an error is generated by
698af69d88dSmrg    *          a command, that command has no effect.  This is somewhat
699af69d88dSmrg    *          unfortunate for multi-bind commands, because it would require
700af69d88dSmrg    *          a first pass to scan the entire list of bound objects for
701af69d88dSmrg    *          errors and then a second pass to actually perform the
702af69d88dSmrg    *          bindings.  Should we have different error semantics?
703af69d88dSmrg    *
704af69d88dSmrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
705af69d88dSmrg    *       one of the <count> binding points are invalid, that binding
706af69d88dSmrg    *       point is not updated and an error will be generated.  However,
707af69d88dSmrg    *       other binding points in the same command will be updated if
708af69d88dSmrg    *       their parameters are valid and no other error occurs."
709af69d88dSmrg    */
710af69d88dSmrg
71101e04c3fSmrg   _mesa_HashLockMutex(ctx->Shared->TexObjects);
712af69d88dSmrg
713af69d88dSmrg   for (i = 0; i < count; i++) {
714af69d88dSmrg      struct gl_image_unit *u = &ctx->ImageUnits[first + i];
715af69d88dSmrg      const GLuint texture = textures ? textures[i] : 0;
716af69d88dSmrg
71701e04c3fSmrg      if (texture) {
71801e04c3fSmrg         struct gl_texture_object *texObj = u->TexObj;
71901e04c3fSmrg         GLenum tex_format;
720af69d88dSmrg
72101e04c3fSmrg         if (!texObj || texObj->Name != texture) {
722af69d88dSmrg            texObj = _mesa_lookup_texture_locked(ctx, texture);
72301e04c3fSmrg            if (!no_error && !texObj) {
724af69d88dSmrg               /* The ARB_multi_bind spec says:
725af69d88dSmrg                *
726af69d88dSmrg                *    "An INVALID_OPERATION error is generated if any value
727af69d88dSmrg                *     in <textures> is not zero or the name of an existing
728af69d88dSmrg                *     texture object (per binding)."
729af69d88dSmrg                */
730af69d88dSmrg               _mesa_error(ctx, GL_INVALID_OPERATION,
731af69d88dSmrg                           "glBindImageTextures(textures[%d]=%u "
732af69d88dSmrg                           "is not zero or the name of an existing texture "
733af69d88dSmrg                           "object)", i, texture);
734af69d88dSmrg               continue;
735af69d88dSmrg            }
736af69d88dSmrg         }
737af69d88dSmrg
73801e04c3fSmrg         if (texObj->Target == GL_TEXTURE_BUFFER) {
73901e04c3fSmrg            tex_format = texObj->BufferObjectFormat;
74001e04c3fSmrg         } else {
74101e04c3fSmrg            struct gl_texture_image *image = texObj->Image[0][0];
742af69d88dSmrg
74301e04c3fSmrg            if (!no_error && (!image || image->Width == 0 ||
74401e04c3fSmrg                              image->Height == 0 || image->Depth == 0)) {
74501e04c3fSmrg               /* The ARB_multi_bind spec says:
74601e04c3fSmrg                *
74701e04c3fSmrg                *    "An INVALID_OPERATION error is generated if the width,
74801e04c3fSmrg                *     height, or depth of the level zero texture image of
74901e04c3fSmrg                *     any texture in <textures> is zero (per binding)."
75001e04c3fSmrg                */
75101e04c3fSmrg               _mesa_error(ctx, GL_INVALID_OPERATION,
75201e04c3fSmrg                           "glBindImageTextures(the width, height or depth "
75301e04c3fSmrg                           "of the level zero texture image of "
75401e04c3fSmrg                           "textures[%d]=%u is zero)", i, texture);
75501e04c3fSmrg               continue;
75601e04c3fSmrg            }
757af69d88dSmrg
75801e04c3fSmrg            tex_format = image->InternalFormat;
75901e04c3fSmrg         }
760af69d88dSmrg
76101e04c3fSmrg         if (!no_error &&
76201e04c3fSmrg             !_mesa_is_shader_image_format_supported(ctx, tex_format)) {
763af69d88dSmrg            /* The ARB_multi_bind spec says:
764af69d88dSmrg             *
765af69d88dSmrg             *   "An INVALID_OPERATION error is generated if the internal
766af69d88dSmrg             *    format of the level zero texture image of any texture
767af69d88dSmrg             *    in <textures> is not found in table 8.33 (per binding)."
768af69d88dSmrg             */
769af69d88dSmrg            _mesa_error(ctx, GL_INVALID_OPERATION,
770af69d88dSmrg                        "glBindImageTextures(the internal format %s of "
771af69d88dSmrg                        "the level zero texture image of textures[%d]=%u "
772af69d88dSmrg                        "is not supported)",
77301e04c3fSmrg                        _mesa_enum_to_string(tex_format),
774af69d88dSmrg                        i, texture);
775af69d88dSmrg            continue;
776af69d88dSmrg         }
777af69d88dSmrg
778af69d88dSmrg         /* Update the texture binding */
77901e04c3fSmrg         set_image_binding(u, texObj, 0,
78001e04c3fSmrg                           _mesa_tex_target_is_layered(texObj->Target),
78101e04c3fSmrg                           0, GL_READ_WRITE, tex_format);
782af69d88dSmrg      } else {
783af69d88dSmrg         /* Unbind the texture from the unit */
78401e04c3fSmrg         set_image_binding(u, NULL, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
785af69d88dSmrg      }
786af69d88dSmrg   }
787af69d88dSmrg
78801e04c3fSmrg   _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
78901e04c3fSmrg}
79001e04c3fSmrg
79101e04c3fSmrgvoid GLAPIENTRY
79201e04c3fSmrg_mesa_BindImageTextures_no_error(GLuint first, GLsizei count,
79301e04c3fSmrg                                 const GLuint *textures)
79401e04c3fSmrg{
79501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
79601e04c3fSmrg
79701e04c3fSmrg   bind_image_textures(ctx, first, count, textures, true);
798af69d88dSmrg}
799af69d88dSmrg
800af69d88dSmrgvoid GLAPIENTRY
80101e04c3fSmrg_mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
802af69d88dSmrg{
803af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
804af69d88dSmrg
80501e04c3fSmrg   if (!ctx->Extensions.ARB_shader_image_load_store) {
80601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()");
80701e04c3fSmrg      return;
80801e04c3fSmrg   }
80901e04c3fSmrg
81001e04c3fSmrg   if (first + count > ctx->Const.MaxImageUnits) {
81101e04c3fSmrg      /* The ARB_multi_bind spec says:
81201e04c3fSmrg       *
81301e04c3fSmrg       *    "An INVALID_OPERATION error is generated if <first> + <count>
81401e04c3fSmrg       *     is greater than the number of image units supported by
81501e04c3fSmrg       *     the implementation."
81601e04c3fSmrg       */
81701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
81801e04c3fSmrg                  "glBindImageTextures(first=%u + count=%d > the value of "
81901e04c3fSmrg                  "GL_MAX_IMAGE_UNITS=%u)",
82001e04c3fSmrg                  first, count, ctx->Const.MaxImageUnits);
82101e04c3fSmrg      return;
82201e04c3fSmrg   }
82301e04c3fSmrg
82401e04c3fSmrg   bind_image_textures(ctx, first, count, textures, false);
825af69d88dSmrg}
826