1/*
2 * Copyright 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 *    Francisco Jerez <currojerez@riseup.net>
25 */
26
27#include <assert.h>
28
29#include "shaderimage.h"
30#include "mtypes.h"
31#include "formats.h"
32#include "errors.h"
33#include "hash.h"
34#include "context.h"
35#include "texobj.h"
36#include "teximage.h"
37#include "enums.h"
38
39mesa_format
40_mesa_get_shader_image_format(GLenum format)
41{
42   switch (format) {
43   case GL_RGBA32F:
44      return MESA_FORMAT_RGBA_FLOAT32;
45
46   case GL_RGBA16F:
47      return MESA_FORMAT_RGBA_FLOAT16;
48
49   case GL_RG32F:
50      return MESA_FORMAT_RG_FLOAT32;
51
52   case GL_RG16F:
53      return MESA_FORMAT_RG_FLOAT16;
54
55   case GL_R11F_G11F_B10F:
56      return MESA_FORMAT_R11G11B10_FLOAT;
57
58   case GL_R32F:
59      return MESA_FORMAT_R_FLOAT32;
60
61   case GL_R16F:
62      return MESA_FORMAT_R_FLOAT16;
63
64   case GL_RGBA32UI:
65      return MESA_FORMAT_RGBA_UINT32;
66
67   case GL_RGBA16UI:
68      return MESA_FORMAT_RGBA_UINT16;
69
70   case GL_RGB10_A2UI:
71      return MESA_FORMAT_R10G10B10A2_UINT;
72
73   case GL_RGBA8UI:
74      return MESA_FORMAT_RGBA_UINT8;
75
76   case GL_RG32UI:
77      return MESA_FORMAT_RG_UINT32;
78
79   case GL_RG16UI:
80      return MESA_FORMAT_RG_UINT16;
81
82   case GL_RG8UI:
83      return MESA_FORMAT_RG_UINT8;
84
85   case GL_R32UI:
86      return MESA_FORMAT_R_UINT32;
87
88   case GL_R16UI:
89      return MESA_FORMAT_R_UINT16;
90
91   case GL_R8UI:
92      return MESA_FORMAT_R_UINT8;
93
94   case GL_RGBA32I:
95      return MESA_FORMAT_RGBA_SINT32;
96
97   case GL_RGBA16I:
98      return MESA_FORMAT_RGBA_SINT16;
99
100   case GL_RGBA8I:
101      return MESA_FORMAT_RGBA_SINT8;
102
103   case GL_RG32I:
104      return MESA_FORMAT_RG_SINT32;
105
106   case GL_RG16I:
107      return MESA_FORMAT_RG_SINT16;
108
109   case GL_RG8I:
110      return MESA_FORMAT_RG_SINT8;
111
112   case GL_R32I:
113      return MESA_FORMAT_R_SINT32;
114
115   case GL_R16I:
116      return MESA_FORMAT_R_SINT16;
117
118   case GL_R8I:
119      return MESA_FORMAT_R_SINT8;
120
121   case GL_RGBA16:
122      return MESA_FORMAT_RGBA_UNORM16;
123
124   case GL_RGB10_A2:
125      return MESA_FORMAT_R10G10B10A2_UNORM;
126
127   case GL_RGBA8:
128      return MESA_FORMAT_RGBA_UNORM8;
129
130   case GL_RG16:
131      return MESA_FORMAT_RG_UNORM16;
132
133   case GL_RG8:
134      return MESA_FORMAT_RG_UNORM8;
135
136   case GL_R16:
137      return MESA_FORMAT_R_UNORM16;
138
139   case GL_R8:
140      return MESA_FORMAT_R_UNORM8;
141
142   case GL_RGBA16_SNORM:
143      return MESA_FORMAT_RGBA_SNORM16;
144
145   case GL_RGBA8_SNORM:
146      return MESA_FORMAT_RGBA_SNORM8;
147
148   case GL_RG16_SNORM:
149      return MESA_FORMAT_RG_SNORM16;
150
151   case GL_RG8_SNORM:
152      return MESA_FORMAT_RG_SNORM8;
153
154   case GL_R16_SNORM:
155      return MESA_FORMAT_R_SNORM16;
156
157   case GL_R8_SNORM:
158      return MESA_FORMAT_R_SNORM8;
159
160   default:
161      return MESA_FORMAT_NONE;
162   }
163}
164
165enum image_format_class
166{
167   /** Not a valid image format. */
168   IMAGE_FORMAT_CLASS_NONE = 0,
169
170   /** Classes of image formats you can cast into each other. */
171   /** \{ */
172   IMAGE_FORMAT_CLASS_1X8,
173   IMAGE_FORMAT_CLASS_1X16,
174   IMAGE_FORMAT_CLASS_1X32,
175   IMAGE_FORMAT_CLASS_2X8,
176   IMAGE_FORMAT_CLASS_2X16,
177   IMAGE_FORMAT_CLASS_2X32,
178   IMAGE_FORMAT_CLASS_10_11_11,
179   IMAGE_FORMAT_CLASS_4X8,
180   IMAGE_FORMAT_CLASS_4X16,
181   IMAGE_FORMAT_CLASS_4X32,
182   IMAGE_FORMAT_CLASS_2_10_10_10
183   /** \} */
184};
185
186static enum image_format_class
187get_image_format_class(mesa_format format)
188{
189   switch (format) {
190   case MESA_FORMAT_RGBA_FLOAT32:
191      return IMAGE_FORMAT_CLASS_4X32;
192
193   case MESA_FORMAT_RGBA_FLOAT16:
194      return IMAGE_FORMAT_CLASS_4X16;
195
196   case MESA_FORMAT_RG_FLOAT32:
197      return IMAGE_FORMAT_CLASS_2X32;
198
199   case MESA_FORMAT_RG_FLOAT16:
200      return IMAGE_FORMAT_CLASS_2X16;
201
202   case MESA_FORMAT_R11G11B10_FLOAT:
203      return IMAGE_FORMAT_CLASS_10_11_11;
204
205   case MESA_FORMAT_R_FLOAT32:
206      return IMAGE_FORMAT_CLASS_1X32;
207
208   case MESA_FORMAT_R_FLOAT16:
209      return IMAGE_FORMAT_CLASS_1X16;
210
211   case MESA_FORMAT_RGBA_UINT32:
212      return IMAGE_FORMAT_CLASS_4X32;
213
214   case MESA_FORMAT_RGBA_UINT16:
215      return IMAGE_FORMAT_CLASS_4X16;
216
217   case MESA_FORMAT_R10G10B10A2_UINT:
218      return IMAGE_FORMAT_CLASS_2_10_10_10;
219
220   case MESA_FORMAT_RGBA_UINT8:
221      return IMAGE_FORMAT_CLASS_4X8;
222
223   case MESA_FORMAT_RG_UINT32:
224      return IMAGE_FORMAT_CLASS_2X32;
225
226   case MESA_FORMAT_RG_UINT16:
227      return IMAGE_FORMAT_CLASS_2X16;
228
229   case MESA_FORMAT_RG_UINT8:
230      return IMAGE_FORMAT_CLASS_2X8;
231
232   case MESA_FORMAT_R_UINT32:
233      return IMAGE_FORMAT_CLASS_1X32;
234
235   case MESA_FORMAT_R_UINT16:
236      return IMAGE_FORMAT_CLASS_1X16;
237
238   case MESA_FORMAT_R_UINT8:
239      return IMAGE_FORMAT_CLASS_1X8;
240
241   case MESA_FORMAT_RGBA_SINT32:
242      return IMAGE_FORMAT_CLASS_4X32;
243
244   case MESA_FORMAT_RGBA_SINT16:
245      return IMAGE_FORMAT_CLASS_4X16;
246
247   case MESA_FORMAT_RGBA_SINT8:
248      return IMAGE_FORMAT_CLASS_4X8;
249
250   case MESA_FORMAT_RG_SINT32:
251      return IMAGE_FORMAT_CLASS_2X32;
252
253   case MESA_FORMAT_RG_SINT16:
254      return IMAGE_FORMAT_CLASS_2X16;
255
256   case MESA_FORMAT_RG_SINT8:
257      return IMAGE_FORMAT_CLASS_2X8;
258
259   case MESA_FORMAT_R_SINT32:
260      return IMAGE_FORMAT_CLASS_1X32;
261
262   case MESA_FORMAT_R_SINT16:
263      return IMAGE_FORMAT_CLASS_1X16;
264
265   case MESA_FORMAT_R_SINT8:
266      return IMAGE_FORMAT_CLASS_1X8;
267
268   case MESA_FORMAT_RGBA_UNORM16:
269      return IMAGE_FORMAT_CLASS_4X16;
270
271   case MESA_FORMAT_R10G10B10A2_UNORM:
272      return IMAGE_FORMAT_CLASS_2_10_10_10;
273
274   case MESA_FORMAT_RGBA_UNORM8:
275      return IMAGE_FORMAT_CLASS_4X8;
276
277   case MESA_FORMAT_RG_UNORM16:
278      return IMAGE_FORMAT_CLASS_2X16;
279
280   case MESA_FORMAT_RG_UNORM8:
281      return IMAGE_FORMAT_CLASS_2X8;
282
283   case MESA_FORMAT_R_UNORM16:
284      return IMAGE_FORMAT_CLASS_1X16;
285
286   case MESA_FORMAT_R_UNORM8:
287      return IMAGE_FORMAT_CLASS_1X8;
288
289   case MESA_FORMAT_RGBA_SNORM16:
290      return IMAGE_FORMAT_CLASS_4X16;
291
292   case MESA_FORMAT_RGBA_SNORM8:
293      return IMAGE_FORMAT_CLASS_4X8;
294
295   case MESA_FORMAT_RG_SNORM16:
296      return IMAGE_FORMAT_CLASS_2X16;
297
298   case MESA_FORMAT_RG_SNORM8:
299      return IMAGE_FORMAT_CLASS_2X8;
300
301   case MESA_FORMAT_R_SNORM16:
302      return IMAGE_FORMAT_CLASS_1X16;
303
304   case MESA_FORMAT_R_SNORM8:
305      return IMAGE_FORMAT_CLASS_1X8;
306
307   default:
308      return IMAGE_FORMAT_CLASS_NONE;
309   }
310}
311
312static GLenum
313_image_format_class_to_glenum(enum image_format_class class)
314{
315   switch (class) {
316   case IMAGE_FORMAT_CLASS_NONE:
317      return GL_NONE;
318   case IMAGE_FORMAT_CLASS_1X8:
319      return GL_IMAGE_CLASS_1_X_8;
320   case IMAGE_FORMAT_CLASS_1X16:
321      return GL_IMAGE_CLASS_1_X_16;
322   case IMAGE_FORMAT_CLASS_1X32:
323      return GL_IMAGE_CLASS_1_X_32;
324   case IMAGE_FORMAT_CLASS_2X8:
325      return GL_IMAGE_CLASS_2_X_8;
326   case IMAGE_FORMAT_CLASS_2X16:
327      return GL_IMAGE_CLASS_2_X_16;
328   case IMAGE_FORMAT_CLASS_2X32:
329      return GL_IMAGE_CLASS_2_X_32;
330   case IMAGE_FORMAT_CLASS_10_11_11:
331      return GL_IMAGE_CLASS_11_11_10;
332   case IMAGE_FORMAT_CLASS_4X8:
333      return GL_IMAGE_CLASS_4_X_8;
334   case IMAGE_FORMAT_CLASS_4X16:
335      return GL_IMAGE_CLASS_4_X_16;
336   case IMAGE_FORMAT_CLASS_4X32:
337      return GL_IMAGE_CLASS_4_X_32;
338   case IMAGE_FORMAT_CLASS_2_10_10_10:
339      return GL_IMAGE_CLASS_10_10_10_2;
340   default:
341      assert(!"Invalid image_format_class");
342      return GL_NONE;
343   }
344}
345
346GLenum
347_mesa_get_image_format_class(GLenum format)
348{
349   mesa_format tex_format = _mesa_get_shader_image_format(format);
350   if (tex_format == MESA_FORMAT_NONE)
351      return GL_NONE;
352
353   enum image_format_class class = get_image_format_class(tex_format);
354   return _image_format_class_to_glenum(class);
355}
356
357bool
358_mesa_is_shader_image_format_supported(const struct gl_context *ctx,
359                                       GLenum format)
360{
361   switch (format) {
362   /* Formats supported on both desktop and ES GL, c.f. table 8.27 of the
363    * OpenGL ES 3.1 specification.
364    */
365   case GL_RGBA32F:
366   case GL_RGBA16F:
367   case GL_R32F:
368   case GL_RGBA32UI:
369   case GL_RGBA16UI:
370   case GL_RGBA8UI:
371   case GL_R32UI:
372   case GL_RGBA32I:
373   case GL_RGBA16I:
374   case GL_RGBA8I:
375   case GL_R32I:
376   case GL_RGBA8:
377   case GL_RGBA8_SNORM:
378      return true;
379
380   /* Formats supported on unextended desktop GL and the original
381    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
382    * specification or by GLES 3.1 with GL_NV_image_formats extension.
383    */
384   case GL_RG32F:
385   case GL_RG16F:
386   case GL_R11F_G11F_B10F:
387   case GL_R16F:
388   case GL_RGB10_A2UI:
389   case GL_RG32UI:
390   case GL_RG16UI:
391   case GL_RG8UI:
392   case GL_R16UI:
393   case GL_R8UI:
394   case GL_RG32I:
395   case GL_RG16I:
396   case GL_RG8I:
397   case GL_R16I:
398   case GL_R8I:
399   case GL_RGB10_A2:
400   case GL_RG8:
401   case GL_R8:
402   case GL_RG8_SNORM:
403   case GL_R8_SNORM:
404      return true;
405
406   /* Formats supported on unextended desktop GL and the original
407    * ARB_shader_image_load_store extension, c.f. table 3.21 of the OpenGL 4.2
408    * specification.
409    *
410    * Following formats are supported by GLES 3.1 with GL_NV_image_formats &
411    * GL_EXT_texture_norm16 extensions.
412    */
413   case GL_RGBA16:
414   case GL_RGBA16_SNORM:
415   case GL_RG16:
416   case GL_RG16_SNORM:
417   case GL_R16:
418   case GL_R16_SNORM:
419      return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx);
420
421   default:
422      return false;
423   }
424}
425
426struct gl_image_unit
427_mesa_default_image_unit(struct gl_context *ctx)
428{
429   const GLenum format = _mesa_is_desktop_gl(ctx) ? GL_R8 : GL_R32UI;
430   const struct gl_image_unit u = {
431      .Access = GL_READ_ONLY,
432      .Format = format,
433      ._ActualFormat = _mesa_get_shader_image_format(format)
434   };
435   return u;
436}
437
438void
439_mesa_init_image_units(struct gl_context *ctx)
440{
441   unsigned i;
442
443   ASSERT_BITFIELD_SIZE(struct gl_image_unit, Format, MESA_FORMAT_COUNT);
444
445   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
446      ctx->ImageUnits[i] = _mesa_default_image_unit(ctx);
447}
448
449
450void
451_mesa_free_image_textures(struct gl_context *ctx)
452{
453   unsigned i;
454
455   for (i = 0; i < ARRAY_SIZE(ctx->ImageUnits); ++i)
456      _mesa_reference_texobj(&ctx->ImageUnits[i].TexObj, NULL);
457}
458
459GLboolean
460_mesa_is_image_unit_valid(struct gl_context *ctx, struct gl_image_unit *u)
461{
462   struct gl_texture_object *t = u->TexObj;
463   mesa_format tex_format;
464
465   if (!t)
466      return GL_FALSE;
467
468   if (!t->_BaseComplete && !t->_MipmapComplete)
469       _mesa_test_texobj_completeness(ctx, t);
470
471   if (u->Level < t->Attrib.BaseLevel ||
472       u->Level > t->_MaxLevel ||
473       (u->Level == t->Attrib.BaseLevel && !t->_BaseComplete) ||
474       (u->Level != t->Attrib.BaseLevel && !t->_MipmapComplete))
475      return GL_FALSE;
476
477   if (_mesa_tex_target_is_layered(t->Target) &&
478       u->_Layer >= _mesa_get_texture_layers(t, u->Level))
479      return GL_FALSE;
480
481   if (t->Target == GL_TEXTURE_BUFFER) {
482      tex_format = _mesa_get_shader_image_format(t->BufferObjectFormat);
483
484   } else {
485      struct gl_texture_image *img = (t->Target == GL_TEXTURE_CUBE_MAP ?
486                                      t->Image[u->_Layer][u->Level] :
487                                      t->Image[0][u->Level]);
488
489      if (!img || img->Border || img->NumSamples > ctx->Const.MaxImageSamples)
490         return GL_FALSE;
491
492      tex_format = _mesa_get_shader_image_format(img->InternalFormat);
493   }
494
495   if (!tex_format)
496      return GL_FALSE;
497
498   switch (t->Attrib.ImageFormatCompatibilityType) {
499   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE:
500      if (_mesa_get_format_bytes(tex_format) !=
501          _mesa_get_format_bytes(u->_ActualFormat))
502         return GL_FALSE;
503      break;
504
505   case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS:
506      if (get_image_format_class(tex_format) !=
507          get_image_format_class(u->_ActualFormat))
508         return GL_FALSE;
509      break;
510
511   default:
512      assert(!"Unexpected image format compatibility type");
513   }
514
515   return GL_TRUE;
516}
517
518static GLboolean
519validate_bind_image_texture(struct gl_context *ctx, GLuint unit,
520                            GLuint texture, GLint level, GLint layer,
521                            GLenum access, GLenum format, bool check_level_layer)
522{
523   assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS);
524
525   if (unit >= ctx->Const.MaxImageUnits) {
526      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)");
527      return GL_FALSE;
528   }
529
530   if (check_level_layer) {
531      /* EXT_shader_image_load_store doesn't throw an error if level or
532       * layer is negative.
533       */
534      if (level < 0) {
535         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)");
536         return GL_FALSE;
537      }
538
539         if (layer < 0) {
540            _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)");
541            return GL_FALSE;
542      }
543   }
544
545   if (access != GL_READ_ONLY &&
546       access != GL_WRITE_ONLY &&
547       access != GL_READ_WRITE) {
548      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)");
549      return GL_FALSE;
550   }
551
552   if (!_mesa_is_shader_image_format_supported(ctx, format)) {
553      _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
554      return GL_FALSE;
555   }
556
557   return GL_TRUE;
558}
559
560static void
561set_image_binding(struct gl_image_unit *u, struct gl_texture_object *texObj,
562                  GLint level, GLboolean layered, GLint layer, GLenum access,
563                  GLenum format)
564{
565   u->Level = level;
566   u->Access = access;
567   u->Format = format;
568   u->_ActualFormat = _mesa_get_shader_image_format(format);
569
570   if (texObj && _mesa_tex_target_is_layered(texObj->Target)) {
571      u->Layered = layered;
572      u->Layer = layer;
573   } else {
574      u->Layered = GL_FALSE;
575      u->Layer = 0;
576   }
577   u->_Layer = (u->Layered ? 0 : u->Layer);
578
579   _mesa_reference_texobj(&u->TexObj, texObj);
580}
581
582static void
583bind_image_texture(struct gl_context *ctx, struct gl_texture_object *texObj,
584                   GLuint unit, GLint level, GLboolean layered, GLint layer,
585                   GLenum access, GLenum format)
586{
587   struct gl_image_unit *u;
588
589   u = &ctx->ImageUnits[unit];
590
591   FLUSH_VERTICES(ctx, 0, 0);
592   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
593
594   set_image_binding(u, texObj, level, layered, layer, access, format);
595}
596
597void GLAPIENTRY
598_mesa_BindImageTexture_no_error(GLuint unit, GLuint texture, GLint level,
599                                GLboolean layered, GLint layer, GLenum access,
600                                GLenum format)
601{
602   struct gl_texture_object *texObj = NULL;
603
604   GET_CURRENT_CONTEXT(ctx);
605
606   if (texture)
607      texObj = _mesa_lookup_texture(ctx, texture);
608
609   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
610}
611
612void GLAPIENTRY
613_mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
614                       GLboolean layered, GLint layer, GLenum access,
615                       GLenum format)
616{
617   struct gl_texture_object *texObj = NULL;
618
619   GET_CURRENT_CONTEXT(ctx);
620
621   if (!validate_bind_image_texture(ctx, unit, texture, level, layer, access,
622                                    format, true))
623      return;
624
625   if (texture) {
626      texObj = _mesa_lookup_texture(ctx, texture);
627
628      if (!texObj) {
629         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)");
630         return;
631      }
632
633      /* From section 8.22 "Texture Image Loads and Stores" of the OpenGL ES
634       * 3.1 spec:
635       *
636       * "An INVALID_OPERATION error is generated if texture is not the name
637       *  of an immutable texture object."
638       *
639       * However note that issue 7 of the GL_OES_texture_buffer spec
640       * recognizes that there is no way to create immutable buffer textures,
641       * so those are excluded from this requirement.
642       *
643       * Additionally, issue 10 of the OES_EGL_image_external_essl3 spec
644       * states that glBindImageTexture must accept external texture objects.
645       */
646      if (_mesa_is_gles(ctx) && !texObj->Immutable && !texObj->External &&
647          texObj->Target != GL_TEXTURE_BUFFER) {
648         _mesa_error(ctx, GL_INVALID_OPERATION,
649                     "glBindImageTexture(!immutable)");
650         return;
651      }
652   }
653
654   bind_image_texture(ctx, texObj, unit, level, layered, layer, access, format);
655}
656
657void GLAPIENTRY
658_mesa_BindImageTextureEXT(GLuint index, GLuint texture, GLint level,
659                          GLboolean layered, GLint layer, GLenum access,
660                          GLint format)
661{
662   struct gl_texture_object *texObj = NULL;
663
664   GET_CURRENT_CONTEXT(ctx);
665
666   if (!validate_bind_image_texture(ctx, index, texture, level, layer, access,
667                                    format, false))
668      return;
669
670   if (texture) {
671      texObj = _mesa_lookup_texture(ctx, texture);
672
673      if (!texObj) {
674         _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTextureEXT(texture)");
675         return;
676      }
677   }
678
679   bind_image_texture(ctx, texObj, index, level, layered, layer, access, format);
680}
681
682static ALWAYS_INLINE void
683bind_image_textures(struct gl_context *ctx, GLuint first, GLuint count,
684                    const GLuint *textures, bool no_error)
685{
686   int i;
687
688   /* Assume that at least one binding will be changed */
689   FLUSH_VERTICES(ctx, 0, 0);
690   ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
691
692   /* Note that the error semantics for multi-bind commands differ from
693    * those of other GL commands.
694    *
695    * The Issues section in the ARB_multi_bind spec says:
696    *
697    *    "(11) Typically, OpenGL specifies that if an error is generated by
698    *          a command, that command has no effect.  This is somewhat
699    *          unfortunate for multi-bind commands, because it would require
700    *          a first pass to scan the entire list of bound objects for
701    *          errors and then a second pass to actually perform the
702    *          bindings.  Should we have different error semantics?
703    *
704    *       RESOLVED:  Yes.  In this specification, when the parameters for
705    *       one of the <count> binding points are invalid, that binding
706    *       point is not updated and an error will be generated.  However,
707    *       other binding points in the same command will be updated if
708    *       their parameters are valid and no other error occurs."
709    */
710
711   _mesa_HashLockMutex(ctx->Shared->TexObjects);
712
713   for (i = 0; i < count; i++) {
714      struct gl_image_unit *u = &ctx->ImageUnits[first + i];
715      const GLuint texture = textures ? textures[i] : 0;
716
717      if (texture) {
718         struct gl_texture_object *texObj = u->TexObj;
719         GLenum tex_format;
720
721         if (!texObj || texObj->Name != texture) {
722            texObj = _mesa_lookup_texture_locked(ctx, texture);
723            if (!no_error && !texObj) {
724               /* The ARB_multi_bind spec says:
725                *
726                *    "An INVALID_OPERATION error is generated if any value
727                *     in <textures> is not zero or the name of an existing
728                *     texture object (per binding)."
729                */
730               _mesa_error(ctx, GL_INVALID_OPERATION,
731                           "glBindImageTextures(textures[%d]=%u "
732                           "is not zero or the name of an existing texture "
733                           "object)", i, texture);
734               continue;
735            }
736         }
737
738         if (texObj->Target == GL_TEXTURE_BUFFER) {
739            tex_format = texObj->BufferObjectFormat;
740         } else {
741            struct gl_texture_image *image = texObj->Image[0][0];
742
743            if (!no_error && (!image || image->Width == 0 ||
744                              image->Height == 0 || image->Depth == 0)) {
745               /* The ARB_multi_bind spec says:
746                *
747                *    "An INVALID_OPERATION error is generated if the width,
748                *     height, or depth of the level zero texture image of
749                *     any texture in <textures> is zero (per binding)."
750                */
751               _mesa_error(ctx, GL_INVALID_OPERATION,
752                           "glBindImageTextures(the width, height or depth "
753                           "of the level zero texture image of "
754                           "textures[%d]=%u is zero)", i, texture);
755               continue;
756            }
757
758            tex_format = image->InternalFormat;
759         }
760
761         if (!no_error &&
762             !_mesa_is_shader_image_format_supported(ctx, tex_format)) {
763            /* The ARB_multi_bind spec says:
764             *
765             *   "An INVALID_OPERATION error is generated if the internal
766             *    format of the level zero texture image of any texture
767             *    in <textures> is not found in table 8.33 (per binding)."
768             */
769            _mesa_error(ctx, GL_INVALID_OPERATION,
770                        "glBindImageTextures(the internal format %s of "
771                        "the level zero texture image of textures[%d]=%u "
772                        "is not supported)",
773                        _mesa_enum_to_string(tex_format),
774                        i, texture);
775            continue;
776         }
777
778         /* Update the texture binding */
779         set_image_binding(u, texObj, 0,
780                           _mesa_tex_target_is_layered(texObj->Target),
781                           0, GL_READ_WRITE, tex_format);
782      } else {
783         /* Unbind the texture from the unit */
784         set_image_binding(u, NULL, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
785      }
786   }
787
788   _mesa_HashUnlockMutex(ctx->Shared->TexObjects);
789}
790
791void GLAPIENTRY
792_mesa_BindImageTextures_no_error(GLuint first, GLsizei count,
793                                 const GLuint *textures)
794{
795   GET_CURRENT_CONTEXT(ctx);
796
797   bind_image_textures(ctx, first, count, textures, true);
798}
799
800void GLAPIENTRY
801_mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
802{
803   GET_CURRENT_CONTEXT(ctx);
804
805   if (!ctx->Extensions.ARB_shader_image_load_store) {
806      _mesa_error(ctx, GL_INVALID_OPERATION, "glBindImageTextures()");
807      return;
808   }
809
810   if (first + count > ctx->Const.MaxImageUnits) {
811      /* The ARB_multi_bind spec says:
812       *
813       *    "An INVALID_OPERATION error is generated if <first> + <count>
814       *     is greater than the number of image units supported by
815       *     the implementation."
816       */
817      _mesa_error(ctx, GL_INVALID_OPERATION,
818                  "glBindImageTextures(first=%u + count=%d > the value of "
819                  "GL_MAX_IMAGE_UNITS=%u)",
820                  first, count, ctx->Const.MaxImageUnits);
821      return;
822   }
823
824   bind_image_textures(ctx, first, count, textures, false);
825}
826