mesa/formatquery: Added a func to check if the <target> is supported
[mesa.git] / src / mesa / main / formatquery.c
1 /*
2 * Copyright © 2012 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
24 #include "mtypes.h"
25 #include "context.h"
26 #include "glformats.h"
27 #include "macros.h"
28 #include "enums.h"
29 #include "fbobject.h"
30 #include "formatquery.h"
31 #include "teximage.h"
32
33 /* Handles the cases where either ARB_internalformat_query or
34 * ARB_internalformat_query2 have to return an error.
35 */
36 static bool
37 _legal_parameters(struct gl_context *ctx, GLenum target, GLenum internalformat,
38 GLenum pname, GLsizei bufSize, GLint *params)
39
40 {
41 bool query2 = _mesa_has_ARB_internalformat_query2(ctx);
42
43 /* The ARB_internalformat_query2 spec says:
44 *
45 * "The INVALID_ENUM error is generated if the <target> parameter to
46 * GetInternalformati*v is not one of the targets listed in Table 6.xx.
47 */
48 switch(target){
49 case GL_TEXTURE_1D:
50 case GL_TEXTURE_1D_ARRAY:
51 case GL_TEXTURE_2D:
52 case GL_TEXTURE_2D_ARRAY:
53 case GL_TEXTURE_3D:
54 case GL_TEXTURE_CUBE_MAP:
55 case GL_TEXTURE_CUBE_MAP_ARRAY:
56 case GL_TEXTURE_RECTANGLE:
57 case GL_TEXTURE_BUFFER:
58 if (!query2) {
59 /* The ARB_internalformat_query spec says:
60 *
61 * "If the <target> parameter to GetInternalformativ is not one of
62 * TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY
63 * or RENDERBUFFER then an INVALID_ENUM error is generated.
64 */
65 _mesa_error(ctx, GL_INVALID_ENUM,
66 "glGetInternalformativ(target=%s)",
67 _mesa_enum_to_string(target));
68
69 return false;
70 }
71 break;
72
73 case GL_RENDERBUFFER:
74 break;
75
76 case GL_TEXTURE_2D_MULTISAMPLE:
77 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
78 /* The non-existence of ARB_texture_multisample is treated in
79 * ARB_internalformat_query implementation like an error.
80 */
81 if (!query2 &&
82 !(_mesa_has_ARB_texture_multisample(ctx) || _mesa_is_gles31(ctx))) {
83 _mesa_error(ctx, GL_INVALID_ENUM,
84 "glGetInternalformativ(target=%s)",
85 _mesa_enum_to_string(target));
86
87 return false;
88 }
89 break;
90
91 default:
92 _mesa_error(ctx, GL_INVALID_ENUM,
93 "glGetInternalformativ(target=%s)",
94 _mesa_enum_to_string(target));
95 return false;
96 }
97
98
99 /* The ARB_internalformat_query2 spec says:
100 *
101 * "The INVALID_ENUM error is generated if the <pname> parameter is
102 * not one of the listed possibilities.
103 */
104 switch(pname){
105 case GL_SAMPLES:
106 case GL_NUM_SAMPLE_COUNTS:
107 break;
108
109 case GL_SRGB_DECODE_ARB:
110 /* The ARB_internalformat_query2 spec says:
111 *
112 * "If ARB_texture_sRGB_decode or EXT_texture_sRGB_decode or
113 * equivalent functionality is not supported, queries for the
114 * SRGB_DECODE_ARB <pname> set the INVALID_ENUM error.
115 */
116 if (!_mesa_has_EXT_texture_sRGB_decode(ctx)) {
117 _mesa_error(ctx, GL_INVALID_ENUM,
118 "glGetInternalformativ(pname=%s)",
119 _mesa_enum_to_string(pname));
120 return false;
121 }
122 /* fallthrough */
123 case GL_INTERNALFORMAT_SUPPORTED:
124 case GL_INTERNALFORMAT_PREFERRED:
125 case GL_INTERNALFORMAT_RED_SIZE:
126 case GL_INTERNALFORMAT_GREEN_SIZE:
127 case GL_INTERNALFORMAT_BLUE_SIZE:
128 case GL_INTERNALFORMAT_ALPHA_SIZE:
129 case GL_INTERNALFORMAT_DEPTH_SIZE:
130 case GL_INTERNALFORMAT_STENCIL_SIZE:
131 case GL_INTERNALFORMAT_SHARED_SIZE:
132 case GL_INTERNALFORMAT_RED_TYPE:
133 case GL_INTERNALFORMAT_GREEN_TYPE:
134 case GL_INTERNALFORMAT_BLUE_TYPE:
135 case GL_INTERNALFORMAT_ALPHA_TYPE:
136 case GL_INTERNALFORMAT_DEPTH_TYPE:
137 case GL_INTERNALFORMAT_STENCIL_TYPE:
138 case GL_MAX_WIDTH:
139 case GL_MAX_HEIGHT:
140 case GL_MAX_DEPTH:
141 case GL_MAX_LAYERS:
142 case GL_MAX_COMBINED_DIMENSIONS:
143 case GL_COLOR_COMPONENTS:
144 case GL_DEPTH_COMPONENTS:
145 case GL_STENCIL_COMPONENTS:
146 case GL_COLOR_RENDERABLE:
147 case GL_DEPTH_RENDERABLE:
148 case GL_STENCIL_RENDERABLE:
149 case GL_FRAMEBUFFER_RENDERABLE:
150 case GL_FRAMEBUFFER_RENDERABLE_LAYERED:
151 case GL_FRAMEBUFFER_BLEND:
152 case GL_READ_PIXELS:
153 case GL_READ_PIXELS_FORMAT:
154 case GL_READ_PIXELS_TYPE:
155 case GL_TEXTURE_IMAGE_FORMAT:
156 case GL_TEXTURE_IMAGE_TYPE:
157 case GL_GET_TEXTURE_IMAGE_FORMAT:
158 case GL_GET_TEXTURE_IMAGE_TYPE:
159 case GL_MIPMAP:
160 case GL_MANUAL_GENERATE_MIPMAP:
161 case GL_AUTO_GENERATE_MIPMAP:
162 case GL_COLOR_ENCODING:
163 case GL_SRGB_READ:
164 case GL_SRGB_WRITE:
165 case GL_FILTER:
166 case GL_VERTEX_TEXTURE:
167 case GL_TESS_CONTROL_TEXTURE:
168 case GL_TESS_EVALUATION_TEXTURE:
169 case GL_GEOMETRY_TEXTURE:
170 case GL_FRAGMENT_TEXTURE:
171 case GL_COMPUTE_TEXTURE:
172 case GL_TEXTURE_SHADOW:
173 case GL_TEXTURE_GATHER:
174 case GL_TEXTURE_GATHER_SHADOW:
175 case GL_SHADER_IMAGE_LOAD:
176 case GL_SHADER_IMAGE_STORE:
177 case GL_SHADER_IMAGE_ATOMIC:
178 case GL_IMAGE_TEXEL_SIZE:
179 case GL_IMAGE_COMPATIBILITY_CLASS:
180 case GL_IMAGE_PIXEL_FORMAT:
181 case GL_IMAGE_PIXEL_TYPE:
182 case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
183 case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST:
184 case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST:
185 case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE:
186 case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE:
187 case GL_TEXTURE_COMPRESSED:
188 case GL_TEXTURE_COMPRESSED_BLOCK_WIDTH:
189 case GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT:
190 case GL_TEXTURE_COMPRESSED_BLOCK_SIZE:
191 case GL_CLEAR_BUFFER:
192 case GL_TEXTURE_VIEW:
193 case GL_VIEW_COMPATIBILITY_CLASS:
194 /* The ARB_internalformat_query spec says:
195 *
196 * "If the <pname> parameter to GetInternalformativ is not SAMPLES
197 * or NUM_SAMPLE_COUNTS, then an INVALID_ENUM error is generated."
198 */
199 if (!query2) {
200 _mesa_error(ctx, GL_INVALID_ENUM,
201 "glGetInternalformativ(pname=%s)",
202 _mesa_enum_to_string(pname));
203
204 return false;
205 }
206 break;
207
208 default:
209 _mesa_error(ctx, GL_INVALID_ENUM,
210 "glGetInternalformativ(pname=%s)",
211 _mesa_enum_to_string(pname));
212 return false;
213 }
214
215 /* The ARB_internalformat_query spec says:
216 *
217 * "If the <bufSize> parameter to GetInternalformativ is negative, then
218 * an INVALID_VALUE error is generated."
219 *
220 * Nothing is said in ARB_internalformat_query2 but we assume the same.
221 */
222 if (bufSize < 0) {
223 _mesa_error(ctx, GL_INVALID_VALUE,
224 "glGetInternalformativ(target=%s)",
225 _mesa_enum_to_string(target));
226 return false;
227 }
228
229 /* The ARB_internalformat_query spec says:
230 *
231 * "If the <internalformat> parameter to GetInternalformativ is not
232 * color-, depth- or stencil-renderable, then an INVALID_ENUM error is
233 * generated."
234 *
235 * Page 243 of the GLES 3.0.4 spec says this for GetInternalformativ:
236 *
237 * "internalformat must be color-renderable, depth-renderable or
238 * stencilrenderable (as defined in section 4.4.4)."
239 *
240 * Section 4.4.4 on page 212 of the same spec says:
241 *
242 * "An internal format is color-renderable if it is one of the
243 * formats from table 3.13 noted as color-renderable or if it
244 * is unsized format RGBA or RGB."
245 *
246 * Therefore, we must accept GL_RGB and GL_RGBA here.
247 */
248 if (!query2 &&
249 internalformat != GL_RGB && internalformat != GL_RGBA &&
250 _mesa_base_fbo_format(ctx, internalformat) == 0) {
251 _mesa_error(ctx, GL_INVALID_ENUM,
252 "glGetInternalformativ(internalformat=%s)",
253 _mesa_enum_to_string(internalformat));
254 return false;
255 }
256
257 return true;
258 }
259
260 /* Sets the appropriate "unsupported" response as defined by the
261 * ARB_internalformat_query2 spec for each each <pname>.
262 */
263 static void
264 _set_default_response(GLenum pname, GLint buffer[16])
265 {
266 /* The ARB_internalformat_query2 defines which is the reponse best
267 * representing "not supported" or "not applicable" for each <pname>.
268 *
269 * " In general:
270 * - size- or count-based queries will return zero,
271 * - support-, format- or type-based queries will return NONE,
272 * - boolean-based queries will return FALSE, and
273 * - list-based queries return no entries."
274 */
275 switch(pname) {
276 case GL_SAMPLES:
277 break;
278
279 case GL_MAX_COMBINED_DIMENSIONS:
280 case GL_NUM_SAMPLE_COUNTS:
281 case GL_INTERNALFORMAT_RED_SIZE:
282 case GL_INTERNALFORMAT_GREEN_SIZE:
283 case GL_INTERNALFORMAT_BLUE_SIZE:
284 case GL_INTERNALFORMAT_ALPHA_SIZE:
285 case GL_INTERNALFORMAT_DEPTH_SIZE:
286 case GL_INTERNALFORMAT_STENCIL_SIZE:
287 case GL_INTERNALFORMAT_SHARED_SIZE:
288 case GL_MAX_WIDTH:
289 case GL_MAX_HEIGHT:
290 case GL_MAX_DEPTH:
291 case GL_MAX_LAYERS:
292 case GL_IMAGE_TEXEL_SIZE:
293 case GL_TEXTURE_COMPRESSED_BLOCK_WIDTH:
294 case GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT:
295 case GL_TEXTURE_COMPRESSED_BLOCK_SIZE:
296 buffer[0] = 0;
297 break;
298
299 case GL_INTERNALFORMAT_PREFERRED:
300 case GL_INTERNALFORMAT_RED_TYPE:
301 case GL_INTERNALFORMAT_GREEN_TYPE:
302 case GL_INTERNALFORMAT_BLUE_TYPE:
303 case GL_INTERNALFORMAT_ALPHA_TYPE:
304 case GL_INTERNALFORMAT_DEPTH_TYPE:
305 case GL_INTERNALFORMAT_STENCIL_TYPE:
306 case GL_FRAMEBUFFER_RENDERABLE:
307 case GL_FRAMEBUFFER_RENDERABLE_LAYERED:
308 case GL_FRAMEBUFFER_BLEND:
309 case GL_READ_PIXELS:
310 case GL_READ_PIXELS_FORMAT:
311 case GL_READ_PIXELS_TYPE:
312 case GL_TEXTURE_IMAGE_FORMAT:
313 case GL_TEXTURE_IMAGE_TYPE:
314 case GL_GET_TEXTURE_IMAGE_FORMAT:
315 case GL_GET_TEXTURE_IMAGE_TYPE:
316 case GL_MANUAL_GENERATE_MIPMAP:
317 case GL_AUTO_GENERATE_MIPMAP:
318 case GL_COLOR_ENCODING:
319 case GL_SRGB_READ:
320 case GL_SRGB_WRITE:
321 case GL_SRGB_DECODE_ARB:
322 case GL_FILTER:
323 case GL_VERTEX_TEXTURE:
324 case GL_TESS_CONTROL_TEXTURE:
325 case GL_TESS_EVALUATION_TEXTURE:
326 case GL_GEOMETRY_TEXTURE:
327 case GL_FRAGMENT_TEXTURE:
328 case GL_COMPUTE_TEXTURE:
329 case GL_TEXTURE_SHADOW:
330 case GL_TEXTURE_GATHER:
331 case GL_TEXTURE_GATHER_SHADOW:
332 case GL_SHADER_IMAGE_LOAD:
333 case GL_SHADER_IMAGE_STORE:
334 case GL_SHADER_IMAGE_ATOMIC:
335 case GL_IMAGE_COMPATIBILITY_CLASS:
336 case GL_IMAGE_PIXEL_FORMAT:
337 case GL_IMAGE_PIXEL_TYPE:
338 case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
339 case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST:
340 case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST:
341 case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE:
342 case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE:
343 case GL_CLEAR_BUFFER:
344 case GL_TEXTURE_VIEW:
345 case GL_VIEW_COMPATIBILITY_CLASS:
346 buffer[0] = GL_NONE;
347 break;
348
349 case GL_INTERNALFORMAT_SUPPORTED:
350 case GL_COLOR_COMPONENTS:
351 case GL_DEPTH_COMPONENTS:
352 case GL_STENCIL_COMPONENTS:
353 case GL_COLOR_RENDERABLE:
354 case GL_DEPTH_RENDERABLE:
355 case GL_STENCIL_RENDERABLE:
356 case GL_MIPMAP:
357 case GL_TEXTURE_COMPRESSED:
358 buffer[0] = GL_FALSE;
359 break;
360
361 default:
362 unreachable("invalid 'pname'");
363 }
364 }
365
366 static bool
367 _is_target_supported(struct gl_context *ctx, GLenum target)
368 {
369 /* The ARB_internalformat_query2 spec says:
370 *
371 * "if a particular type of <target> is not supported by the
372 * implementation the "unsupported" answer should be given.
373 * This is not an error."
374 */
375 switch(target){
376 case GL_TEXTURE_2D:
377 case GL_TEXTURE_3D:
378 break;
379
380 case GL_TEXTURE_1D:
381 if (!_mesa_is_desktop_gl(ctx))
382 return false;
383 break;
384
385 case GL_TEXTURE_1D_ARRAY:
386 if (!_mesa_has_EXT_texture_array(ctx))
387 return false;
388 break;
389
390 case GL_TEXTURE_2D_ARRAY:
391 if (!(_mesa_has_EXT_texture_array(ctx) || _mesa_is_gles3(ctx)))
392 return false;
393 break;
394
395 case GL_TEXTURE_CUBE_MAP:
396 if (!_mesa_has_ARB_texture_cube_map(ctx))
397 return false;
398 break;
399
400 case GL_TEXTURE_CUBE_MAP_ARRAY:
401 if (!_mesa_has_ARB_texture_cube_map_array(ctx))
402 return false;
403 break;
404
405 case GL_TEXTURE_RECTANGLE:
406 if (!_mesa_has_NV_texture_rectangle(ctx))
407 return false;
408 break;
409
410 case GL_TEXTURE_BUFFER:
411 if (!_mesa_has_ARB_texture_buffer_object(ctx))
412 return false;
413 break;
414
415 case GL_RENDERBUFFER:
416 if (!(_mesa_has_ARB_framebuffer_object(ctx) ||
417 _mesa_is_gles3(ctx)))
418 return false;
419 break;
420
421 case GL_TEXTURE_2D_MULTISAMPLE:
422 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
423 if (!(_mesa_has_ARB_texture_multisample(ctx) ||
424 _mesa_is_gles31(ctx)))
425 return false;
426 break;
427
428 default:
429 unreachable("invalid target");
430 }
431
432 return true;
433 }
434
435 /* default implementation of QueryInternalFormat driverfunc, for
436 * drivers not implementing ARB_internalformat_query2.
437 */
438 void
439 _mesa_query_internal_format_default(struct gl_context *ctx, GLenum target,
440 GLenum internalFormat, GLenum pname,
441 GLint *params)
442 {
443 (void) ctx;
444 (void) target;
445 (void) internalFormat;
446
447 switch (pname) {
448 case GL_SAMPLES:
449 case GL_NUM_SAMPLE_COUNTS:
450 params[0] = 1;
451 break;
452 default:
453 /* @TODO: handle default values for all the different pnames. */
454 break;
455 }
456 }
457
458 void GLAPIENTRY
459 _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,
460 GLsizei bufSize, GLint *params)
461 {
462 GLint buffer[16];
463 GET_CURRENT_CONTEXT(ctx);
464
465 ASSERT_OUTSIDE_BEGIN_END(ctx);
466
467 if (!ctx->Extensions.ARB_internalformat_query) {
468 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInternalformativ");
469 return;
470 }
471
472 assert(ctx->Driver.QueryInternalFormat != NULL);
473
474 /* The ARB_internalformat_query spec says:
475 *
476 * "If the <target> parameter to GetInternalformativ is not one of
477 * TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY or RENDERBUFFER
478 * then an INVALID_ENUM error is generated."
479 */
480 switch (target) {
481 case GL_RENDERBUFFER:
482 break;
483
484 case GL_TEXTURE_2D_MULTISAMPLE:
485 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
486 /* These enums are only valid if ARB_texture_multisample is supported */
487 if ((_mesa_is_desktop_gl(ctx) &&
488 ctx->Extensions.ARB_texture_multisample) ||
489 _mesa_is_gles31(ctx))
490 break;
491
492 default:
493 _mesa_error(ctx, GL_INVALID_ENUM,
494 "glGetInternalformativ(target=%s)",
495 _mesa_enum_to_string(target));
496 return;
497 }
498
499 /* The ARB_internalformat_query spec says:
500 *
501 * "If the <internalformat> parameter to GetInternalformativ is not
502 * color-, depth- or stencil-renderable, then an INVALID_ENUM error is
503 * generated."
504 *
505 * Page 243 of the GLES 3.0.4 spec says this for GetInternalformativ:
506 *
507 * "internalformat must be color-renderable, depth-renderable or
508 * stencilrenderable (as defined in section 4.4.4)."
509 *
510 * Section 4.4.4 on page 212 of the same spec says:
511 *
512 * "An internal format is color-renderable if it is one of the
513 * formats from table 3.13 noted as color-renderable or if it
514 * is unsized format RGBA or RGB."
515 *
516 * Therefore, we must accept GL_RGB and GL_RGBA here.
517 */
518 if (internalformat != GL_RGB && internalformat != GL_RGBA &&
519 _mesa_base_fbo_format(ctx, internalformat) == 0) {
520 _mesa_error(ctx, GL_INVALID_ENUM,
521 "glGetInternalformativ(internalformat=%s)",
522 _mesa_enum_to_string(internalformat));
523 return;
524 }
525
526 /* The ARB_internalformat_query spec says:
527 *
528 * "If the <bufSize> parameter to GetInternalformativ is negative, then
529 * an INVALID_VALUE error is generated."
530 */
531 if (bufSize < 0) {
532 _mesa_error(ctx, GL_INVALID_VALUE,
533 "glGetInternalformativ(target=%s)",
534 _mesa_enum_to_string(target));
535 return;
536 }
537
538 /* initialize the contents of the temporary buffer */
539 memcpy(buffer, params, MIN2(bufSize, 16) * sizeof(GLint));
540
541 switch (pname) {
542 case GL_SAMPLES:
543 ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
544 buffer);
545 break;
546 case GL_NUM_SAMPLE_COUNTS: {
547 if ((ctx->API == API_OPENGLES2 && ctx->Version == 30) &&
548 _mesa_is_enum_format_integer(internalformat)) {
549 /* From GL ES 3.0 specification, section 6.1.15 page 236: "Since
550 * multisampling is not supported for signed and unsigned integer
551 * internal formats, the value of NUM_SAMPLE_COUNTS will be zero
552 * for such formats.
553 *
554 * Such a restriction no longer exists in GL ES 3.1.
555 */
556 buffer[0] = 0;
557 } else {
558 ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
559 buffer);
560 }
561 break;
562 }
563 default:
564 _mesa_error(ctx, GL_INVALID_ENUM,
565 "glGetInternalformativ(pname=%s)",
566 _mesa_enum_to_string(pname));
567 return;
568 }
569
570 if (bufSize != 0 && params == NULL) {
571 /* Emit a warning to aid application debugging, but go ahead and do the
572 * memcpy (and probably crash) anyway.
573 */
574 _mesa_warning(ctx,
575 "glGetInternalformativ(bufSize = %d, but params = NULL)",
576 bufSize);
577 }
578
579 /* Copy the data from the temporary buffer to the buffer supplied by the
580 * application. Clamp the size of the copy to the size supplied by the
581 * application.
582 */
583 memcpy(params, buffer, MIN2(bufSize, 16) * sizeof(GLint));
584
585 return;
586 }