1848b8605Smrg/*
2848b8605Smrg * Copyright 2013 Intel Corporation
3848b8605Smrg *
4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5848b8605Smrg * copy of this software and associated documentation files (the "Software"),
6848b8605Smrg * to deal in the Software without restriction, including without limitation
7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
9848b8605Smrg * Software is furnished to do so, subject to the following conditions:
10848b8605Smrg *
11848b8605Smrg * The above copyright notice and this permission notice (including the next
12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
13848b8605Smrg * Software.
14848b8605Smrg *
15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21848b8605Smrg * DEALINGS IN THE SOFTWARE.
22848b8605Smrg *
23848b8605Smrg * Authors:
24848b8605Smrg *    Francisco Jerez <currojerez@riseup.net>
25848b8605Smrg */
26848b8605Smrg
27848b8605Smrg#include <assert.h>
28848b8605Smrg
29848b8605Smrg#include "shaderimage.h"
30848b8605Smrg#include "mtypes.h"
31848b8605Smrg#include "formats.h"
32848b8605Smrg#include "errors.h"
33b8e80941Smrg#include "hash.h"
34848b8605Smrg#include "context.h"
35848b8605Smrg#include "texobj.h"
36848b8605Smrg#include "teximage.h"
37848b8605Smrg#include "enums.h"
38848b8605Smrg
39848b8605Smrg/*
40848b8605Smrg * Define endian-invariant aliases for some mesa formats that are
41848b8605Smrg * defined in terms of their channel layout from LSB to MSB in a
42848b8605Smrg * 32-bit word.  The actual byte offsets matter here because the user
43848b8605Smrg * is allowed to bit-cast one format into another and get predictable
44848b8605Smrg * results.
45848b8605Smrg */
46848b8605Smrg#ifdef MESA_BIG_ENDIAN
47848b8605Smrg# define MESA_FORMAT_RGBA_8 MESA_FORMAT_A8B8G8R8_UNORM
48848b8605Smrg# define MESA_FORMAT_RG_16 MESA_FORMAT_G16R16_UNORM
49848b8605Smrg# define MESA_FORMAT_RG_8 MESA_FORMAT_G8R8_UNORM
50848b8605Smrg# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_A8B8G8R8_SNORM
51848b8605Smrg# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_G16R16_SNORM
52848b8605Smrg# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_G8R8_SNORM
53848b8605Smrg#else
54848b8605Smrg# define MESA_FORMAT_RGBA_8 MESA_FORMAT_R8G8B8A8_UNORM
55848b8605Smrg# define MESA_FORMAT_RG_16 MESA_FORMAT_R16G16_UNORM
56848b8605Smrg# define MESA_FORMAT_RG_8 MESA_FORMAT_R8G8_UNORM
57848b8605Smrg# define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_R8G8B8A8_SNORM
58848b8605Smrg# define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_R16G16_SNORM
59848b8605Smrg# define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_R8G8_SNORM
60848b8605Smrg#endif
61848b8605Smrg
62b8e80941Smrgmesa_format
63b8e80941Smrg_mesa_get_shader_image_format(GLenum format)
64848b8605Smrg{
65848b8605Smrg   switch (format) {
66848b8605Smrg   case GL_RGBA32F:
67848b8605Smrg      return MESA_FORMAT_RGBA_FLOAT32;
68848b8605Smrg
69848b8605Smrg   case GL_RGBA16F:
70848b8605Smrg      return MESA_FORMAT_RGBA_FLOAT16;
71848b8605Smrg
72848b8605Smrg   case GL_RG32F:
73848b8605Smrg      return MESA_FORMAT_RG_FLOAT32;
74848b8605Smrg
75848b8605Smrg   case GL_RG16F:
76848b8605Smrg      return MESA_FORMAT_RG_FLOAT16;
77848b8605Smrg
78848b8605Smrg   case GL_R11F_G11F_B10F:
79848b8605Smrg      return MESA_FORMAT_R11G11B10_FLOAT;
80848b8605Smrg
81848b8605Smrg   case GL_R32F:
82848b8605Smrg      return MESA_FORMAT_R_FLOAT32;
83848b8605Smrg
84848b8605Smrg   case GL_R16F:
85848b8605Smrg      return MESA_FORMAT_R_FLOAT16;
86848b8605Smrg
87848b8605Smrg   case GL_RGBA32UI:
88848b8605Smrg      return MESA_FORMAT_RGBA_UINT32;
89848b8605Smrg
90848b8605Smrg   case GL_RGBA16UI:
91848b8605Smrg      return MESA_FORMAT_RGBA_UINT16;
92848b8605Smrg
93848b8605Smrg   case GL_RGB10_A2UI:
94848b8605Smrg      return MESA_FORMAT_R10G10B10A2_UINT;
95848b8605Smrg
96848b8605Smrg   case GL_RGBA8UI:
97848b8605Smrg      return MESA_FORMAT_RGBA_UINT8;
98848b8605Smrg
99848b8605Smrg   case GL_RG32UI:
100848b8605Smrg      return MESA_FORMAT_RG_UINT32;
101848b8605Smrg
102848b8605Smrg   case GL_RG16UI:
103848b8605Smrg      return MESA_FORMAT_RG_UINT16;
104848b8605Smrg
105848b8605Smrg   case GL_RG8UI:
106848b8605Smrg      return MESA_FORMAT_RG_UINT8;
107848b8605Smrg
108848b8605Smrg   case GL_R32UI:
109848b8605Smrg      return MESA_FORMAT_R_UINT32;
110848b8605Smrg
111848b8605Smrg   case GL_R16UI:
112848b8605Smrg      return MESA_FORMAT_R_UINT16;
113848b8605Smrg
114848b8605Smrg   case GL_R8UI:
115848b8605Smrg      return MESA_FORMAT_R_UINT8;
116848b8605Smrg
117848b8605Smrg   case GL_RGBA32I:
118848b8605Smrg      return MESA_FORMAT_RGBA_SINT32;
119848b8605Smrg
120848b8605Smrg   case GL_RGBA16I:
121848b8605Smrg      return MESA_FORMAT_RGBA_SINT16;
122848b8605Smrg
123848b8605Smrg   case GL_RGBA8I:
124848b8605Smrg      return MESA_FORMAT_RGBA_SINT8;
125848b8605Smrg
126848b8605Smrg   case GL_RG32I:
127848b8605Smrg      return MESA_FORMAT_RG_SINT32;
128848b8605Smrg
129848b8605Smrg   case GL_RG16I:
130848b8605Smrg      return MESA_FORMAT_RG_SINT16;
131848b8605Smrg
132848b8605Smrg   case GL_RG8I:
133848b8605Smrg      return MESA_FORMAT_RG_SINT8;
134848b8605Smrg
135848b8605Smrg   case GL_R32I:
136848b8605Smrg      return MESA_FORMAT_R_SINT32;
137848b8605Smrg
138848b8605Smrg   case GL_R16I:
139848b8605Smrg      return MESA_FORMAT_R_SINT16;
140848b8605Smrg
141848b8605Smrg   case GL_R8I:
142848b8605Smrg      return MESA_FORMAT_R_SINT8;
143848b8605Smrg
144848b8605Smrg   case GL_RGBA16:
145848b8605Smrg      return MESA_FORMAT_RGBA_UNORM16;
146848b8605Smrg
147848b8605Smrg   case GL_RGB10_A2:
148848b8605Smrg      return MESA_FORMAT_R10G10B10A2_UNORM;
149848b8605Smrg
150848b8605Smrg   case GL_RGBA8:
151848b8605Smrg      return MESA_FORMAT_RGBA_8;
152848b8605Smrg
153848b8605Smrg   case GL_RG16:
154848b8605Smrg      return MESA_FORMAT_RG_16;
155848b8605Smrg
156848b8605Smrg   case GL_RG8:
157848b8605Smrg      return MESA_FORMAT_RG_8;
158848b8605Smrg
159848b8605Smrg   case GL_R16:
160848b8605Smrg      return MESA_FORMAT_R_UNORM16;
161848b8605Smrg
162848b8605Smrg   case GL_R8:
163848b8605Smrg      return MESA_FORMAT_R_UNORM8;
164848b8605Smrg
165848b8605Smrg   case GL_RGBA16_SNORM:
166848b8605Smrg      return MESA_FORMAT_RGBA_SNORM16;
167848b8605Smrg
168848b8605Smrg   case GL_RGBA8_SNORM:
169848b8605Smrg      return MESA_FORMAT_SIGNED_RGBA_8;
170848b8605Smrg
171848b8605Smrg   case GL_RG16_SNORM:
172848b8605Smrg      return MESA_FORMAT_SIGNED_RG_16;
173848b8605Smrg
174848b8605Smrg   case GL_RG8_SNORM:
175848b8605Smrg      return MESA_FORMAT_SIGNED_RG_8;
176848b8605Smrg
177848b8605Smrg   case GL_R16_SNORM:
178848b8605Smrg      return MESA_FORMAT_R_SNORM16;
179848b8605Smrg
180848b8605Smrg   case GL_R8_SNORM:
181848b8605Smrg      return MESA_FORMAT_R_SNORM8;
182848b8605Smrg
183848b8605Smrg   default:
184848b8605Smrg      return MESA_FORMAT_NONE;
185848b8605Smrg   }
186848b8605Smrg}
187848b8605Smrg
188848b8605Smrgenum image_format_class
189848b8605Smrg{
190848b8605Smrg   /** Not a valid image format. */
191848b8605Smrg   IMAGE_FORMAT_CLASS_NONE = 0,
192848b8605Smrg
193848b8605Smrg   /** Classes of image formats you can cast into each other. */
194848b8605Smrg   /** \{ */
195848b8605Smrg   IMAGE_FORMAT_CLASS_1X8,
196848b8605Smrg   IMAGE_FORMAT_CLASS_1X16,
197848b8605Smrg   IMAGE_FORMAT_CLASS_1X32,
198848b8605Smrg   IMAGE_FORMAT_CLASS_2X8,
199848b8605Smrg   IMAGE_FORMAT_CLASS_2X16,
200848b8605Smrg   IMAGE_FORMAT_CLASS_2X32,
201848b8605Smrg   IMAGE_FORMAT_CLASS_10_11_11,
202848b8605Smrg   IMAGE_FORMAT_CLASS_4X8,
203848b8605Smrg   IMAGE_FORMAT_CLASS_4X16,
204848b8605Smrg   IMAGE_FORMAT_CLASS_4X32,
205848b8605Smrg   IMAGE_FORMAT_CLASS_2_10_10_10
206848b8605Smrg   /** \} */
207848b8605Smrg};
208848b8605Smrg
209848b8605Smrgstatic enum image_format_class
210848b8605Smrgget_image_format_class(mesa_format format)
211848b8605Smrg{
212848b8605Smrg   switch (format) {
213848b8605Smrg   case MESA_FORMAT_RGBA_FLOAT32:
214848b8605Smrg      return IMAGE_FORMAT_CLASS_4X32;
215848b8605Smrg
216848b8605Smrg   case MESA_FORMAT_RGBA_FLOAT16:
217848b8605Smrg      return IMAGE_FORMAT_CLASS_4X16;
218848b8605Smrg
219848b8605Smrg   case MESA_FORMAT_RG_FLOAT32:
220848b8605Smrg      return IMAGE_FORMAT_CLASS_2X32;
221848b8605Smrg
222848b8605Smrg   case MESA_FORMAT_RG_FLOAT16:
223848b8605Smrg      return IMAGE_FORMAT_CLASS_2X16;
224848b8605Smrg
225848b8605Smrg   case MESA_FORMAT_R11G11B10_FLOAT:
226848b8605Smrg      return IMAGE_FORMAT_CLASS_10_11_11;
227848b8605Smrg
228848b8605Smrg   case MESA_FORMAT_R_FLOAT32:
229848b8605Smrg      return IMAGE_FORMAT_CLASS_1X32;
230848b8605Smrg
231848b8605Smrg   case MESA_FORMAT_R_FLOAT16:
232848b8605Smrg      return IMAGE_FORMAT_CLASS_1X16;
233848b8605Smrg
234848b8605Smrg   case MESA_FORMAT_RGBA_UINT32:
235848b8605Smrg      return IMAGE_FORMAT_CLASS_4X32;
236848b8605Smrg
237848b8605Smrg   case MESA_FORMAT_RGBA_UINT16:
238848b8605Smrg      return IMAGE_FORMAT_CLASS_4X16;
239848b8605Smrg
240848b8605Smrg   case MESA_FORMAT_R10G10B10A2_UINT:
241848b8605Smrg      return IMAGE_FORMAT_CLASS_2_10_10_10;
242848b8605Smrg
243848b8605Smrg   case MESA_FORMAT_RGBA_UINT8:
244848b8605Smrg      return IMAGE_FORMAT_CLASS_4X8;
245848b8605Smrg
246848b8605Smrg   case MESA_FORMAT_RG_UINT32:
247848b8605Smrg      return IMAGE_FORMAT_CLASS_2X32;
248848b8605Smrg
249848b8605Smrg   case MESA_FORMAT_RG_UINT16:
250848b8605Smrg      return IMAGE_FORMAT_CLASS_2X16;
251848b8605Smrg
252848b8605Smrg   case MESA_FORMAT_RG_UINT8:
253848b8605Smrg      return IMAGE_FORMAT_CLASS_2X8;
254848b8605Smrg
255848b8605Smrg   case MESA_FORMAT_R_UINT32:
256848b8605Smrg      return IMAGE_FORMAT_CLASS_1X32;
257848b8605Smrg
258848b8605Smrg   case MESA_FORMAT_R_UINT16:
259848b8605Smrg      return IMAGE_FORMAT_CLASS_1X16;
260848b8605Smrg
261848b8605Smrg   case MESA_FORMAT_R_UINT8:
262848b8605Smrg      return IMAGE_FORMAT_CLASS_1X8;
263848b8605Smrg
264848b8605Smrg   case MESA_FORMAT_RGBA_SINT32:
265848b8605Smrg      return IMAGE_FORMAT_CLASS_4X32;
266848b8605Smrg
267848b8605Smrg   case MESA_FORMAT_RGBA_SINT16:
268848b8605Smrg      return IMAGE_FORMAT_CLASS_4X16;
269848b8605Smrg
270848b8605Smrg   case MESA_FORMAT_RGBA_SINT8:
271848b8605Smrg      return IMAGE_FORMAT_CLASS_4X8;
272848b8605Smrg
273848b8605Smrg   case MESA_FORMAT_RG_SINT32:
274848b8605Smrg      return IMAGE_FORMAT_CLASS_2X32;
275848b8605Smrg
276848b8605Smrg   case MESA_FORMAT_RG_SINT16:
277848b8605Smrg      return IMAGE_FORMAT_CLASS_2X16;
278848b8605Smrg
279848b8605Smrg   case MESA_FORMAT_RG_SINT8:
280848b8605Smrg      return IMAGE_FORMAT_CLASS_2X8;
281848b8605Smrg
282848b8605Smrg   case MESA_FORMAT_R_SINT32:
283848b8605Smrg      return IMAGE_FORMAT_CLASS_1X32;
284848b8605Smrg
285848b8605Smrg   case MESA_FORMAT_R_SINT16:
286848b8605Smrg      return IMAGE_FORMAT_CLASS_1X16;
287848b8605Smrg
288848b8605Smrg   case MESA_FORMAT_R_SINT8:
289848b8605Smrg      return IMAGE_FORMAT_CLASS_1X8;
290848b8605Smrg
291848b8605Smrg   case MESA_FORMAT_RGBA_UNORM16:
292848b8605Smrg      return IMAGE_FORMAT_CLASS_4X16;
293848b8605Smrg
294848b8605Smrg   case MESA_FORMAT_R10G10B10A2_UNORM:
295848b8605Smrg      return IMAGE_FORMAT_CLASS_2_10_10_10;
296848b8605Smrg
297848b8605Smrg   case MESA_FORMAT_RGBA_8:
298848b8605Smrg      return IMAGE_FORMAT_CLASS_4X8;
299848b8605Smrg
300848b8605Smrg   case MESA_FORMAT_RG_16:
301848b8605Smrg      return IMAGE_FORMAT_CLASS_2X16;
302848b8605Smrg
303848b8605Smrg   case MESA_FORMAT_RG_8:
304848b8605Smrg      return IMAGE_FORMAT_CLASS_2X8;
305848b8605Smrg
306848b8605Smrg   case MESA_FORMAT_R_UNORM16:
307848b8605Smrg      return IMAGE_FORMAT_CLASS_1X16;
308848b8605Smrg
309848b8605Smrg   case MESA_FORMAT_R_UNORM8:
310848b8605Smrg      return IMAGE_FORMAT_CLASS_1X8;
311848b8605Smrg
312848b8605Smrg   case MESA_FORMAT_RGBA_SNORM16:
313848b8605Smrg      return IMAGE_FORMAT_CLASS_4X16;
314848b8605Smrg
315848b8605Smrg   case MESA_FORMAT_SIGNED_RGBA_8:
316848b8605Smrg      return IMAGE_FORMAT_CLASS_4X8;
317848b8605Smrg
318848b8605Smrg   case MESA_FORMAT_SIGNED_RG_16:
319848b8605Smrg      return IMAGE_FORMAT_CLASS_2X16;
320848b8605Smrg
321848b8605Smrg   case MESA_FORMAT_SIGNED_RG_8:
322848b8605Smrg      return IMAGE_FORMAT_CLASS_2X8;
323848b8605Smrg
324848b8605Smrg   case MESA_FORMAT_R_SNORM16:
325848b8605Smrg      return IMAGE_FORMAT_CLASS_1X16;
326848b8605Smrg
327848b8605Smrg   case MESA_FORMAT_R_SNORM8:
328848b8605Smrg      return IMAGE_FORMAT_CLASS_1X8;
329848b8605Smrg
330848b8605Smrg   default:
331848b8605Smrg      return IMAGE_FORMAT_CLASS_NONE;
332848b8605Smrg   }
333848b8605Smrg}
334848b8605Smrg
335b8e80941Smrgstatic GLenum
336b8e80941Smrg_image_format_class_to_glenum(enum image_format_class class)
337b8e80941Smrg{
338b8e80941Smrg   switch (class) {
339b8e80941Smrg   case IMAGE_FORMAT_CLASS_NONE:
340b8e80941Smrg      return GL_NONE;
341b8e80941Smrg   case IMAGE_FORMAT_CLASS_1X8:
342b8e80941Smrg      return GL_IMAGE_CLASS_1_X_8;
343b8e80941Smrg   case IMAGE_FORMAT_CLASS_1X16:
344b8e80941Smrg      return GL_IMAGE_CLASS_1_X_16;
345b8e80941Smrg   case IMAGE_FORMAT_CLASS_1X32:
346b8e80941Smrg      return GL_IMAGE_CLASS_1_X_32;
347b8e80941Smrg   case IMAGE_FORMAT_CLASS_2X8:
348b8e80941Smrg      return GL_IMAGE_CLASS_2_X_8;
349b8e80941Smrg   case IMAGE_FORMAT_CLASS_2X16:
350b8e80941Smrg      return GL_IMAGE_CLASS_2_X_16;
351b8e80941Smrg   case IMAGE_FORMAT_CLASS_2X32:
352b8e80941Smrg      return GL_IMAGE_CLASS_2_X_32;
353b8e80941Smrg   case IMAGE_FORMAT_CLASS_10_11_11:
354b8e80941Smrg      return GL_IMAGE_CLASS_11_11_10;
355b8e80941Smrg   case IMAGE_FORMAT_CLASS_4X8:
356b8e80941Smrg      return GL_IMAGE_CLASS_4_X_8;
357b8e80941Smrg   case IMAGE_FORMAT_CLASS_4X16:
358b8e80941Smrg      return GL_IMAGE_CLASS_4_X_16;
359b8e80941Smrg   case IMAGE_FORMAT_CLASS_4X32:
360b8e80941Smrg      return GL_IMAGE_CLASS_4_X_32;
361b8e80941Smrg   case IMAGE_FORMAT_CLASS_2_10_10_10:
362b8e80941Smrg      return GL_IMAGE_CLASS_10_10_10_2;
363b8e80941Smrg   default:
364b8e80941Smrg      assert(!"Invalid image_format_class");
365b8e80941Smrg      return GL_NONE;
366b8e80941Smrg   }
367b8e80941Smrg}
368b8e80941Smrg
369b8e80941SmrgGLenum
370b8e80941Smrg_mesa_get_image_format_class(GLenum format)
371b8e80941Smrg{
372b8e80941Smrg   mesa_format tex_format = _mesa_get_shader_image_format(format);
373b8e80941Smrg   if (tex_format == MESA_FORMAT_NONE)
374b8e80941Smrg      return GL_NONE;
375b8e80941Smrg
376b8e80941Smrg   enum image_format_class class = get_image_format_class(tex_format);
377b8e80941Smrg   return _image_format_class_to_glenum(class);
378b8e80941Smrg}
379b8e80941Smrg
380b8e80941Smrgbool
381b8e80941Smrg_mesa_is_shader_image_format_supported(const struct gl_context *ctx,
382b8e80941Smrg                                       GLenum format)
383b8e80941Smrg{
384b8e80941Smrg   switch (format) {
385b8e80941Smrg   /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the
386b8e80941Smrg    * OpenGL ES 3.1 specification.
387b8e80941Smrg    */
388b8e80941Smrg   case GL_RGBA32F:
389b8e80941Smrg   case GL_RGBA16F:
390b8e80941Smrg   case GL_R32F:
391b8e80941Smrg   case GL_RGBA32UI:
392b8e80941Smrg   case GL_RGBA16UI:
393b8e80941Smrg   case GL_RGBA8UI:
394b8e80941Smrg   case GL_R32UI:
395b8e80941Smrg   case GL_RGBA32I:
396b8e80941Smrg   case GL_RGBA16I:
397b8e80941Smrg   case GL_RGBA8I:
398b8e80941Smrg   case GL_R32I:
399b8e80941Smrg   case GL_RGBA8:
400b8e80941Smrg   case GL_RGBA8_SNORM:
401b8e80941Smrg      return true;
402b8e80941Smrg
403b8e80941Smrg   /* Formats supported on unextended desktop GL and the original
404b8e80941Smrg    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
405b8e80941Smrg    * specification or by GLES 3.1 with GL_NV_image_formats extension.
406b8e80941Smrg    */
407b8e80941Smrg   case GL_RG32F:
408b8e80941Smrg   case GL_RG16F:
409b8e80941Smrg   case GL_R11F_G11F_B10F:
410b8e80941Smrg   case GL_R16F:
411b8e80941Smrg   case GL_RGB10_A2UI:
412b8e80941Smrg   case GL_RG32UI:
413b8e80941Smrg   case GL_RG16UI:
414b8e80941Smrg   case GL_RG8UI:
415b8e80941Smrg   case GL_R16UI:
416b8e80941Smrg   case GL_R8UI:
417b8e80941Smrg   case GL_RG32I:
418b8e80941Smrg   case GL_RG16I:
419b8e80941Smrg   case GL_RG8I:
420b8e80941Smrg   case GL_R16I:
421b8e80941Smrg   case GL_R8I:
422b8e80941Smrg   case GL_RGB10_A2:
423b8e80941Smrg   case GL_RG8:
424b8e80941Smrg   case GL_R8:
425b8e80941Smrg   case GL_RG8_SNORM:
426b8e80941Smrg   case GL_R8_SNORM:
427b8e80941Smrg      return true;
428b8e80941Smrg
429b8e80941Smrg   /* Formats supported on unextended desktop GL and the original
430b8e80941Smrg    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
431b8e80941Smrg    * specification.
432b8e80941Smrg    *
433b8e80941Smrg    * Following formats are supported by GLES 3.1 with GL_NV_image_formats &
434b8e80941Smrg    * GL_EXT_texture_norm16 extensions.
435b8e80941Smrg    */
436b8e80941Smrg   case GL_RGBA16:
437b8e80941Smrg   case GL_RGBA16_SNORM:
438b8e80941Smrg   case GL_RG16:
439b8e80941Smrg   case GL_RG16_SNORM:
440b8e80941Smrg   case GL_R16:
441b8e80941Smrg   case GL_R16_SNORM:
442b8e80941Smrg      return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx);
443b8e80941Smrg
444b8e80941Smrg   default:
445b8e80941Smrg      return false;
446b8e80941Smrg   }
447b8e80941Smrg}
448b8e80941Smrg
449b8e80941Smrgstruct gl_image_unit
450b8e80941Smrg_mesa_default_image_unit(struct gl_context *ctx)
451b8e80941Smrg{
452b8e80941Smrg   const GLenum format = _mesa_is_desktop_gl(ctx) ? GL_R8 : GL_R32UI;
453b8e80941Smrg   const struct gl_image_unit u = {
454b8e80941Smrg      .Access = GL_READ_ONLY,
455b8e80941Smrg      .Format = format,
456b8e80941Smrg      ._ActualFormat = _mesa_get_shader_image_format(format)
457b8e80941Smrg   };
458b8e80941Smrg   return u;
459b8e80941Smrg}
460b8e80941Smrg
461b8e80941Smrgvoid
462b8e80941Smrg_mesa_init_image_units(struct gl_context *ctx)
463b8e80941Smrg{
464b8e80941Smrg   unsigned i;
465b8e80941Smrg
466b8e80941Smrg   ASSERT_BITFIELD_SIZE(struct gl_image_unit, Format, MESA_FORMAT_COUNT);
467b8e80941Smrg
468b8e80941Smrg   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
469b8e80941Smrg      ctx->ImageUnits[i] = _mesa_default_image_unit(ctx);
470b8e80941Smrg}
471b8e80941Smrg
472b8e80941Smrg
473b8e80941Smrgvoid
474b8e80941Smrg_mesa_free_image_textures(struct gl_context *ctx)
475b8e80941Smrg{
476b8e80941Smrg   unsigned i;
477b8e80941Smrg
478b8e80941Smrg   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
479b8e80941Smrg      _mesa_reference_texobj(&ctx->ImageUnits[i].TexObj, NULL);
480b8e80941Smrg}
481b8e80941Smrg
482b8e80941SmrgGLboolean
483b8e80941Smrg_mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u)
484848b8605Smrg{
485848b8605Smrg   struct gl_texture_object *t = u->TexObj;
486b8e80941Smrg   mesa_format tex_format;
487848b8605Smrg
488b8e80941Smrg   if (!t)
489848b8605Smrg      return GL_FALSE;
490848b8605Smrg
491b8e80941Smrg   if (!t->_BaseComplete && !t->_MipmapComplete)
492b8e80941Smrg       _mesa_test_texobj_completeness(ctx, t);
493848b8605Smrg
494b8e80941Smrg   if (u->Level < t->BaseLevel ||
495b8e80941Smrg       u->Level > t->_MaxLevel ||
496b8e80941Smrg       (u->Level == t->BaseLevel && !t->_BaseComplete) ||
497848b8605Smrg       (u->Level != t->BaseLevel && !t->_MipmapComplete))
498848b8605Smrg      return GL_FALSE;
499848b8605Smrg
500848b8605Smrg   if (_mesa_tex_target_is_layered(t->Target) &&
501b8e80941Smrg       u->_Layer >= _mesa_get_texture_layers(t, u->Level))
502848b8605Smrg      return GL_FALSE;
503848b8605Smrg
504b8e80941Smrg   if (t->Target == GL_TEXTURE_BUFFER) {
505b8e80941Smrg      tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat);
506b8e80941Smrg
507b8e80941Smrg   } else {
508b8e80941Smrg      struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ?
509b8e80941Smrg                                      t->Image[u->_Layer][u->Level] :
510b8e80941Smrg                                      t->Image[0][u->Level]);
511b8e80941Smrg
512b8e80941Smrg      if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples)
513b8e80941Smrg         return GL_FALSE;
514848b8605Smrg
515b8e80941Smrg      tex_format = _mesa_get_shader_image_format(img->InternalFormat);
516b8e80941Smrg   }
517b8e80941Smrg
518b8e80941Smrg   if (!tex_format)
519848b8605Smrg      return GL_FALSE;
520848b8605Smrg
521848b8605Smrg   switch (t->ImageFormatCompatibilityType) {
522848b8605Smrg   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE:
523b8e80941Smrg      if (_mesa_get_format_bytes(tex_format) !=
524848b8605Smrg          _mesa_get_format_bytes(u->_ActualFormat))
525848b8605Smrg         return GL_FALSE;
526848b8605Smrg      break;
527848b8605Smrg
528848b8605Smrg   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS:
529b8e80941Smrg      if (get_image_format_class(tex_format) !=
530848b8605Smrg          get_image_format_class(u->_ActualFormat))
531848b8605Smrg         return GL_FALSE;
532848b8605Smrg      break;
533848b8605Smrg
534848b8605Smrg   default:
535848b8605Smrg      assert(!"Unexpected image format compatibility type");
536848b8605Smrg   }
537848b8605Smrg
538848b8605Smrg   return GL_TRUE;
539848b8605Smrg}
540848b8605Smrg
541848b8605Smrgstatic GLboolean
542848b8605Smrgvalidate_bind_image_texture(struct gl_context *ctx, GLuint unit,
543b8e80941Smrg                            GLuint texture, GLint level, GLint layer,
544b8e80941Smrg                            GLenum access, GLenum format)
545848b8605Smrg{
546848b8605Smrg   assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS);
547848b8605Smrg
548848b8605Smrg   if (unit >= ctx->Const.MaxImageUnits) {
549848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)");
550848b8605Smrg      return GL_FALSE;
551848b8605Smrg   }
552848b8605Smrg
553848b8605Smrg   if (level < 0) {
554848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)");
555848b8605Smrg      return GL_FALSE;
556848b8605Smrg   }
557848b8605Smrg
558848b8605Smrg   if (layer < 0) {
559848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)");
560848b8605Smrg      return GL_FALSE;
561848b8605Smrg   }
562848b8605Smrg
563848b8605Smrg   if (access != GL_READ_ONLY &&
564848b8605Smrg       access != GL_WRITE_ONLY &&
565848b8605Smrg       access != GL_READ_WRITE) {
566848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)");
567848b8605Smrg      return GL_FALSE;
568848b8605Smrg   }
569848b8605Smrg
570b8e80941Smrg   if (!_mesa_is_shader_image_format_supported(ctx, format)) {
571848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
572848b8605Smrg      return GL_FALSE;
573848b8605Smrg   }
574848b8605Smrg
575848b8605Smrg   return GL_TRUE;
576848b8605Smrg}
577848b8605Smrg
578b8e80941Smrgstatic void
579b8e80941Smrgset_image_binding(struct gl_image_unit *u, struct gl_texture_object *texObj,
580b8e80941Smrg                  GLint level, GLboolean layered, GLint layer, GLenum access,
581b8e80941Smrg                  GLenum format)
582848b8605Smrg{
583b8e80941Smrg   u->Level = level;
584b8e80941Smrg   u->Access = access;
585b8e80941Smrg   u->Format = format;
586b8e80941Smrg   u->_ActualFormat = _mesa_get_shader_image_format(format);
587b8e80941Smrg
588b8e80941Smrg   if (texObj && _mesa_tex_target_is_layered(texObj->Target)) {
589b8e80941Smrg      u->Layered = layered;
590b8e80941Smrg      u->Layer = layer;
591b8e80941Smrg      u->_Layer = (u->Layered ? 0 : u->Layer);
592b8e80941Smrg   } else {
593b8e80941Smrg      u->Layered = GL_FALSE;
594b8e80941Smrg      u->Layer = 0;
595b8e80941Smrg   }
596848b8605Smrg
597b8e80941Smrg   _mesa_reference_texobj(&u->TexObj, texObj);
598b8e80941Smrg}
599b8e80941Smrg
600b8e80941Smrgstatic void
601b8e80941Smrgbind_image_texture(struct gl_context *ctx, struct gl_texture_object *texObj,
602b8e80941Smrg                   GLuint unit, GLint level, GLboolean layered, GLint layer,
603b8e80941Smrg                   GLenum access, GLenum format)
604b8e80941Smrg{
605b8e80941Smrg   struct gl_image_unit *u;
606848b8605Smrg
607848b8605Smrg   u = &ctx->ImageUnits[unit];
608848b8605Smrg
609848b8605Smrg   FLUSH_VERTICES(ctx, 0);
610848b8605Smrg   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
611848b8605Smrg
612b8e80941Smrg   set_image_binding(u, texObj, level, layered, layer, access, format);
613b8e80941Smrg}
614848b8605Smrg
615b8e80941Smrgvoid GLAPIENTRY
616b8e80941Smrg_mesa_BindImageTexture_no_error(GLuint unit, GLuint texture, GLint level,
617b8e80941Smrg                                GLboolean layered, GLint layer, GLenum access,
618b8e80941Smrg                                GLenum format)
619b8e80941Smrg{
620b8e80941Smrg   struct gl_texture_object *texObj = NULL;
621848b8605Smrg
622b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
623848b8605Smrg
624b8e80941Smrg   if (texture)
625b8e80941Smrg      texObj = _mesa_lookup_texture(ctx, texture);
626848b8605Smrg
627b8e80941Smrg   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
628848b8605Smrg}
629848b8605Smrg
630848b8605Smrgvoid GLAPIENTRY
631b8e80941Smrg_mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
632b8e80941Smrg                       GLboolean layered, GLint layer, GLenum access,
633b8e80941Smrg                       GLenum format)
634848b8605Smrg{
635b8e80941Smrg   struct gl_texture_object *texObj = NULL;
636b8e80941Smrg
637848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
638848b8605Smrg
639b8e80941Smrg   if (!validate_bind_image_texture(ctx, unit, texture, level, layer, access,
640b8e80941Smrg                                    format))
641848b8605Smrg      return;
642848b8605Smrg
643b8e80941Smrg   if (texture) {
644b8e80941Smrg      texObj = _mesa_lookup_texture(ctx, texture);
645b8e80941Smrg
646b8e80941Smrg      if (!texObj) {
647b8e80941Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)");
648b8e80941Smrg         return;
649b8e80941Smrg      }
650b8e80941Smrg
651b8e80941Smrg      /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES
652b8e80941Smrg       * 3.1 spec:
653848b8605Smrg       *
654b8e80941Smrg       * "An INVALID_OPERATION error is generated if texture is not the name
655b8e80941Smrg       *  of an immutable texture object."
656b8e80941Smrg       *
657b8e80941Smrg       * However note that issue 7 of the GL_OES_texture_buffer spec
658b8e80941Smrg       * recognizes that there is no way to create immutable buffer textures,
659b8e80941Smrg       * so those are excluded from this requirement.
660848b8605Smrg       */
661b8e80941Smrg      if (_mesa_is_gles(ctx) && !texObj->Immutable &&
662b8e80941Smrg          texObj->Target != GL_TEXTURE_BUFFER) {
663b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
664b8e80941Smrg                     "glBindImageTexture(!immutable)");
665b8e80941Smrg         return;
666b8e80941Smrg      }
667848b8605Smrg   }
668848b8605Smrg
669b8e80941Smrg   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
670b8e80941Smrg}
671b8e80941Smrg
672b8e80941Smrgstatic ALWAYS_INLINE void
673b8e80941Smrgbind_image_textures(struct gl_context *ctx, GLuint first, GLuint count,
674b8e80941Smrg                    const GLuint *textures, bool no_error)
675b8e80941Smrg{
676b8e80941Smrg   int i;
677b8e80941Smrg
678848b8605Smrg   /* Assume that at least one binding will be changed */
679848b8605Smrg   FLUSH_VERTICES(ctx, 0);
680848b8605Smrg   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
681848b8605Smrg
682848b8605Smrg   /* Note that the error semantics for multi-bind commands differ from
683848b8605Smrg    * those of other GL commands.
684848b8605Smrg    *
685848b8605Smrg    * The Issues section in the ARB_multi_bind spec says:
686848b8605Smrg    *
687848b8605Smrg    *    "(11) Typically, OpenGL specifies that if an error is generated by
688848b8605Smrg    *          a command, that command has no effect.  This is somewhat
689848b8605Smrg    *          unfortunate for multi-bind commands, because it would require
690848b8605Smrg    *          a first pass to scan the entire list of bound objects for
691848b8605Smrg    *          errors and then a second pass to actually perform the
692848b8605Smrg    *          bindings.  Should we have different error semantics?
693848b8605Smrg    *
694848b8605Smrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
695848b8605Smrg    *       one of the <count> binding points are invalid, that binding
696848b8605Smrg    *       point is not updated and an error will be generated.  However,
697848b8605Smrg    *       other binding points in the same command will be updated if
698848b8605Smrg    *       their parameters are valid and no other error occurs."
699848b8605Smrg    */
700848b8605Smrg
701b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->TexObjects);
702848b8605Smrg
703848b8605Smrg   for (i = 0; i < count; i++) {
704848b8605Smrg      struct gl_image_unit *u = &ctx->ImageUnits[first + i];
705848b8605Smrg      const GLuint texture = textures ? textures[i] : 0;
706848b8605Smrg
707b8e80941Smrg      if (texture) {
708b8e80941Smrg         struct gl_texture_object *texObj = u->TexObj;
709b8e80941Smrg         GLenum tex_format;
710848b8605Smrg
711b8e80941Smrg         if (!texObj || texObj->Name != texture) {
712848b8605Smrg            texObj = _mesa_lookup_texture_locked(ctx, texture);
713b8e80941Smrg            if (!no_error && !texObj) {
714848b8605Smrg               /* The ARB_multi_bind spec says:
715848b8605Smrg                *
716848b8605Smrg                *    "An INVALID_OPERATION error is generated if any value
717848b8605Smrg                *     in <textures> is not zero or the name of an existing
718848b8605Smrg                *     texture object (per binding)."
719848b8605Smrg                */
720848b8605Smrg               _mesa_error(ctx, GL_INVALID_OPERATION,
721848b8605Smrg                           "glBindImageTextures(textures[%d]=%u "
722848b8605Smrg                           "is not zero or the name of an existing texture "
723848b8605Smrg                           "object)", i, texture);
724848b8605Smrg               continue;
725848b8605Smrg            }
726848b8605Smrg         }
727848b8605Smrg
728b8e80941Smrg         if (texObj->Target == GL_TEXTURE_BUFFER) {
729b8e80941Smrg            tex_format = texObj->BufferObjectFormat;
730b8e80941Smrg         } else {
731b8e80941Smrg            struct gl_texture_image *image = texObj->Image[0][0];
732848b8605Smrg
733b8e80941Smrg            if (!no_error && (!image || image->Width == 0 ||
734b8e80941Smrg                              image->Height == 0 || image->Depth == 0)) {
735b8e80941Smrg               /* The ARB_multi_bind spec says:
736b8e80941Smrg                *
737b8e80941Smrg                *    "An INVALID_OPERATION error is generated if the width,
738b8e80941Smrg                *     height, or depth of the level zero texture image of
739b8e80941Smrg                *     any texture in <textures> is zero (per binding)."
740b8e80941Smrg                */
741b8e80941Smrg               _mesa_error(ctx, GL_INVALID_OPERATION,
742b8e80941Smrg                           "glBindImageTextures(the width, height or depth "
743b8e80941Smrg                           "of the level zero texture image of "
744b8e80941Smrg                           "textures[%d]=%u is zero)", i, texture);
745b8e80941Smrg               continue;
746b8e80941Smrg            }
747848b8605Smrg
748b8e80941Smrg            tex_format = image->InternalFormat;
749b8e80941Smrg         }
750848b8605Smrg
751b8e80941Smrg         if (!no_error &&
752b8e80941Smrg             !_mesa_is_shader_image_format_supported(ctx, tex_format)) {
753848b8605Smrg            /* The ARB_multi_bind spec says:
754848b8605Smrg             *
755848b8605Smrg             *   "An INVALID_OPERATION error is generated if the internal
756848b8605Smrg             *    format of the level zero texture image of any texture
757848b8605Smrg             *    in <textures> is not found in table 8.33 (per binding)."
758848b8605Smrg             */
759848b8605Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
760848b8605Smrg                        "glBindImageTextures(the internal format %s of "
761848b8605Smrg                        "the level zero texture image of textures[%d]=%u "
762848b8605Smrg                        "is not supported)",
763b8e80941Smrg                        _mesa_enum_to_string(tex_format),
764848b8605Smrg                        i, texture);
765848b8605Smrg            continue;
766848b8605Smrg         }
767848b8605Smrg
768848b8605Smrg         /* Update the texture binding */
769b8e80941Smrg         set_image_binding(u, texObj, 0,
770b8e80941Smrg                           _mesa_tex_target_is_layered(texObj->Target),
771b8e80941Smrg                           0, GL_READ_WRITE, tex_format);
772848b8605Smrg      } else {
773848b8605Smrg         /* Unbind the texture from the unit */
774b8e80941Smrg         set_image_binding(u, NULL, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
775848b8605Smrg      }
776848b8605Smrg   }
777848b8605Smrg
778b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
779848b8605Smrg}
780848b8605Smrg
781848b8605Smrgvoid GLAPIENTRY
782b8e80941Smrg_mesa_BindImageTextures_no_error(GLuint first, GLsizei count,
783b8e80941Smrg                                 const GLuint *textures)
784848b8605Smrg{
785848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
786848b8605Smrg
787b8e80941Smrg   bind_image_textures(ctx, first, count, textures, true);
788b8e80941Smrg}
789b8e80941Smrg
790b8e80941Smrgvoid GLAPIENTRY
791b8e80941Smrg_mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
792b8e80941Smrg{
793b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
794b8e80941Smrg
795b8e80941Smrg   if (!ctx->Extensions.ARB_shader_image_load_store) {
796b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()");
797b8e80941Smrg      return;
798b8e80941Smrg   }
799b8e80941Smrg
800b8e80941Smrg   if (first + count > ctx->Const.MaxImageUnits) {
801b8e80941Smrg      /* The ARB_multi_bind spec says:
802b8e80941Smrg       *
803b8e80941Smrg       *    "An INVALID_OPERATION error is generated if <first> + <count>
804b8e80941Smrg       *     is greater than the number of image units supported by
805b8e80941Smrg       *     the implementation."
806b8e80941Smrg       */
807b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
808b8e80941Smrg                  "glBindImageTextures(first=%u + count=%d > the value of "
809b8e80941Smrg                  "GL_MAX_IMAGE_UNITS=%u)",
810b8e80941Smrg                  first, count, ctx->Const.MaxImageUnits);
811b8e80941Smrg      return;
812b8e80941Smrg   }
813b8e80941Smrg
814b8e80941Smrg   bind_image_textures(ctx, first, count, textures, false);
815848b8605Smrg}
816