f77f2c6c2bad45085f2c5b727a325a26b275e02a
[mesa.git] / src / mesa / main / shaderimage.c
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 "context.h"
34 #include "texobj.h"
35 #include "teximage.h"
36
37 /*
38 * Define endian-invariant aliases for some mesa formats that are
39 * defined in terms of their channel layout from LSB to MSB in a
40 * 32-bit word. The actual byte offsets matter here because the user
41 * is allowed to bit-cast one format into another and get predictable
42 * results.
43 */
44 #ifdef MESA_BIG_ENDIAN
45 # define MESA_FORMAT_RGBA_8 MESA_FORMAT_A8B8G8R8_UNORM
46 # define MESA_FORMAT_RG_16 MESA_FORMAT_G16R16_UNORM
47 # define MESA_FORMAT_RG_8 MESA_FORMAT_G8R8_UNORM
48 # define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_A8B8G8R8_SNORM
49 # define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_G16R16_SNORM
50 # define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_G8R8_SNORM
51 #else
52 # define MESA_FORMAT_RGBA_8 MESA_FORMAT_R8G8B8A8_UNORM
53 # define MESA_FORMAT_RG_16 MESA_FORMAT_R16G16_UNORM
54 # define MESA_FORMAT_RG_8 MESA_FORMAT_R8G8_UNORM
55 # define MESA_FORMAT_SIGNED_RGBA_8 MESA_FORMAT_R8G8B8A8_SNORM
56 # define MESA_FORMAT_SIGNED_RG_16 MESA_FORMAT_R16G16_SNORM
57 # define MESA_FORMAT_SIGNED_RG_8 MESA_FORMAT_R8G8_SNORM
58 #endif
59
60 static mesa_format
61 get_image_format(GLenum format)
62 {
63 switch (format) {
64 case GL_RGBA32F:
65 return MESA_FORMAT_RGBA_FLOAT32;
66
67 case GL_RGBA16F:
68 return MESA_FORMAT_RGBA_FLOAT16;
69
70 case GL_RG32F:
71 return MESA_FORMAT_RG_FLOAT32;
72
73 case GL_RG16F:
74 return MESA_FORMAT_RG_FLOAT16;
75
76 case GL_R11F_G11F_B10F:
77 return MESA_FORMAT_R11G11B10_FLOAT;
78
79 case GL_R32F:
80 return MESA_FORMAT_R_FLOAT32;
81
82 case GL_R16F:
83 return MESA_FORMAT_R_FLOAT16;
84
85 case GL_RGBA32UI:
86 return MESA_FORMAT_RGBA_UINT32;
87
88 case GL_RGBA16UI:
89 return MESA_FORMAT_RGBA_UINT16;
90
91 case GL_RGB10_A2UI:
92 return MESA_FORMAT_R10G10B10A2_UINT;
93
94 case GL_RGBA8UI:
95 return MESA_FORMAT_RGBA_UINT8;
96
97 case GL_RG32UI:
98 return MESA_FORMAT_RG_UINT32;
99
100 case GL_RG16UI:
101 return MESA_FORMAT_RG_UINT16;
102
103 case GL_RG8UI:
104 return MESA_FORMAT_RG_UINT8;
105
106 case GL_R32UI:
107 return MESA_FORMAT_R_UINT32;
108
109 case GL_R16UI:
110 return MESA_FORMAT_R_UINT16;
111
112 case GL_R8UI:
113 return MESA_FORMAT_R_UINT8;
114
115 case GL_RGBA32I:
116 return MESA_FORMAT_RGBA_SINT32;
117
118 case GL_RGBA16I:
119 return MESA_FORMAT_RGBA_SINT16;
120
121 case GL_RGBA8I:
122 return MESA_FORMAT_RGBA_SINT8;
123
124 case GL_RG32I:
125 return MESA_FORMAT_RG_SINT32;
126
127 case GL_RG16I:
128 return MESA_FORMAT_RG_SINT16;
129
130 case GL_RG8I:
131 return MESA_FORMAT_RG_SINT8;
132
133 case GL_R32I:
134 return MESA_FORMAT_R_SINT32;
135
136 case GL_R16I:
137 return MESA_FORMAT_R_SINT16;
138
139 case GL_R8I:
140 return MESA_FORMAT_R_SINT8;
141
142 case GL_RGBA16:
143 return MESA_FORMAT_RGBA_UNORM16;
144
145 case GL_RGB10_A2:
146 return MESA_FORMAT_R10G10B10A2_UNORM;
147
148 case GL_RGBA8:
149 return MESA_FORMAT_RGBA_8;
150
151 case GL_RG16:
152 return MESA_FORMAT_RG_16;
153
154 case GL_RG8:
155 return MESA_FORMAT_RG_8;
156
157 case GL_R16:
158 return MESA_FORMAT_R_UNORM16;
159
160 case GL_R8:
161 return MESA_FORMAT_R_UNORM8;
162
163 case GL_RGBA16_SNORM:
164 return MESA_FORMAT_RGBA_SNORM16;
165
166 case GL_RGBA8_SNORM:
167 return MESA_FORMAT_SIGNED_RGBA_8;
168
169 case GL_RG16_SNORM:
170 return MESA_FORMAT_SIGNED_RG_16;
171
172 case GL_RG8_SNORM:
173 return MESA_FORMAT_SIGNED_RG_8;
174
175 case GL_R16_SNORM:
176 return MESA_FORMAT_R_SNORM16;
177
178 case GL_R8_SNORM:
179 return MESA_FORMAT_R_SNORM8;
180
181 default:
182 return MESA_FORMAT_NONE;
183 }
184 }
185
186 enum image_format_class
187 {
188 /** Not a valid image format. */
189 IMAGE_FORMAT_CLASS_NONE = 0,
190
191 /** Classes of image formats you can cast into each other. */
192 /** \{ */
193 IMAGE_FORMAT_CLASS_1X8,
194 IMAGE_FORMAT_CLASS_1X16,
195 IMAGE_FORMAT_CLASS_1X32,
196 IMAGE_FORMAT_CLASS_2X8,
197 IMAGE_FORMAT_CLASS_2X16,
198 IMAGE_FORMAT_CLASS_2X32,
199 IMAGE_FORMAT_CLASS_10_11_11,
200 IMAGE_FORMAT_CLASS_4X8,
201 IMAGE_FORMAT_CLASS_4X16,
202 IMAGE_FORMAT_CLASS_4X32,
203 IMAGE_FORMAT_CLASS_2_10_10_10
204 /** \} */
205 };
206
207 static enum image_format_class
208 get_image_format_class(mesa_format format)
209 {
210 switch (format) {
211 case MESA_FORMAT_RGBA_FLOAT32:
212 return IMAGE_FORMAT_CLASS_4X32;
213
214 case MESA_FORMAT_RGBA_FLOAT16:
215 return IMAGE_FORMAT_CLASS_4X16;
216
217 case MESA_FORMAT_RG_FLOAT32:
218 return IMAGE_FORMAT_CLASS_2X32;
219
220 case MESA_FORMAT_RG_FLOAT16:
221 return IMAGE_FORMAT_CLASS_2X16;
222
223 case MESA_FORMAT_R11G11B10_FLOAT:
224 return IMAGE_FORMAT_CLASS_10_11_11;
225
226 case MESA_FORMAT_R_FLOAT32:
227 return IMAGE_FORMAT_CLASS_1X32;
228
229 case MESA_FORMAT_R_FLOAT16:
230 return IMAGE_FORMAT_CLASS_1X16;
231
232 case MESA_FORMAT_RGBA_UINT32:
233 return IMAGE_FORMAT_CLASS_4X32;
234
235 case MESA_FORMAT_RGBA_UINT16:
236 return IMAGE_FORMAT_CLASS_4X16;
237
238 case MESA_FORMAT_R10G10B10A2_UINT:
239 return IMAGE_FORMAT_CLASS_2_10_10_10;
240
241 case MESA_FORMAT_RGBA_UINT8:
242 return IMAGE_FORMAT_CLASS_4X8;
243
244 case MESA_FORMAT_RG_UINT32:
245 return IMAGE_FORMAT_CLASS_2X32;
246
247 case MESA_FORMAT_RG_UINT16:
248 return IMAGE_FORMAT_CLASS_2X16;
249
250 case MESA_FORMAT_RG_UINT8:
251 return IMAGE_FORMAT_CLASS_2X8;
252
253 case MESA_FORMAT_R_UINT32:
254 return IMAGE_FORMAT_CLASS_1X32;
255
256 case MESA_FORMAT_R_UINT16:
257 return IMAGE_FORMAT_CLASS_1X16;
258
259 case MESA_FORMAT_R_UINT8:
260 return IMAGE_FORMAT_CLASS_1X8;
261
262 case MESA_FORMAT_RGBA_SINT32:
263 return IMAGE_FORMAT_CLASS_4X32;
264
265 case MESA_FORMAT_RGBA_SINT16:
266 return IMAGE_FORMAT_CLASS_4X16;
267
268 case MESA_FORMAT_RGBA_SINT8:
269 return IMAGE_FORMAT_CLASS_4X8;
270
271 case MESA_FORMAT_RG_SINT32:
272 return IMAGE_FORMAT_CLASS_2X32;
273
274 case MESA_FORMAT_RG_SINT16:
275 return IMAGE_FORMAT_CLASS_2X16;
276
277 case MESA_FORMAT_RG_SINT8:
278 return IMAGE_FORMAT_CLASS_2X8;
279
280 case MESA_FORMAT_R_SINT32:
281 return IMAGE_FORMAT_CLASS_1X32;
282
283 case MESA_FORMAT_R_SINT16:
284 return IMAGE_FORMAT_CLASS_1X16;
285
286 case MESA_FORMAT_R_SINT8:
287 return IMAGE_FORMAT_CLASS_1X8;
288
289 case MESA_FORMAT_RGBA_UNORM16:
290 return IMAGE_FORMAT_CLASS_4X16;
291
292 case MESA_FORMAT_R10G10B10A2_UNORM:
293 return IMAGE_FORMAT_CLASS_2_10_10_10;
294
295 case MESA_FORMAT_RGBA_8:
296 return IMAGE_FORMAT_CLASS_4X8;
297
298 case MESA_FORMAT_RG_16:
299 return IMAGE_FORMAT_CLASS_2X16;
300
301 case MESA_FORMAT_RG_8:
302 return IMAGE_FORMAT_CLASS_2X8;
303
304 case MESA_FORMAT_R_UNORM16:
305 return IMAGE_FORMAT_CLASS_1X16;
306
307 case MESA_FORMAT_R_UNORM8:
308 return IMAGE_FORMAT_CLASS_1X8;
309
310 case MESA_FORMAT_RGBA_SNORM16:
311 return IMAGE_FORMAT_CLASS_4X16;
312
313 case MESA_FORMAT_SIGNED_RGBA_8:
314 return IMAGE_FORMAT_CLASS_4X8;
315
316 case MESA_FORMAT_SIGNED_RG_16:
317 return IMAGE_FORMAT_CLASS_2X16;
318
319 case MESA_FORMAT_SIGNED_RG_8:
320 return IMAGE_FORMAT_CLASS_2X8;
321
322 case MESA_FORMAT_R_SNORM16:
323 return IMAGE_FORMAT_CLASS_1X16;
324
325 case MESA_FORMAT_R_SNORM8:
326 return IMAGE_FORMAT_CLASS_1X8;
327
328 default:
329 return IMAGE_FORMAT_CLASS_NONE;
330 }
331 }
332
333 static GLboolean
334 validate_image_unit(struct gl_context *ctx, struct gl_image_unit *u)
335 {
336 struct gl_texture_object *t = u->TexObj;
337 struct gl_texture_image *img;
338
339 if (!t || u->Level < t->BaseLevel ||
340 u->Level > t->_MaxLevel)
341 return GL_FALSE;
342
343 _mesa_test_texobj_completeness(ctx, t);
344
345 if ((u->Level == t->BaseLevel && !t->_BaseComplete) ||
346 (u->Level != t->BaseLevel && !t->_MipmapComplete))
347 return GL_FALSE;
348
349 if (_mesa_tex_target_is_layered(t->Target) &&
350 u->Layer >= _mesa_get_texture_layers(t, u->Level))
351 return GL_FALSE;
352
353 if (t->Target == GL_TEXTURE_CUBE_MAP)
354 img = t->Image[u->Layer][u->Level];
355 else
356 img = t->Image[0][u->Level];
357
358 if (!img || img->Border ||
359 get_image_format_class(img->TexFormat) == IMAGE_FORMAT_CLASS_NONE ||
360 img->NumSamples > ctx->Const.MaxImageSamples)
361 return GL_FALSE;
362
363 switch (t->ImageFormatCompatibilityType) {
364 case GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE:
365 if (_mesa_get_format_bytes(img->TexFormat) !=
366 _mesa_get_format_bytes(u->_ActualFormat))
367 return GL_FALSE;
368 break;
369
370 case GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS:
371 if (get_image_format_class(img->TexFormat) !=
372 get_image_format_class(u->_ActualFormat))
373 return GL_FALSE;
374 break;
375
376 default:
377 assert(!"Unexpected image format compatibility type");
378 }
379
380 return GL_TRUE;
381 }
382
383 void
384 _mesa_validate_image_units(struct gl_context *ctx)
385 {
386 int i;
387
388 for (i = 0; i < ctx->Const.MaxImageUnits; ++i) {
389 struct gl_image_unit *u = &ctx->ImageUnits[i];
390 u->_Valid = validate_image_unit(ctx, u);
391 }
392 }
393
394 static GLboolean
395 validate_bind_image_texture(struct gl_context *ctx, GLuint unit,
396 GLuint texture, GLint level, GLboolean layered,
397 GLint layer, GLenum access, GLenum format)
398 {
399 assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS);
400
401 if (unit >= ctx->Const.MaxImageUnits) {
402 _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)");
403 return GL_FALSE;
404 }
405
406 if (level < 0) {
407 _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)");
408 return GL_FALSE;
409 }
410
411 if (layer < 0) {
412 _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)");
413 return GL_FALSE;
414 }
415
416 if (access != GL_READ_ONLY &&
417 access != GL_WRITE_ONLY &&
418 access != GL_READ_WRITE) {
419 _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)");
420 return GL_FALSE;
421 }
422
423 if (!get_image_format(format)) {
424 _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)");
425 return GL_FALSE;
426 }
427
428 return GL_TRUE;
429 }
430
431 void GLAPIENTRY
432 _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level,
433 GLboolean layered, GLint layer, GLenum access,
434 GLenum format)
435 {
436 GET_CURRENT_CONTEXT(ctx);
437 struct gl_texture_object *t = NULL;
438 struct gl_image_unit *u;
439
440 if (!validate_bind_image_texture(ctx, unit, texture, level,
441 layered, layer, access, format))
442 return;
443
444 u = &ctx->ImageUnits[unit];
445
446 FLUSH_VERTICES(ctx, 0);
447 ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits;
448
449 if (texture) {
450 t = _mesa_lookup_texture(ctx, texture);
451 if (!t) {
452 _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)");
453 return;
454 }
455
456 _mesa_reference_texobj(&u->TexObj, t);
457 u->Level = level;
458 u->Access = access;
459 u->Format = format;
460 u->_ActualFormat = get_image_format(format);
461
462 if (_mesa_tex_target_is_layered(t->Target)) {
463 u->Layered = layered;
464 u->Layer = (layered ? 0 : layer);
465 } else {
466 u->Layered = GL_FALSE;
467 u->Layer = 0;
468 }
469
470 } else {
471 _mesa_reference_texobj(&u->TexObj, NULL);
472 }
473
474 u->_Valid = validate_image_unit(ctx, u);
475
476 if (ctx->Driver.BindImageTexture)
477 ctx->Driver.BindImageTexture(ctx, u, t, level, layered,
478 layer, access, format);
479 }
480
481 void GLAPIENTRY
482 _mesa_BindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
483 {
484 }
485
486 void GLAPIENTRY
487 _mesa_MemoryBarrier(GLbitfield barriers)
488 {
489 GET_CURRENT_CONTEXT(ctx);
490
491 if (ctx->Driver.MemoryBarrier)
492 ctx->Driver.MemoryBarrier(ctx, barriers);
493 }