mesa: return NULL if we exceed MaxColorAttachments in get_fb_attachment
[mesa.git] / src / mesa / main / fbobject.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /*
28 * GL_EXT/ARB_framebuffer_object extensions
29 *
30 * Authors:
31 * Brian Paul
32 */
33
34 #include <stdbool.h>
35
36 #include "buffers.h"
37 #include "context.h"
38 #include "debug_output.h"
39 #include "enums.h"
40 #include "fbobject.h"
41 #include "formats.h"
42 #include "framebuffer.h"
43 #include "glformats.h"
44 #include "hash.h"
45 #include "macros.h"
46 #include "multisample.h"
47 #include "mtypes.h"
48 #include "renderbuffer.h"
49 #include "state.h"
50 #include "teximage.h"
51 #include "texobj.h"
52
53
54 /**
55 * Notes:
56 *
57 * None of the GL_EXT_framebuffer_object functions are compiled into
58 * display lists.
59 */
60
61
62
63 /*
64 * When glGenRender/FramebuffersEXT() is called we insert pointers to
65 * these placeholder objects into the hash table.
66 * Later, when the object ID is first bound, we replace the placeholder
67 * with the real frame/renderbuffer.
68 */
69 static struct gl_framebuffer DummyFramebuffer;
70 static struct gl_renderbuffer DummyRenderbuffer;
71
72 /* We bind this framebuffer when applications pass a NULL
73 * drawable/surface in make current. */
74 static struct gl_framebuffer IncompleteFramebuffer;
75
76
77 static void
78 delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
79 {
80 /* no op */
81 }
82
83 static void
84 delete_dummy_framebuffer(struct gl_framebuffer *fb)
85 {
86 /* no op */
87 }
88
89
90 void
91 _mesa_init_fbobjects(struct gl_context *ctx)
92 {
93 simple_mtx_init(&DummyFramebuffer.Mutex, mtx_plain);
94 simple_mtx_init(&DummyRenderbuffer.Mutex, mtx_plain);
95 simple_mtx_init(&IncompleteFramebuffer.Mutex, mtx_plain);
96 DummyFramebuffer.Delete = delete_dummy_framebuffer;
97 DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
98 IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
99 }
100
101 struct gl_framebuffer *
102 _mesa_get_incomplete_framebuffer(void)
103 {
104 return &IncompleteFramebuffer;
105 }
106
107 /**
108 * Helper routine for getting a gl_renderbuffer.
109 */
110 struct gl_renderbuffer *
111 _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
112 {
113 struct gl_renderbuffer *rb;
114
115 if (id == 0)
116 return NULL;
117
118 rb = (struct gl_renderbuffer *)
119 _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
120 return rb;
121 }
122
123
124 /**
125 * A convenience function for direct state access that throws
126 * GL_INVALID_OPERATION if the renderbuffer doesn't exist.
127 */
128 struct gl_renderbuffer *
129 _mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
130 const char *func)
131 {
132 struct gl_renderbuffer *rb;
133
134 rb = _mesa_lookup_renderbuffer(ctx, id);
135 if (!rb || rb == &DummyRenderbuffer) {
136 _mesa_error(ctx, GL_INVALID_OPERATION,
137 "%s(non-existent renderbuffer %u)", func, id);
138 return NULL;
139 }
140
141 return rb;
142 }
143
144
145 /**
146 * Helper routine for getting a gl_framebuffer.
147 */
148 struct gl_framebuffer *
149 _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
150 {
151 struct gl_framebuffer *fb;
152
153 if (id == 0)
154 return NULL;
155
156 fb = (struct gl_framebuffer *)
157 _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
158 return fb;
159 }
160
161
162 /**
163 * A convenience function for direct state access that throws
164 * GL_INVALID_OPERATION if the framebuffer doesn't exist.
165 */
166 struct gl_framebuffer *
167 _mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
168 const char *func)
169 {
170 struct gl_framebuffer *fb;
171
172 fb = _mesa_lookup_framebuffer(ctx, id);
173 if (!fb || fb == &DummyFramebuffer) {
174 _mesa_error(ctx, GL_INVALID_OPERATION,
175 "%s(non-existent framebuffer %u)", func, id);
176 return NULL;
177 }
178
179 return fb;
180 }
181
182
183 /**
184 * Mark the given framebuffer as invalid. This will force the
185 * test for framebuffer completeness to be done before the framebuffer
186 * is used.
187 */
188 static void
189 invalidate_framebuffer(struct gl_framebuffer *fb)
190 {
191 fb->_Status = 0; /* "indeterminate" */
192 }
193
194
195 /**
196 * Return the gl_framebuffer object which corresponds to the given
197 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
198 * Check support for GL_EXT_framebuffer_blit to determine if certain
199 * targets are legal.
200 * \return gl_framebuffer pointer or NULL if target is illegal
201 */
202 static struct gl_framebuffer *
203 get_framebuffer_target(struct gl_context *ctx, GLenum target)
204 {
205 bool have_fb_blit = _mesa_is_gles3(ctx) || _mesa_is_desktop_gl(ctx);
206 switch (target) {
207 case GL_DRAW_FRAMEBUFFER:
208 return have_fb_blit ? ctx->DrawBuffer : NULL;
209 case GL_READ_FRAMEBUFFER:
210 return have_fb_blit ? ctx->ReadBuffer : NULL;
211 case GL_FRAMEBUFFER_EXT:
212 return ctx->DrawBuffer;
213 default:
214 return NULL;
215 }
216 }
217
218
219 /**
220 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
221 * gl_renderbuffer_attachment object.
222 * This function is only used for user-created FB objects, not the
223 * default / window-system FB object.
224 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
225 * the depth buffer attachment point.
226 * Returns if the attachment is a GL_COLOR_ATTACHMENTm_EXT on
227 * is_color_attachment, because several callers would return different errors
228 * if they don't find the attachment.
229 */
230 static struct gl_renderbuffer_attachment *
231 get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
232 GLenum attachment, bool *is_color_attachment)
233 {
234 GLuint i;
235
236 assert(_mesa_is_user_fbo(fb));
237
238 if (is_color_attachment)
239 *is_color_attachment = false;
240
241 switch (attachment) {
242 case GL_COLOR_ATTACHMENT0_EXT:
243 case GL_COLOR_ATTACHMENT1_EXT:
244 case GL_COLOR_ATTACHMENT2_EXT:
245 case GL_COLOR_ATTACHMENT3_EXT:
246 case GL_COLOR_ATTACHMENT4_EXT:
247 case GL_COLOR_ATTACHMENT5_EXT:
248 case GL_COLOR_ATTACHMENT6_EXT:
249 case GL_COLOR_ATTACHMENT7_EXT:
250 case GL_COLOR_ATTACHMENT8_EXT:
251 case GL_COLOR_ATTACHMENT9_EXT:
252 case GL_COLOR_ATTACHMENT10_EXT:
253 case GL_COLOR_ATTACHMENT11_EXT:
254 case GL_COLOR_ATTACHMENT12_EXT:
255 case GL_COLOR_ATTACHMENT13_EXT:
256 case GL_COLOR_ATTACHMENT14_EXT:
257 case GL_COLOR_ATTACHMENT15_EXT:
258 if (is_color_attachment)
259 *is_color_attachment = true;
260 /* Only OpenGL ES 1.x forbids color attachments other than
261 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the
262 * hardware is used.
263 */
264 i = attachment - GL_COLOR_ATTACHMENT0_EXT;
265 if (i >= ctx->Const.MaxColorAttachments
266 || (i > 0 && ctx->API == API_OPENGLES)) {
267 return NULL;
268 }
269 return &fb->Attachment[BUFFER_COLOR0 + i];
270 case GL_DEPTH_STENCIL_ATTACHMENT:
271 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
272 return NULL;
273 /* fall-through */
274 case GL_DEPTH_ATTACHMENT_EXT:
275 return &fb->Attachment[BUFFER_DEPTH];
276 case GL_STENCIL_ATTACHMENT_EXT:
277 return &fb->Attachment[BUFFER_STENCIL];
278 default:
279 return NULL;
280 }
281 }
282
283
284 /**
285 * As above, but only used for getting attachments of the default /
286 * window-system framebuffer (not user-created framebuffer objects).
287 */
288 static struct gl_renderbuffer_attachment *
289 get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
290 GLenum attachment)
291 {
292 assert(_mesa_is_winsys_fbo(fb));
293
294 if (_mesa_is_gles3(ctx)) {
295 assert(attachment == GL_BACK ||
296 attachment == GL_DEPTH ||
297 attachment == GL_STENCIL);
298 switch (attachment) {
299 case GL_BACK:
300 /* Since there is no stereo rendering in ES 3.0, only return the
301 * LEFT bits.
302 */
303 if (ctx->DrawBuffer->Visual.doubleBufferMode)
304 return &fb->Attachment[BUFFER_BACK_LEFT];
305 return &fb->Attachment[BUFFER_FRONT_LEFT];
306 case GL_DEPTH:
307 return &fb->Attachment[BUFFER_DEPTH];
308 case GL_STENCIL:
309 return &fb->Attachment[BUFFER_STENCIL];
310 }
311 }
312
313 switch (attachment) {
314 case GL_FRONT_LEFT:
315 /* Front buffers can be allocated on the first use, but
316 * glGetFramebufferAttachmentParameteriv must work even if that
317 * allocation hasn't happened yet. In such case, use the back buffer,
318 * which should be the same.
319 */
320 if (fb->Attachment[BUFFER_FRONT_LEFT].Type == GL_NONE)
321 return &fb->Attachment[BUFFER_BACK_LEFT];
322 else
323 return &fb->Attachment[BUFFER_FRONT_LEFT];
324 case GL_FRONT_RIGHT:
325 /* Same as above. */
326 if (fb->Attachment[BUFFER_FRONT_RIGHT].Type == GL_NONE)
327 return &fb->Attachment[BUFFER_BACK_RIGHT];
328 else
329 return &fb->Attachment[BUFFER_FRONT_RIGHT];
330 case GL_BACK_LEFT:
331 return &fb->Attachment[BUFFER_BACK_LEFT];
332 case GL_BACK_RIGHT:
333 return &fb->Attachment[BUFFER_BACK_RIGHT];
334 case GL_BACK:
335 /* The ARB_ES3_1_compatibility spec says:
336 *
337 * "Since this command can only query a single framebuffer
338 * attachment, BACK is equivalent to BACK_LEFT."
339 */
340 if (ctx->Extensions.ARB_ES3_1_compatibility)
341 return &fb->Attachment[BUFFER_BACK_LEFT];
342 return NULL;
343 case GL_AUX0:
344 if (fb->Visual.numAuxBuffers == 1) {
345 return &fb->Attachment[BUFFER_AUX0];
346 }
347 return NULL;
348
349 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
350 *
351 * "If the default framebuffer is bound to target, then attachment must
352 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
353 * identifying a color buffer; DEPTH, identifying the depth buffer; or
354 * STENCIL, identifying the stencil buffer."
355 *
356 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
357 * language. However, revision #33 of the ARB_framebuffer_object spec
358 * says:
359 *
360 * "If the default framebuffer is bound to <target>, then <attachment>
361 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
362 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
363 * depth buffer, or the stencil buffer, and <pname> may be
364 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
365 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
366 *
367 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
368 * from glext.h, so shipping apps should not use those values.
369 *
370 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
371 * support queries of the window system FBO.
372 */
373 case GL_DEPTH:
374 return &fb->Attachment[BUFFER_DEPTH];
375 case GL_STENCIL:
376 return &fb->Attachment[BUFFER_STENCIL];
377 default:
378 return NULL;
379 }
380 }
381
382
383
384 /**
385 * Remove any texture or renderbuffer attached to the given attachment
386 * point. Update reference counts, etc.
387 */
388 static void
389 remove_attachment(struct gl_context *ctx,
390 struct gl_renderbuffer_attachment *att)
391 {
392 struct gl_renderbuffer *rb = att->Renderbuffer;
393
394 /* tell driver that we're done rendering to this texture. */
395 if (rb && rb->NeedsFinishRenderTexture)
396 ctx->Driver.FinishRenderTexture(ctx, rb);
397
398 if (att->Type == GL_TEXTURE) {
399 assert(att->Texture);
400 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
401 assert(!att->Texture);
402 }
403 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
404 assert(!att->Texture);
405 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
406 assert(!att->Renderbuffer);
407 }
408 att->Type = GL_NONE;
409 att->Complete = GL_TRUE;
410 }
411
412 /**
413 * Verify a couple error conditions that will lead to an incomplete FBO and
414 * may cause problems for the driver's RenderTexture path.
415 */
416 static bool
417 driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
418 {
419 const struct gl_texture_image *const texImage =
420 att->Texture->Image[att->CubeMapFace][att->TextureLevel];
421
422 if (!texImage ||
423 texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
424 return false;
425
426 if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
427 && att->Zoffset >= texImage->Height)
428 || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
429 && att->Zoffset >= texImage->Depth))
430 return false;
431
432 return true;
433 }
434
435 /**
436 * Create a renderbuffer which will be set up by the driver to wrap the
437 * texture image slice.
438 *
439 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
440 * to share most of their framebuffer rendering code between winsys,
441 * renderbuffer, and texture attachments.
442 *
443 * The allocated renderbuffer uses a non-zero Name so that drivers can check
444 * it for determining vertical orientation, but we use ~0 to make it fairly
445 * unambiguous with actual user (non-texture) renderbuffers.
446 */
447 void
448 _mesa_update_texture_renderbuffer(struct gl_context *ctx,
449 struct gl_framebuffer *fb,
450 struct gl_renderbuffer_attachment *att)
451 {
452 struct gl_texture_image *texImage;
453 struct gl_renderbuffer *rb;
454
455 texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
456
457 rb = att->Renderbuffer;
458 if (!rb) {
459 rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
460 if (!rb) {
461 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
462 return;
463 }
464 att->Renderbuffer = rb;
465
466 /* This can't get called on a texture renderbuffer, so set it to NULL
467 * for clarity compared to user renderbuffers.
468 */
469 rb->AllocStorage = NULL;
470
471 rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
472 }
473
474 if (!texImage)
475 return;
476
477 rb->_BaseFormat = texImage->_BaseFormat;
478 rb->Format = texImage->TexFormat;
479 rb->InternalFormat = texImage->InternalFormat;
480 rb->Width = texImage->Width2;
481 rb->Height = texImage->Height2;
482 rb->Depth = texImage->Depth2;
483 rb->NumSamples = texImage->NumSamples;
484 rb->NumStorageSamples = texImage->NumSamples;
485 rb->TexImage = texImage;
486
487 if (driver_RenderTexture_is_safe(att))
488 ctx->Driver.RenderTexture(ctx, fb, att);
489 }
490
491 /**
492 * Bind a texture object to an attachment point.
493 * The previous binding, if any, will be removed first.
494 */
495 static void
496 set_texture_attachment(struct gl_context *ctx,
497 struct gl_framebuffer *fb,
498 struct gl_renderbuffer_attachment *att,
499 struct gl_texture_object *texObj,
500 GLenum texTarget, GLuint level, GLsizei samples,
501 GLuint layer, GLboolean layered)
502 {
503 struct gl_renderbuffer *rb = att->Renderbuffer;
504
505 if (rb && rb->NeedsFinishRenderTexture)
506 ctx->Driver.FinishRenderTexture(ctx, rb);
507
508 if (att->Texture == texObj) {
509 /* re-attaching same texture */
510 assert(att->Type == GL_TEXTURE);
511 }
512 else {
513 /* new attachment */
514 remove_attachment(ctx, att);
515 att->Type = GL_TEXTURE;
516 assert(!att->Texture);
517 _mesa_reference_texobj(&att->Texture, texObj);
518 }
519 invalidate_framebuffer(fb);
520
521 /* always update these fields */
522 att->TextureLevel = level;
523 att->NumSamples = samples;
524 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
525 att->Zoffset = layer;
526 att->Layered = layered;
527 att->Complete = GL_FALSE;
528
529 _mesa_update_texture_renderbuffer(ctx, fb, att);
530 }
531
532
533 /**
534 * Bind a renderbuffer to an attachment point.
535 * The previous binding, if any, will be removed first.
536 */
537 static void
538 set_renderbuffer_attachment(struct gl_context *ctx,
539 struct gl_renderbuffer_attachment *att,
540 struct gl_renderbuffer *rb)
541 {
542 /* XXX check if re-doing same attachment, exit early */
543 remove_attachment(ctx, att);
544 att->Type = GL_RENDERBUFFER_EXT;
545 att->Texture = NULL; /* just to be safe */
546 att->Layered = GL_FALSE;
547 att->Complete = GL_FALSE;
548 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
549 }
550
551
552 /**
553 * Fallback for ctx->Driver.FramebufferRenderbuffer()
554 * Attach a renderbuffer object to a framebuffer object.
555 */
556 void
557 _mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
558 struct gl_framebuffer *fb,
559 GLenum attachment,
560 struct gl_renderbuffer *rb)
561 {
562 struct gl_renderbuffer_attachment *att;
563
564 simple_mtx_lock(&fb->Mutex);
565
566 att = get_attachment(ctx, fb, attachment, NULL);
567 assert(att);
568 if (rb) {
569 set_renderbuffer_attachment(ctx, att, rb);
570 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
571 /* do stencil attachment here (depth already done above) */
572 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
573 assert(att);
574 set_renderbuffer_attachment(ctx, att, rb);
575 }
576 rb->AttachedAnytime = GL_TRUE;
577 }
578 else {
579 remove_attachment(ctx, att);
580 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
581 /* detach stencil (depth was detached above) */
582 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
583 assert(att);
584 remove_attachment(ctx, att);
585 }
586 }
587
588 invalidate_framebuffer(fb);
589
590 simple_mtx_unlock(&fb->Mutex);
591 }
592
593
594 /**
595 * Fallback for ctx->Driver.ValidateFramebuffer()
596 * Check if the renderbuffer's formats are supported by the software
597 * renderer.
598 * Drivers should probably override this.
599 */
600 void
601 _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
602 {
603 gl_buffer_index buf;
604 for (buf = 0; buf < BUFFER_COUNT; buf++) {
605 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
606 if (rb) {
607 switch (rb->_BaseFormat) {
608 case GL_ALPHA:
609 case GL_LUMINANCE_ALPHA:
610 case GL_LUMINANCE:
611 case GL_INTENSITY:
612 case GL_RED:
613 case GL_RG:
614 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
615 return;
616
617 default:
618 switch (rb->Format) {
619 /* XXX This list is likely incomplete. */
620 case MESA_FORMAT_R9G9B9E5_FLOAT:
621 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
622 return;
623 default:;
624 /* render buffer format is supported by software rendering */
625 }
626 }
627 }
628 }
629 }
630
631
632 /**
633 * Return true if the framebuffer has a combined depth/stencil
634 * renderbuffer attached.
635 */
636 GLboolean
637 _mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
638 {
639 const struct gl_renderbuffer_attachment *depth =
640 &fb->Attachment[BUFFER_DEPTH];
641 const struct gl_renderbuffer_attachment *stencil =
642 &fb->Attachment[BUFFER_STENCIL];
643
644 if (depth->Type == stencil->Type) {
645 if (depth->Type == GL_RENDERBUFFER_EXT &&
646 depth->Renderbuffer == stencil->Renderbuffer)
647 return GL_TRUE;
648
649 if (depth->Type == GL_TEXTURE &&
650 depth->Texture == stencil->Texture)
651 return GL_TRUE;
652 }
653
654 return GL_FALSE;
655 }
656
657
658 /**
659 * For debug only.
660 */
661 static void
662 att_incomplete(const char *msg)
663 {
664 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
665 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
666 }
667 }
668
669
670 /**
671 * For debug only.
672 */
673 static void
674 fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
675 {
676 static GLuint msg_id;
677
678 _mesa_gl_debug(ctx, &msg_id,
679 MESA_DEBUG_SOURCE_API,
680 MESA_DEBUG_TYPE_OTHER,
681 MESA_DEBUG_SEVERITY_MEDIUM,
682 "FBO incomplete: %s [%d]\n", msg, index);
683
684 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
685 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
686 }
687 }
688
689
690 /**
691 * Is the given base format a legal format for a color renderbuffer?
692 */
693 GLboolean
694 _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
695 {
696 switch (baseFormat) {
697 case GL_RGB:
698 case GL_RGBA:
699 return GL_TRUE;
700 case GL_LUMINANCE:
701 case GL_LUMINANCE_ALPHA:
702 case GL_INTENSITY:
703 case GL_ALPHA:
704 return ctx->API == API_OPENGL_COMPAT &&
705 ctx->Extensions.ARB_framebuffer_object;
706 case GL_RED:
707 case GL_RG:
708 return ctx->Extensions.ARB_texture_rg;
709 default:
710 return GL_FALSE;
711 }
712 }
713
714
715 /**
716 * Is the given base format a legal format for a color renderbuffer?
717 */
718 static GLboolean
719 is_format_color_renderable(const struct gl_context *ctx, mesa_format format,
720 GLenum internalFormat)
721 {
722 const GLenum baseFormat =
723 _mesa_get_format_base_format(format);
724 GLboolean valid;
725
726 valid = _mesa_is_legal_color_format(ctx, baseFormat);
727 if (!valid || _mesa_is_desktop_gl(ctx)) {
728 return valid;
729 }
730
731 /* Reject additional cases for GLES */
732 switch (internalFormat) {
733 case GL_R8_SNORM:
734 case GL_RG8_SNORM:
735 case GL_RGBA8_SNORM:
736 return _mesa_has_EXT_render_snorm(ctx);
737 case GL_R16_SNORM:
738 case GL_RG16_SNORM:
739 case GL_RGBA16_SNORM:
740 return _mesa_has_EXT_texture_norm16(ctx) &&
741 _mesa_has_EXT_render_snorm(ctx);
742 case GL_RGB32F:
743 case GL_RGB32I:
744 case GL_RGB32UI:
745 case GL_RGB16F:
746 case GL_RGB16I:
747 case GL_RGB16UI:
748 case GL_RGB8_SNORM:
749 case GL_RGB8I:
750 case GL_RGB8UI:
751 case GL_SRGB8:
752 case GL_RGB10:
753 case GL_RGB9_E5:
754 case GL_SR8_EXT:
755 return GL_FALSE;
756 default:
757 break;
758 }
759
760 if (internalFormat != GL_RGB10_A2 &&
761 (format == MESA_FORMAT_B10G10R10A2_UNORM ||
762 format == MESA_FORMAT_B10G10R10X2_UNORM ||
763 format == MESA_FORMAT_R10G10B10A2_UNORM ||
764 format == MESA_FORMAT_R10G10B10X2_UNORM)) {
765 return GL_FALSE;
766 }
767
768 return GL_TRUE;
769 }
770
771
772 /**
773 * Is the given base format a legal format for a depth/stencil renderbuffer?
774 */
775 static GLboolean
776 is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
777 {
778 switch (baseFormat) {
779 case GL_DEPTH_COMPONENT:
780 case GL_DEPTH_STENCIL_EXT:
781 return GL_TRUE;
782 default:
783 return GL_FALSE;
784 }
785 }
786
787
788 /**
789 * Test if an attachment point is complete and update its Complete field.
790 * \param format if GL_COLOR, this is a color attachment point,
791 * if GL_DEPTH, this is a depth component attachment point,
792 * if GL_STENCIL, this is a stencil component attachment point.
793 */
794 static void
795 test_attachment_completeness(const struct gl_context *ctx, GLenum format,
796 struct gl_renderbuffer_attachment *att)
797 {
798 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
799
800 /* assume complete */
801 att->Complete = GL_TRUE;
802
803 /* Look for reasons why the attachment might be incomplete */
804 if (att->Type == GL_TEXTURE) {
805 const struct gl_texture_object *texObj = att->Texture;
806 const struct gl_texture_image *texImage;
807 GLenum baseFormat;
808
809 if (!texObj) {
810 att_incomplete("no texobj");
811 att->Complete = GL_FALSE;
812 return;
813 }
814
815 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
816 if (!texImage) {
817 att_incomplete("no teximage");
818 att->Complete = GL_FALSE;
819 return;
820 }
821 if (texImage->Width < 1 || texImage->Height < 1) {
822 att_incomplete("teximage width/height=0");
823 att->Complete = GL_FALSE;
824 return;
825 }
826
827 switch (texObj->Target) {
828 case GL_TEXTURE_3D:
829 if (att->Zoffset >= texImage->Depth) {
830 att_incomplete("bad z offset");
831 att->Complete = GL_FALSE;
832 return;
833 }
834 break;
835 case GL_TEXTURE_1D_ARRAY:
836 if (att->Zoffset >= texImage->Height) {
837 att_incomplete("bad 1D-array layer");
838 att->Complete = GL_FALSE;
839 return;
840 }
841 break;
842 case GL_TEXTURE_2D_ARRAY:
843 if (att->Zoffset >= texImage->Depth) {
844 att_incomplete("bad 2D-array layer");
845 att->Complete = GL_FALSE;
846 return;
847 }
848 break;
849 case GL_TEXTURE_CUBE_MAP_ARRAY:
850 if (att->Zoffset >= texImage->Depth) {
851 att_incomplete("bad cube-array layer");
852 att->Complete = GL_FALSE;
853 return;
854 }
855 break;
856 }
857
858 baseFormat = texImage->_BaseFormat;
859
860 if (format == GL_COLOR) {
861 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
862 att_incomplete("bad format");
863 att->Complete = GL_FALSE;
864 return;
865 }
866 if (_mesa_is_format_compressed(texImage->TexFormat)) {
867 att_incomplete("compressed internalformat");
868 att->Complete = GL_FALSE;
869 return;
870 }
871
872 /* OES_texture_float allows creation and use of floating point
873 * textures with GL_FLOAT, GL_HALF_FLOAT but it does not allow
874 * these textures to be used as a render target, this is done via
875 * GL_EXT_color_buffer(_half)_float with set of new sized types.
876 */
877 if (_mesa_is_gles(ctx) && (texObj->_IsFloat || texObj->_IsHalfFloat)) {
878 att_incomplete("bad internal format");
879 att->Complete = GL_FALSE;
880 return;
881 }
882 }
883 else if (format == GL_DEPTH) {
884 if (baseFormat == GL_DEPTH_COMPONENT) {
885 /* OK */
886 }
887 else if (ctx->Extensions.ARB_depth_texture &&
888 baseFormat == GL_DEPTH_STENCIL) {
889 /* OK */
890 }
891 else {
892 att->Complete = GL_FALSE;
893 att_incomplete("bad depth format");
894 return;
895 }
896 }
897 else {
898 assert(format == GL_STENCIL);
899 if (ctx->Extensions.ARB_depth_texture &&
900 baseFormat == GL_DEPTH_STENCIL) {
901 /* OK */
902 } else if (ctx->Extensions.ARB_texture_stencil8 &&
903 baseFormat == GL_STENCIL_INDEX) {
904 /* OK */
905 } else {
906 /* no such thing as stencil-only textures */
907 att_incomplete("illegal stencil texture");
908 att->Complete = GL_FALSE;
909 return;
910 }
911 }
912 }
913 else if (att->Type == GL_RENDERBUFFER_EXT) {
914 const GLenum baseFormat = att->Renderbuffer->_BaseFormat;
915
916 assert(att->Renderbuffer);
917 if (!att->Renderbuffer->InternalFormat ||
918 att->Renderbuffer->Width < 1 ||
919 att->Renderbuffer->Height < 1) {
920 att_incomplete("0x0 renderbuffer");
921 att->Complete = GL_FALSE;
922 return;
923 }
924 if (format == GL_COLOR) {
925 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
926 att_incomplete("bad renderbuffer color format");
927 att->Complete = GL_FALSE;
928 return;
929 }
930 }
931 else if (format == GL_DEPTH) {
932 if (baseFormat == GL_DEPTH_COMPONENT) {
933 /* OK */
934 }
935 else if (baseFormat == GL_DEPTH_STENCIL) {
936 /* OK */
937 }
938 else {
939 att_incomplete("bad renderbuffer depth format");
940 att->Complete = GL_FALSE;
941 return;
942 }
943 }
944 else {
945 assert(format == GL_STENCIL);
946 if (baseFormat == GL_STENCIL_INDEX ||
947 baseFormat == GL_DEPTH_STENCIL) {
948 /* OK */
949 }
950 else {
951 att->Complete = GL_FALSE;
952 att_incomplete("bad renderbuffer stencil format");
953 return;
954 }
955 }
956 }
957 else {
958 assert(att->Type == GL_NONE);
959 /* complete */
960 return;
961 }
962 }
963
964
965 /**
966 * Test if the given framebuffer object is complete and update its
967 * Status field with the results.
968 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
969 * driver to make hardware-specific validation/completeness checks.
970 * Also update the framebuffer's Width and Height fields if the
971 * framebuffer is complete.
972 */
973 void
974 _mesa_test_framebuffer_completeness(struct gl_context *ctx,
975 struct gl_framebuffer *fb)
976 {
977 GLuint numImages;
978 GLenum intFormat = GL_NONE; /* color buffers' internal format */
979 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
980 GLint numColorSamples = -1;
981 GLint numColorStorageSamples = -1;
982 GLint numDepthSamples = -1;
983 GLint fixedSampleLocations = -1;
984 GLint i;
985 GLuint j;
986 /* Covers max_layer_count, is_layered, and layer_tex_target */
987 bool layer_info_valid = false;
988 GLuint max_layer_count = 0, att_layer_count;
989 bool is_layered = false;
990 GLenum layer_tex_target = 0;
991 bool has_depth_attachment = false;
992 bool has_stencil_attachment = false;
993
994 assert(_mesa_is_user_fbo(fb));
995
996 /* we're changing framebuffer fields here */
997 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
998
999 numImages = 0;
1000 fb->Width = 0;
1001 fb->Height = 0;
1002 fb->_AllColorBuffersFixedPoint = GL_TRUE;
1003 fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
1004 fb->_HasAttachments = true;
1005 fb->_IntegerBuffers = 0;
1006 fb->_RGBBuffers = 0;
1007
1008 /* Start at -2 to more easily loop over all attachment points.
1009 * -2: depth buffer
1010 * -1: stencil buffer
1011 * >=0: color buffer
1012 */
1013 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
1014 struct gl_renderbuffer_attachment *att;
1015 GLenum f;
1016 mesa_format attFormat;
1017 GLenum att_tex_target = GL_NONE;
1018
1019 /*
1020 * XXX for ARB_fbo, only check color buffers that are named by
1021 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
1022 */
1023
1024 /* check for attachment completeness
1025 */
1026 if (i == -2) {
1027 att = &fb->Attachment[BUFFER_DEPTH];
1028 test_attachment_completeness(ctx, GL_DEPTH, att);
1029 if (!att->Complete) {
1030 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1031 fbo_incomplete(ctx, "depth attachment incomplete", -1);
1032 return;
1033 } else if (att->Type != GL_NONE) {
1034 has_depth_attachment = true;
1035 }
1036 }
1037 else if (i == -1) {
1038 att = &fb->Attachment[BUFFER_STENCIL];
1039 test_attachment_completeness(ctx, GL_STENCIL, att);
1040 if (!att->Complete) {
1041 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1042 fbo_incomplete(ctx, "stencil attachment incomplete", -1);
1043 return;
1044 } else if (att->Type != GL_NONE) {
1045 has_stencil_attachment = true;
1046 }
1047 }
1048 else {
1049 att = &fb->Attachment[BUFFER_COLOR0 + i];
1050 test_attachment_completeness(ctx, GL_COLOR, att);
1051 if (!att->Complete) {
1052 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1053 fbo_incomplete(ctx, "color attachment incomplete", i);
1054 return;
1055 }
1056 }
1057
1058 /* get width, height, format of the renderbuffer/texture
1059 */
1060 unsigned attNumSamples, attNumStorageSamples;
1061
1062 if (att->Type == GL_TEXTURE) {
1063 const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
1064 att_tex_target = att->Texture->Target;
1065 minWidth = MIN2(minWidth, texImg->Width);
1066 maxWidth = MAX2(maxWidth, texImg->Width);
1067 minHeight = MIN2(minHeight, texImg->Height);
1068 maxHeight = MAX2(maxHeight, texImg->Height);
1069 f = texImg->_BaseFormat;
1070 attFormat = texImg->TexFormat;
1071 numImages++;
1072
1073 if (!is_format_color_renderable(ctx, attFormat,
1074 texImg->InternalFormat) &&
1075 !is_legal_depth_format(ctx, f) &&
1076 f != GL_STENCIL_INDEX) {
1077 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1078 fbo_incomplete(ctx, "texture attachment incomplete", -1);
1079 return;
1080 }
1081
1082 if (fixedSampleLocations < 0)
1083 fixedSampleLocations = texImg->FixedSampleLocations;
1084 else if (fixedSampleLocations != texImg->FixedSampleLocations) {
1085 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1086 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1087 return;
1088 }
1089
1090 if (att->NumSamples > 0)
1091 attNumSamples = att->NumSamples;
1092 else
1093 attNumSamples = texImg->NumSamples;
1094 attNumStorageSamples = attNumSamples;
1095 }
1096 else if (att->Type == GL_RENDERBUFFER_EXT) {
1097 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
1098 maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
1099 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
1100 maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
1101 f = att->Renderbuffer->InternalFormat;
1102 attFormat = att->Renderbuffer->Format;
1103 numImages++;
1104
1105 /* RENDERBUFFER has fixedSampleLocations implicitly true */
1106 if (fixedSampleLocations < 0)
1107 fixedSampleLocations = GL_TRUE;
1108 else if (fixedSampleLocations != GL_TRUE) {
1109 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1110 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1111 return;
1112 }
1113
1114 attNumSamples = att->Renderbuffer->NumSamples;
1115 attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
1116 }
1117 else {
1118 assert(att->Type == GL_NONE);
1119 continue;
1120 }
1121
1122 if (i >= 0) {
1123 /* Color buffers. */
1124 if (numColorSamples < 0) {
1125 assert(numColorStorageSamples < 0);
1126 numColorSamples = attNumSamples;
1127 numColorStorageSamples = attNumStorageSamples;
1128 } else if (numColorSamples != attNumSamples ||
1129 numColorStorageSamples != attNumStorageSamples) {
1130 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1131 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1132 return;
1133 }
1134 } else {
1135 /* Depth/stencil buffers. */
1136 if (numDepthSamples < 0) {
1137 numDepthSamples = attNumSamples;
1138 } else if (numDepthSamples != attNumSamples) {
1139 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1140 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1141 return;
1142 }
1143 }
1144
1145 /* Update flags describing color buffer datatypes */
1146 if (i >= 0) {
1147 GLenum type = _mesa_get_format_datatype(attFormat);
1148
1149 /* check if integer color */
1150 if (_mesa_is_format_integer_color(attFormat))
1151 fb->_IntegerBuffers |= (1 << i);
1152
1153 if (f == GL_RGB)
1154 fb->_RGBBuffers |= (1 << i);
1155
1156 fb->_AllColorBuffersFixedPoint =
1157 fb->_AllColorBuffersFixedPoint &&
1158 (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
1159
1160 fb->_HasSNormOrFloatColorBuffer =
1161 fb->_HasSNormOrFloatColorBuffer ||
1162 type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
1163 }
1164
1165 /* Error-check width, height, format */
1166 if (numImages == 1) {
1167 /* save format */
1168 if (i >= 0) {
1169 intFormat = f;
1170 }
1171 }
1172 else {
1173 if (!ctx->Extensions.ARB_framebuffer_object) {
1174 /* check that width, height, format are same */
1175 if (minWidth != maxWidth || minHeight != maxHeight) {
1176 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
1177 fbo_incomplete(ctx, "width or height mismatch", -1);
1178 return;
1179 }
1180 /* check that all color buffers are the same format */
1181 if (intFormat != GL_NONE && f != intFormat) {
1182 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
1183 fbo_incomplete(ctx, "format mismatch", -1);
1184 return;
1185 }
1186 }
1187 }
1188
1189 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1190 */
1191 if (att->Type == GL_RENDERBUFFER &&
1192 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1193 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1194 fbo_incomplete(ctx, "unsupported renderbuffer format", i);
1195 return;
1196 }
1197
1198 /* Check that layered rendering is consistent. */
1199 if (att->Layered) {
1200 if (att_tex_target == GL_TEXTURE_CUBE_MAP)
1201 att_layer_count = 6;
1202 else if (att_tex_target == GL_TEXTURE_1D_ARRAY)
1203 att_layer_count = att->Renderbuffer->Height;
1204 else
1205 att_layer_count = att->Renderbuffer->Depth;
1206 } else {
1207 att_layer_count = 0;
1208 }
1209 if (!layer_info_valid) {
1210 is_layered = att->Layered;
1211 max_layer_count = att_layer_count;
1212 layer_tex_target = att_tex_target;
1213 layer_info_valid = true;
1214 } else if (max_layer_count > 0 && layer_tex_target != att_tex_target) {
1215 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1216 fbo_incomplete(ctx, "layered framebuffer has mismatched targets", i);
1217 return;
1218 } else if (is_layered != att->Layered) {
1219 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1220 fbo_incomplete(ctx,
1221 "framebuffer attachment layer mode is inconsistent",
1222 i);
1223 return;
1224 } else if (att_layer_count > max_layer_count) {
1225 max_layer_count = att_layer_count;
1226 }
1227
1228 /*
1229 * The extension GL_ARB_framebuffer_no_attachments places additional
1230 * requirement on each attachment. Those additional requirements are
1231 * tighter that those of previous versions of GL. In interest of better
1232 * compatibility, we will not enforce these restrictions. For the record
1233 * those additional restrictions are quoted below:
1234 *
1235 * "The width and height of image are greater than zero and less than or
1236 * equal to the values of the implementation-dependent limits
1237 * MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively."
1238 *
1239 * "If <image> is a three-dimensional texture or a one- or two-dimensional
1240 * array texture and the attachment is layered, the depth or layer count
1241 * of the texture is less than or equal to the implementation-dependent
1242 * limit MAX_FRAMEBUFFER_LAYERS."
1243 *
1244 * "If image has multiple samples, its sample count is less than or equal
1245 * to the value of the implementation-dependent limit
1246 * MAX_FRAMEBUFFER_SAMPLES."
1247 *
1248 * The same requirements are also in place for GL 4.5,
1249 * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
1250 */
1251 }
1252
1253 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
1254 /* See if non-matching sample counts are supported. */
1255 if (numColorSamples >= 0 && numDepthSamples >= 0) {
1256 bool found = false;
1257
1258 assert(numColorStorageSamples != -1);
1259
1260 numColorSamples = MAX2(numColorSamples, 1);
1261 numColorStorageSamples = MAX2(numColorStorageSamples, 1);
1262 numDepthSamples = MAX2(numDepthSamples, 1);
1263
1264 if (numColorSamples == 1 && numColorStorageSamples == 1 &&
1265 numDepthSamples == 1) {
1266 found = true;
1267 } else {
1268 for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
1269 GLint *counts =
1270 &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
1271
1272 if (counts[0] == numColorSamples &&
1273 counts[1] == numColorStorageSamples &&
1274 counts[2] == numDepthSamples) {
1275 found = true;
1276 break;
1277 }
1278 }
1279 }
1280
1281 if (!found) {
1282 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1283 fbo_incomplete(ctx, "unsupported sample counts", -1);
1284 return;
1285 }
1286 }
1287 } else {
1288 /* If the extension is unsupported, all sample counts must be equal. */
1289 if (numColorSamples >= 0 &&
1290 (numColorSamples != numColorStorageSamples ||
1291 (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
1292 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1293 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1294 return;
1295 }
1296 }
1297
1298 fb->MaxNumLayers = max_layer_count;
1299
1300 if (numImages == 0) {
1301 fb->_HasAttachments = false;
1302
1303 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1304 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1305 fbo_incomplete(ctx, "no attachments", -1);
1306 return;
1307 }
1308
1309 if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) {
1310 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1311 fbo_incomplete(ctx, "no attachments and default width or height is 0", -1);
1312 return;
1313 }
1314 }
1315
1316 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
1317 /* Check that all DrawBuffers are present */
1318 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
1319 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1320 const struct gl_renderbuffer_attachment *att
1321 = get_attachment(ctx, fb, fb->ColorDrawBuffer[j], NULL);
1322 assert(att);
1323 if (att->Type == GL_NONE) {
1324 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1325 fbo_incomplete(ctx, "missing drawbuffer", j);
1326 return;
1327 }
1328 }
1329 }
1330
1331 /* Check that the ReadBuffer is present */
1332 if (fb->ColorReadBuffer != GL_NONE) {
1333 const struct gl_renderbuffer_attachment *att
1334 = get_attachment(ctx, fb, fb->ColorReadBuffer, NULL);
1335 assert(att);
1336 if (att->Type == GL_NONE) {
1337 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
1338 fbo_incomplete(ctx, "missing readbuffer", -1);
1339 return;
1340 }
1341 }
1342 }
1343
1344 /* The OpenGL ES3 spec, in chapter 9.4. FRAMEBUFFER COMPLETENESS, says:
1345 *
1346 * "Depth and stencil attachments, if present, are the same image."
1347 *
1348 * This restriction is not present in the OpenGL ES2 spec.
1349 */
1350 if (_mesa_is_gles3(ctx) &&
1351 has_stencil_attachment && has_depth_attachment &&
1352 !_mesa_has_depthstencil_combined(fb)) {
1353 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1354 fbo_incomplete(ctx, "Depth and stencil attachments must be the same image", -1);
1355 return;
1356 }
1357
1358 /* Provisionally set status = COMPLETE ... */
1359 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
1360
1361 /* ... but the driver may say the FB is incomplete.
1362 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1363 * if anything.
1364 */
1365 if (ctx->Driver.ValidateFramebuffer) {
1366 ctx->Driver.ValidateFramebuffer(ctx, fb);
1367 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1368 fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
1369 return;
1370 }
1371 }
1372
1373 /*
1374 * Note that if ARB_framebuffer_object is supported and the attached
1375 * renderbuffers/textures are different sizes, the framebuffer
1376 * width/height will be set to the smallest width/height.
1377 */
1378 if (numImages != 0) {
1379 fb->Width = minWidth;
1380 fb->Height = minHeight;
1381 }
1382
1383 /* finally, update the visual info for the framebuffer */
1384 _mesa_update_framebuffer_visual(ctx, fb);
1385 }
1386
1387
1388 GLboolean GLAPIENTRY
1389 _mesa_IsRenderbuffer(GLuint renderbuffer)
1390 {
1391 struct gl_renderbuffer *rb;
1392
1393 GET_CURRENT_CONTEXT(ctx);
1394
1395 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1396
1397 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1398 return rb != NULL && rb != &DummyRenderbuffer;
1399 }
1400
1401
1402 static struct gl_renderbuffer *
1403 allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
1404 const char *func)
1405 {
1406 struct gl_renderbuffer *newRb;
1407
1408 /* create new renderbuffer object */
1409 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1410 if (!newRb) {
1411 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1412 return NULL;
1413 }
1414 assert(newRb->AllocStorage);
1415 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer, newRb);
1416
1417 return newRb;
1418 }
1419
1420
1421 static void
1422 bind_renderbuffer(GLenum target, GLuint renderbuffer)
1423 {
1424 struct gl_renderbuffer *newRb;
1425 GET_CURRENT_CONTEXT(ctx);
1426
1427 if (target != GL_RENDERBUFFER_EXT) {
1428 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
1429 return;
1430 }
1431
1432 /* No need to flush here since the render buffer binding has no
1433 * effect on rendering state.
1434 */
1435
1436 if (renderbuffer) {
1437 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1438 if (newRb == &DummyRenderbuffer) {
1439 /* ID was reserved, but no real renderbuffer object made yet */
1440 newRb = NULL;
1441 }
1442 else if (!newRb && ctx->API == API_OPENGL_CORE) {
1443 /* All RB IDs must be Gen'd */
1444 _mesa_error(ctx, GL_INVALID_OPERATION,
1445 "glBindRenderbuffer(non-gen name)");
1446 return;
1447 }
1448
1449 if (!newRb) {
1450 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1451 newRb = allocate_renderbuffer_locked(ctx, renderbuffer,
1452 "glBindRenderbufferEXT");
1453 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
1454 }
1455 }
1456 else {
1457 newRb = NULL;
1458 }
1459
1460 assert(newRb != &DummyRenderbuffer);
1461
1462 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
1463 }
1464
1465 void GLAPIENTRY
1466 _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1467 {
1468 /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1469 * entry point, but they allow the use of user-generated names.
1470 */
1471 bind_renderbuffer(target, renderbuffer);
1472 }
1473
1474 void GLAPIENTRY
1475 _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1476 {
1477 bind_renderbuffer(target, renderbuffer);
1478 }
1479
1480 /**
1481 * ARB_framebuffer_no_attachment and ARB_sample_locations - Application passes
1482 * requested param's here. NOTE: NumSamples requested need not be _NumSamples
1483 * which is what the hw supports.
1484 */
1485 static void
1486 framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
1487 GLenum pname, GLint param, const char *func)
1488 {
1489 bool cannot_be_winsys_fbo = false;
1490
1491 switch (pname) {
1492 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1493 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1494 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1495 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1496 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1497 if (!ctx->Extensions.ARB_framebuffer_no_attachments)
1498 goto invalid_pname_enum;
1499 cannot_be_winsys_fbo = true;
1500 break;
1501 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1502 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1503 if (!ctx->Extensions.ARB_sample_locations)
1504 goto invalid_pname_enum;
1505 break;
1506 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1507 if (!ctx->Extensions.MESA_framebuffer_flip_y)
1508 goto invalid_pname_enum;
1509 cannot_be_winsys_fbo = true;
1510 break;
1511 default:
1512 goto invalid_pname_enum;
1513 }
1514
1515 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1516 _mesa_error(ctx, GL_INVALID_OPERATION,
1517 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1518 return;
1519 }
1520
1521 switch (pname) {
1522 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1523 if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
1524 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1525 else
1526 fb->DefaultGeometry.Width = param;
1527 break;
1528 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1529 if (param < 0 || param > ctx->Const.MaxFramebufferHeight)
1530 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1531 else
1532 fb->DefaultGeometry.Height = param;
1533 break;
1534 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1535 /*
1536 * According to the OpenGL ES 3.1 specification section 9.2.1, the
1537 * GL_FRAMEBUFFER_DEFAULT_LAYERS parameter name is not supported.
1538 */
1539 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1540 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1541 break;
1542 }
1543 if (param < 0 || param > ctx->Const.MaxFramebufferLayers)
1544 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1545 else
1546 fb->DefaultGeometry.Layers = param;
1547 break;
1548 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1549 if (param < 0 || param > ctx->Const.MaxFramebufferSamples)
1550 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1551 else
1552 fb->DefaultGeometry.NumSamples = param;
1553 break;
1554 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1555 fb->DefaultGeometry.FixedSampleLocations = param;
1556 break;
1557 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1558 fb->ProgrammableSampleLocations = !!param;
1559 break;
1560 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1561 fb->SampleLocationPixelGrid = !!param;
1562 break;
1563 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1564 fb->FlipY = param;
1565 break;
1566 }
1567
1568 switch (pname) {
1569 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1570 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1571 if (fb == ctx->DrawBuffer)
1572 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
1573 break;
1574 default:
1575 invalidate_framebuffer(fb);
1576 ctx->NewState |= _NEW_BUFFERS;
1577 break;
1578 }
1579
1580 return;
1581
1582 invalid_pname_enum:
1583 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1584 }
1585
1586 void GLAPIENTRY
1587 _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
1588 {
1589 GET_CURRENT_CONTEXT(ctx);
1590 struct gl_framebuffer *fb;
1591
1592 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
1593 !ctx->Extensions.ARB_sample_locations) {
1594 _mesa_error(ctx, GL_INVALID_OPERATION,
1595 "glFramebufferParameteriv not supported "
1596 "(neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
1597 " is available)");
1598 return;
1599 }
1600
1601 fb = get_framebuffer_target(ctx, target);
1602 if (!fb) {
1603 _mesa_error(ctx, GL_INVALID_ENUM,
1604 "glFramebufferParameteri(target=0x%x)", target);
1605 return;
1606 }
1607
1608 framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
1609 }
1610
1611 static bool
1612 validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
1613 struct gl_framebuffer *fb,
1614 GLuint pname, const char *func)
1615 {
1616 bool cannot_be_winsys_fbo = true;
1617
1618 switch (pname) {
1619 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1620 /*
1621 * According to the OpenGL ES 3.1 specification section 9.2.3, the
1622 * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
1623 */
1624 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1625 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1626 return false;
1627 }
1628 break;
1629 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1630 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1631 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1632 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1633 break;
1634 case GL_DOUBLEBUFFER:
1635 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1636 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1637 case GL_SAMPLES:
1638 case GL_SAMPLE_BUFFERS:
1639 case GL_STEREO:
1640 /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
1641 *
1642 * "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
1643 * if the default framebuffer is bound to target and pname is not one
1644 * of the accepted values from table 23.73, other than
1645 * SAMPLE_POSITION."
1646 *
1647 * For OpenGL ES, using default framebuffer raises INVALID_OPERATION
1648 * for any pname.
1649 */
1650 cannot_be_winsys_fbo = !_mesa_is_desktop_gl(ctx);
1651 break;
1652 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1653 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1654 if (!ctx->Extensions.ARB_sample_locations)
1655 goto invalid_pname_enum;
1656 cannot_be_winsys_fbo = false;
1657 break;
1658 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1659 if (!ctx->Extensions.MESA_framebuffer_flip_y) {
1660 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1661 return false;
1662 }
1663 break;
1664 default:
1665 goto invalid_pname_enum;
1666 }
1667
1668 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1669 _mesa_error(ctx, GL_INVALID_OPERATION,
1670 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1671 return false;
1672 }
1673
1674 return true;
1675
1676 invalid_pname_enum:
1677 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1678 return false;
1679 }
1680
1681 static void
1682 get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
1683 GLenum pname, GLint *params, const char *func)
1684 {
1685 if (!validate_get_framebuffer_parameteriv_pname(ctx, fb, pname, func))
1686 return;
1687
1688 switch (pname) {
1689 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1690 *params = fb->DefaultGeometry.Width;
1691 break;
1692 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1693 *params = fb->DefaultGeometry.Height;
1694 break;
1695 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1696 *params = fb->DefaultGeometry.Layers;
1697 break;
1698 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1699 *params = fb->DefaultGeometry.NumSamples;
1700 break;
1701 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1702 *params = fb->DefaultGeometry.FixedSampleLocations;
1703 break;
1704 case GL_DOUBLEBUFFER:
1705 *params = fb->Visual.doubleBufferMode;
1706 break;
1707 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1708 *params = _mesa_get_color_read_format(ctx, fb, func);
1709 break;
1710 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1711 *params = _mesa_get_color_read_type(ctx, fb, func);
1712 break;
1713 case GL_SAMPLES:
1714 *params = _mesa_geometric_samples(fb);
1715 break;
1716 case GL_SAMPLE_BUFFERS:
1717 *params = _mesa_geometric_samples(fb) > 0;
1718 break;
1719 case GL_STEREO:
1720 *params = fb->Visual.stereoMode;
1721 break;
1722 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1723 *params = fb->ProgrammableSampleLocations;
1724 break;
1725 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1726 *params = fb->SampleLocationPixelGrid;
1727 break;
1728 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1729 *params = fb->FlipY;
1730 break;
1731 }
1732 }
1733
1734 void GLAPIENTRY
1735 _mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
1736 {
1737 GET_CURRENT_CONTEXT(ctx);
1738 struct gl_framebuffer *fb;
1739
1740 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
1741 !ctx->Extensions.ARB_sample_locations) {
1742 _mesa_error(ctx, GL_INVALID_OPERATION,
1743 "glGetFramebufferParameteriv not supported "
1744 "(neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
1745 " is available)");
1746 return;
1747 }
1748
1749 fb = get_framebuffer_target(ctx, target);
1750 if (!fb) {
1751 _mesa_error(ctx, GL_INVALID_ENUM,
1752 "glGetFramebufferParameteriv(target=0x%x)", target);
1753 return;
1754 }
1755
1756 get_framebuffer_parameteriv(ctx, fb, pname, params,
1757 "glGetFramebufferParameteriv");
1758 }
1759
1760
1761 /**
1762 * Remove the specified renderbuffer or texture from any attachment point in
1763 * the framebuffer.
1764 *
1765 * \returns
1766 * \c true if the renderbuffer was detached from an attachment point. \c
1767 * false otherwise.
1768 */
1769 bool
1770 _mesa_detach_renderbuffer(struct gl_context *ctx,
1771 struct gl_framebuffer *fb,
1772 const void *att)
1773 {
1774 unsigned i;
1775 bool progress = false;
1776
1777 for (i = 0; i < BUFFER_COUNT; i++) {
1778 if (fb->Attachment[i].Texture == att
1779 || fb->Attachment[i].Renderbuffer == att) {
1780 remove_attachment(ctx, &fb->Attachment[i]);
1781 progress = true;
1782 }
1783 }
1784
1785 /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1786 * Completeness," of the OpenGL 3.1 spec says:
1787 *
1788 * "Performing any of the following actions may change whether the
1789 * framebuffer is considered complete or incomplete:
1790 *
1791 * ...
1792 *
1793 * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1794 * containing an image that is attached to a framebuffer object
1795 * that is bound to the framebuffer."
1796 */
1797 if (progress)
1798 invalidate_framebuffer(fb);
1799
1800 return progress;
1801 }
1802
1803
1804 void GLAPIENTRY
1805 _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
1806 {
1807 GLint i;
1808 GET_CURRENT_CONTEXT(ctx);
1809
1810 if (n < 0) {
1811 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteRenderbuffers(n < 0)");
1812 return;
1813 }
1814
1815 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1816
1817 for (i = 0; i < n; i++) {
1818 if (renderbuffers[i] > 0) {
1819 struct gl_renderbuffer *rb;
1820 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
1821 if (rb) {
1822 /* check if deleting currently bound renderbuffer object */
1823 if (rb == ctx->CurrentRenderbuffer) {
1824 /* bind default */
1825 assert(rb->RefCount >= 2);
1826 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
1827 }
1828
1829 /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
1830 * subsection "Attaching Renderbuffer Images to a Framebuffer,"
1831 * of the OpenGL 3.1 spec says:
1832 *
1833 * "If a renderbuffer object is deleted while its image is
1834 * attached to one or more attachment points in the currently
1835 * bound framebuffer, then it is as if FramebufferRenderbuffer
1836 * had been called, with a renderbuffer of 0, for each
1837 * attachment point to which this image was attached in the
1838 * currently bound framebuffer. In other words, this
1839 * renderbuffer image is first detached from all attachment
1840 * points in the currently bound framebuffer. Note that the
1841 * renderbuffer image is specifically not detached from any
1842 * non-bound framebuffers. Detaching the image from any
1843 * non-bound framebuffers is the responsibility of the
1844 * application.
1845 */
1846 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1847 _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
1848 }
1849 if (_mesa_is_user_fbo(ctx->ReadBuffer)
1850 && ctx->ReadBuffer != ctx->DrawBuffer) {
1851 _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
1852 }
1853
1854 /* Remove from hash table immediately, to free the ID.
1855 * But the object will not be freed until it's no longer
1856 * referenced anywhere else.
1857 */
1858 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
1859
1860 if (rb != &DummyRenderbuffer) {
1861 /* no longer referenced by hash table */
1862 _mesa_reference_renderbuffer(&rb, NULL);
1863 }
1864 }
1865 }
1866 }
1867 }
1868
1869 static void
1870 create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
1871 bool dsa)
1872 {
1873 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
1874 GLuint first;
1875 GLint i;
1876
1877 if (!renderbuffers)
1878 return;
1879
1880 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1881
1882 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1883
1884 for (i = 0; i < n; i++) {
1885 GLuint name = first + i;
1886 renderbuffers[i] = name;
1887
1888 if (dsa) {
1889 allocate_renderbuffer_locked(ctx, name, func);
1890 } else {
1891 /* insert a dummy renderbuffer into the hash table */
1892 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, name,
1893 &DummyRenderbuffer);
1894 }
1895 }
1896
1897 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
1898 }
1899
1900
1901 static void
1902 create_render_buffers_err(struct gl_context *ctx, GLsizei n,
1903 GLuint *renderbuffers, bool dsa)
1904 {
1905 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
1906
1907 if (n < 0) {
1908 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
1909 return;
1910 }
1911
1912 create_render_buffers(ctx, n, renderbuffers, dsa);
1913 }
1914
1915
1916 void GLAPIENTRY
1917 _mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
1918 {
1919 GET_CURRENT_CONTEXT(ctx);
1920 create_render_buffers(ctx, n, renderbuffers, false);
1921 }
1922
1923
1924 void GLAPIENTRY
1925 _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
1926 {
1927 GET_CURRENT_CONTEXT(ctx);
1928 create_render_buffers_err(ctx, n, renderbuffers, false);
1929 }
1930
1931
1932 void GLAPIENTRY
1933 _mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
1934 {
1935 GET_CURRENT_CONTEXT(ctx);
1936 create_render_buffers(ctx, n, renderbuffers, true);
1937 }
1938
1939
1940 void GLAPIENTRY
1941 _mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
1942 {
1943 GET_CURRENT_CONTEXT(ctx);
1944 create_render_buffers_err(ctx, n, renderbuffers, true);
1945 }
1946
1947
1948 /**
1949 * Given an internal format token for a render buffer, return the
1950 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
1951 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
1952 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
1953 *
1954 * This is similar to _mesa_base_tex_format() but the set of valid
1955 * internal formats is different.
1956 *
1957 * Note that even if a format is determined to be legal here, validation
1958 * of the FBO may fail if the format is not supported by the driver/GPU.
1959 *
1960 * \param internalFormat as passed to glRenderbufferStorage()
1961 * \return the base internal format, or 0 if internalFormat is illegal
1962 */
1963 GLenum
1964 _mesa_base_fbo_format(const struct gl_context *ctx, GLenum internalFormat)
1965 {
1966 /*
1967 * Notes: some formats such as alpha, luminance, etc. were added
1968 * with GL_ARB_framebuffer_object.
1969 */
1970 switch (internalFormat) {
1971 case GL_ALPHA:
1972 case GL_ALPHA4:
1973 case GL_ALPHA8:
1974 case GL_ALPHA12:
1975 case GL_ALPHA16:
1976 return (ctx->API == API_OPENGL_COMPAT &&
1977 ctx->Extensions.ARB_framebuffer_object) ? GL_ALPHA : 0;
1978 case GL_LUMINANCE:
1979 case GL_LUMINANCE4:
1980 case GL_LUMINANCE8:
1981 case GL_LUMINANCE12:
1982 case GL_LUMINANCE16:
1983 return (ctx->API == API_OPENGL_COMPAT &&
1984 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE : 0;
1985 case GL_LUMINANCE_ALPHA:
1986 case GL_LUMINANCE4_ALPHA4:
1987 case GL_LUMINANCE6_ALPHA2:
1988 case GL_LUMINANCE8_ALPHA8:
1989 case GL_LUMINANCE12_ALPHA4:
1990 case GL_LUMINANCE12_ALPHA12:
1991 case GL_LUMINANCE16_ALPHA16:
1992 return (ctx->API == API_OPENGL_COMPAT &&
1993 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE_ALPHA : 0;
1994 case GL_INTENSITY:
1995 case GL_INTENSITY4:
1996 case GL_INTENSITY8:
1997 case GL_INTENSITY12:
1998 case GL_INTENSITY16:
1999 return (ctx->API == API_OPENGL_COMPAT &&
2000 ctx->Extensions.ARB_framebuffer_object) ? GL_INTENSITY : 0;
2001 case GL_RGB8:
2002 return GL_RGB;
2003 case GL_RGB:
2004 case GL_R3_G3_B2:
2005 case GL_RGB4:
2006 case GL_RGB5:
2007 case GL_RGB10:
2008 case GL_RGB12:
2009 case GL_RGB16:
2010 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
2011 case GL_SRGB8_EXT:
2012 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
2013 case GL_RGBA4:
2014 case GL_RGB5_A1:
2015 case GL_RGBA8:
2016 return GL_RGBA;
2017 case GL_RGBA:
2018 case GL_RGBA2:
2019 case GL_RGBA12:
2020 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
2021 case GL_RGBA16:
2022 return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2023 ? GL_RGBA : 0;
2024 case GL_RGB10_A2:
2025 case GL_SRGB8_ALPHA8_EXT:
2026 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
2027 case GL_STENCIL_INDEX:
2028 case GL_STENCIL_INDEX1_EXT:
2029 case GL_STENCIL_INDEX4_EXT:
2030 case GL_STENCIL_INDEX16_EXT:
2031 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
2032 * OpenGL ES, but Mesa does not currently support them.
2033 */
2034 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
2035 case GL_STENCIL_INDEX8_EXT:
2036 return GL_STENCIL_INDEX;
2037 case GL_DEPTH_COMPONENT:
2038 case GL_DEPTH_COMPONENT32:
2039 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
2040 case GL_DEPTH_COMPONENT16:
2041 case GL_DEPTH_COMPONENT24:
2042 return GL_DEPTH_COMPONENT;
2043 case GL_DEPTH_STENCIL:
2044 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_STENCIL : 0;
2045 case GL_DEPTH24_STENCIL8:
2046 return GL_DEPTH_STENCIL;
2047 case GL_DEPTH_COMPONENT32F:
2048 return ctx->Version >= 30
2049 || (ctx->API == API_OPENGL_COMPAT &&
2050 ctx->Extensions.ARB_depth_buffer_float)
2051 ? GL_DEPTH_COMPONENT : 0;
2052 case GL_DEPTH32F_STENCIL8:
2053 return ctx->Version >= 30
2054 || (ctx->API == API_OPENGL_COMPAT &&
2055 ctx->Extensions.ARB_depth_buffer_float)
2056 ? GL_DEPTH_STENCIL : 0;
2057 case GL_RED:
2058 return _mesa_has_ARB_texture_rg(ctx) ? GL_RED : 0;
2059 case GL_R16:
2060 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2061 ? GL_RED : 0;
2062 case GL_R8:
2063 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2064 ? GL_RED : 0;
2065 case GL_RG:
2066 return _mesa_has_ARB_texture_rg(ctx) ? GL_RG : 0;
2067 case GL_RG16:
2068 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2069 ? GL_RG : 0;
2070 case GL_RG8:
2071 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2072 ? GL_RG : 0;
2073 /* signed normalized texture formats */
2074 case GL_R8_SNORM:
2075 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2076 ? GL_RED : 0;
2077 case GL_RED_SNORM:
2078 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RED : 0;
2079 case GL_R16_SNORM:
2080 return _mesa_has_EXT_texture_snorm(ctx) ||
2081 (_mesa_has_EXT_render_snorm(ctx) &&
2082 _mesa_has_EXT_texture_norm16(ctx))
2083 ? GL_RED : 0;
2084 case GL_RG8_SNORM:
2085 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2086 ? GL_RG : 0;
2087 case GL_RG_SNORM:
2088 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RG : 0;
2089 case GL_RG16_SNORM:
2090 return _mesa_has_EXT_texture_snorm(ctx) ||
2091 (_mesa_has_EXT_render_snorm(ctx) &&
2092 _mesa_has_EXT_texture_norm16(ctx))
2093 ? GL_RG : 0;
2094 case GL_RGB_SNORM:
2095 case GL_RGB8_SNORM:
2096 case GL_RGB16_SNORM:
2097 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2098 ? GL_RGB : 0;
2099 case GL_RGBA8_SNORM:
2100 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2101 ? GL_RGBA : 0;
2102 case GL_RGBA_SNORM:
2103 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RGBA : 0;
2104 case GL_RGBA16_SNORM:
2105 return _mesa_has_EXT_texture_snorm(ctx) ||
2106 (_mesa_has_EXT_render_snorm(ctx) &&
2107 _mesa_has_EXT_texture_norm16(ctx))
2108 ? GL_RGBA : 0;
2109 case GL_ALPHA_SNORM:
2110 case GL_ALPHA8_SNORM:
2111 case GL_ALPHA16_SNORM:
2112 return ctx->API == API_OPENGL_COMPAT &&
2113 ctx->Extensions.EXT_texture_snorm &&
2114 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2115 case GL_LUMINANCE_SNORM:
2116 case GL_LUMINANCE8_SNORM:
2117 case GL_LUMINANCE16_SNORM:
2118 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2119 ? GL_LUMINANCE : 0;
2120 case GL_LUMINANCE_ALPHA_SNORM:
2121 case GL_LUMINANCE8_ALPHA8_SNORM:
2122 case GL_LUMINANCE16_ALPHA16_SNORM:
2123 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2124 ? GL_LUMINANCE_ALPHA : 0;
2125 case GL_INTENSITY_SNORM:
2126 case GL_INTENSITY8_SNORM:
2127 case GL_INTENSITY16_SNORM:
2128 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2129 ? GL_INTENSITY : 0;
2130
2131 case GL_R16F:
2132 case GL_R32F:
2133 return ((_mesa_is_desktop_gl(ctx) &&
2134 ctx->Extensions.ARB_texture_rg &&
2135 ctx->Extensions.ARB_texture_float) ||
2136 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2137 ? GL_RED : 0;
2138 case GL_RG16F:
2139 case GL_RG32F:
2140 return ((_mesa_is_desktop_gl(ctx) &&
2141 ctx->Extensions.ARB_texture_rg &&
2142 ctx->Extensions.ARB_texture_float) ||
2143 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2144 ? GL_RG : 0;
2145 case GL_RGB16F:
2146 case GL_RGB32F:
2147 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
2148 ? GL_RGB : 0;
2149 case GL_RGBA16F:
2150 case GL_RGBA32F:
2151 return ((_mesa_is_desktop_gl(ctx) &&
2152 ctx->Extensions.ARB_texture_float) ||
2153 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2154 ? GL_RGBA : 0;
2155 case GL_RGB9_E5:
2156 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_shared_exponent)
2157 ? GL_RGB: 0;
2158 case GL_ALPHA16F_ARB:
2159 case GL_ALPHA32F_ARB:
2160 return ctx->API == API_OPENGL_COMPAT &&
2161 ctx->Extensions.ARB_texture_float &&
2162 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2163 case GL_LUMINANCE16F_ARB:
2164 case GL_LUMINANCE32F_ARB:
2165 return ctx->API == API_OPENGL_COMPAT &&
2166 ctx->Extensions.ARB_texture_float &&
2167 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2168 case GL_LUMINANCE_ALPHA16F_ARB:
2169 case GL_LUMINANCE_ALPHA32F_ARB:
2170 return ctx->API == API_OPENGL_COMPAT &&
2171 ctx->Extensions.ARB_texture_float &&
2172 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2173 case GL_INTENSITY16F_ARB:
2174 case GL_INTENSITY32F_ARB:
2175 return ctx->API == API_OPENGL_COMPAT &&
2176 ctx->Extensions.ARB_texture_float &&
2177 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2178 case GL_R11F_G11F_B10F:
2179 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
2180 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2181 ? GL_RGB : 0;
2182
2183 case GL_RGBA8UI_EXT:
2184 case GL_RGBA16UI_EXT:
2185 case GL_RGBA32UI_EXT:
2186 case GL_RGBA8I_EXT:
2187 case GL_RGBA16I_EXT:
2188 case GL_RGBA32I_EXT:
2189 return ctx->Version >= 30
2190 || (_mesa_is_desktop_gl(ctx) &&
2191 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
2192
2193 case GL_RGB8UI_EXT:
2194 case GL_RGB16UI_EXT:
2195 case GL_RGB32UI_EXT:
2196 case GL_RGB8I_EXT:
2197 case GL_RGB16I_EXT:
2198 case GL_RGB32I_EXT:
2199 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
2200 ? GL_RGB : 0;
2201 case GL_R8UI:
2202 case GL_R8I:
2203 case GL_R16UI:
2204 case GL_R16I:
2205 case GL_R32UI:
2206 case GL_R32I:
2207 return ctx->Version >= 30
2208 || (_mesa_is_desktop_gl(ctx) &&
2209 ctx->Extensions.ARB_texture_rg &&
2210 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
2211
2212 case GL_RG8UI:
2213 case GL_RG8I:
2214 case GL_RG16UI:
2215 case GL_RG16I:
2216 case GL_RG32UI:
2217 case GL_RG32I:
2218 return ctx->Version >= 30
2219 || (_mesa_is_desktop_gl(ctx) &&
2220 ctx->Extensions.ARB_texture_rg &&
2221 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
2222
2223 case GL_INTENSITY8I_EXT:
2224 case GL_INTENSITY8UI_EXT:
2225 case GL_INTENSITY16I_EXT:
2226 case GL_INTENSITY16UI_EXT:
2227 case GL_INTENSITY32I_EXT:
2228 case GL_INTENSITY32UI_EXT:
2229 return ctx->API == API_OPENGL_COMPAT &&
2230 ctx->Extensions.EXT_texture_integer &&
2231 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2232
2233 case GL_LUMINANCE8I_EXT:
2234 case GL_LUMINANCE8UI_EXT:
2235 case GL_LUMINANCE16I_EXT:
2236 case GL_LUMINANCE16UI_EXT:
2237 case GL_LUMINANCE32I_EXT:
2238 case GL_LUMINANCE32UI_EXT:
2239 return ctx->API == API_OPENGL_COMPAT &&
2240 ctx->Extensions.EXT_texture_integer &&
2241 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2242
2243 case GL_LUMINANCE_ALPHA8I_EXT:
2244 case GL_LUMINANCE_ALPHA8UI_EXT:
2245 case GL_LUMINANCE_ALPHA16I_EXT:
2246 case GL_LUMINANCE_ALPHA16UI_EXT:
2247 case GL_LUMINANCE_ALPHA32I_EXT:
2248 case GL_LUMINANCE_ALPHA32UI_EXT:
2249 return ctx->API == API_OPENGL_COMPAT &&
2250 ctx->Extensions.EXT_texture_integer &&
2251 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2252
2253 case GL_ALPHA8I_EXT:
2254 case GL_ALPHA8UI_EXT:
2255 case GL_ALPHA16I_EXT:
2256 case GL_ALPHA16UI_EXT:
2257 case GL_ALPHA32I_EXT:
2258 case GL_ALPHA32UI_EXT:
2259 return ctx->API == API_OPENGL_COMPAT &&
2260 ctx->Extensions.EXT_texture_integer &&
2261 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2262
2263 case GL_RGB10_A2UI:
2264 return (_mesa_is_desktop_gl(ctx) &&
2265 ctx->Extensions.ARB_texture_rgb10_a2ui)
2266 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
2267
2268 case GL_RGB565:
2269 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
2270 ? GL_RGB : 0;
2271 default:
2272 return 0;
2273 }
2274 }
2275
2276
2277 /**
2278 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
2279 */
2280 static void
2281 invalidate_rb(GLuint key, void *data, void *userData)
2282 {
2283 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2284 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
2285
2286 /* If this is a user-created FBO */
2287 if (_mesa_is_user_fbo(fb)) {
2288 GLuint i;
2289 for (i = 0; i < BUFFER_COUNT; i++) {
2290 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2291 if (att->Type == GL_RENDERBUFFER &&
2292 att->Renderbuffer == rb) {
2293 /* Mark fb status as indeterminate to force re-validation */
2294 fb->_Status = 0;
2295 return;
2296 }
2297 }
2298 }
2299 }
2300
2301
2302 /** sentinal value, see below */
2303 #define NO_SAMPLES 1000
2304
2305 void
2306 _mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2307 GLenum internalFormat, GLsizei width,
2308 GLsizei height, GLsizei samples,
2309 GLsizei storageSamples)
2310 {
2311 const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2312
2313 assert(baseFormat != 0);
2314 assert(width >= 0 && width <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2315 assert(height >= 0 && height <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2316 assert(samples != NO_SAMPLES);
2317 if (samples != 0) {
2318 assert(samples > 0);
2319 assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
2320 internalFormat, samples,
2321 storageSamples) == GL_NO_ERROR);
2322 }
2323
2324 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2325
2326 if (rb->InternalFormat == internalFormat &&
2327 rb->Width == (GLuint) width &&
2328 rb->Height == (GLuint) height &&
2329 rb->NumSamples == samples &&
2330 rb->NumStorageSamples == storageSamples) {
2331 /* no change in allocation needed */
2332 return;
2333 }
2334
2335 /* These MUST get set by the AllocStorage func */
2336 rb->Format = MESA_FORMAT_NONE;
2337 rb->NumSamples = samples;
2338 rb->NumStorageSamples = storageSamples;
2339
2340 /* Now allocate the storage */
2341 assert(rb->AllocStorage);
2342 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
2343 /* No error - check/set fields now */
2344 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
2345 assert(rb->Width == (GLuint) width);
2346 assert(rb->Height == (GLuint) height);
2347 rb->InternalFormat = internalFormat;
2348 rb->_BaseFormat = baseFormat;
2349 assert(rb->_BaseFormat != 0);
2350 }
2351 else {
2352 /* Probably ran out of memory - clear the fields */
2353 rb->Width = 0;
2354 rb->Height = 0;
2355 rb->Format = MESA_FORMAT_NONE;
2356 rb->InternalFormat = GL_NONE;
2357 rb->_BaseFormat = GL_NONE;
2358 rb->NumSamples = 0;
2359 rb->NumStorageSamples = 0;
2360 }
2361
2362 /* Invalidate the framebuffers the renderbuffer is attached in. */
2363 if (rb->AttachedAnytime) {
2364 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
2365 }
2366 }
2367
2368 /**
2369 * Helper function used by renderbuffer_storage_direct() and
2370 * renderbuffer_storage_target().
2371 * samples will be NO_SAMPLES if called by a non-multisample function.
2372 */
2373 static void
2374 renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2375 GLenum internalFormat, GLsizei width,
2376 GLsizei height, GLsizei samples, GLsizei storageSamples,
2377 const char *func)
2378 {
2379 GLenum baseFormat;
2380 GLenum sample_count_error;
2381
2382 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2383 if (baseFormat == 0) {
2384 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
2385 func, _mesa_enum_to_string(internalFormat));
2386 return;
2387 }
2388
2389 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
2390 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
2391 width);
2392 return;
2393 }
2394
2395 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
2396 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
2397 height);
2398 return;
2399 }
2400
2401 if (samples == NO_SAMPLES) {
2402 /* NumSamples == 0 indicates non-multisampling */
2403 samples = 0;
2404 storageSamples = 0;
2405 }
2406 else {
2407 /* check the sample count;
2408 * note: driver may choose to use more samples than what's requested
2409 */
2410 sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
2411 internalFormat, samples, storageSamples);
2412
2413 /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
2414 *
2415 * "If a negative number is provided where an argument of type sizei or
2416 * sizeiptr is specified, the error INVALID VALUE is generated."
2417 */
2418 if (samples < 0 || storageSamples < 0) {
2419 sample_count_error = GL_INVALID_VALUE;
2420 }
2421
2422 if (sample_count_error != GL_NO_ERROR) {
2423 _mesa_error(ctx, sample_count_error,
2424 "%s(samples=%d, storageSamples=%d)", func, samples,
2425 storageSamples);
2426 return;
2427 }
2428 }
2429
2430 _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2431 storageSamples);
2432 }
2433
2434 /**
2435 * Helper function used by _mesa_NamedRenderbufferStorage*().
2436 * samples will be NO_SAMPLES if called by a non-multisample function.
2437 */
2438 static void
2439 renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
2440 GLsizei width, GLsizei height, GLsizei samples,
2441 GLsizei storageSamples, const char *func)
2442 {
2443 GET_CURRENT_CONTEXT(ctx);
2444
2445 if (MESA_VERBOSE & VERBOSE_API) {
2446 if (samples == NO_SAMPLES)
2447 _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
2448 func, renderbuffer,
2449 _mesa_enum_to_string(internalFormat),
2450 width, height);
2451 else
2452 _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
2453 func, renderbuffer,
2454 _mesa_enum_to_string(internalFormat),
2455 width, height, samples);
2456 }
2457
2458 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2459 if (!rb || rb == &DummyRenderbuffer) {
2460 /* ID was reserved, but no real renderbuffer object made yet */
2461 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
2462 func, renderbuffer);
2463 return;
2464 }
2465
2466 renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2467 storageSamples, func);
2468 }
2469
2470 /**
2471 * Helper function used by _mesa_RenderbufferStorage() and
2472 * _mesa_RenderbufferStorageMultisample().
2473 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
2474 */
2475 static void
2476 renderbuffer_storage_target(GLenum target, GLenum internalFormat,
2477 GLsizei width, GLsizei height, GLsizei samples,
2478 GLsizei storageSamples, const char *func)
2479 {
2480 GET_CURRENT_CONTEXT(ctx);
2481
2482 if (MESA_VERBOSE & VERBOSE_API) {
2483 if (samples == NO_SAMPLES)
2484 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
2485 func,
2486 _mesa_enum_to_string(target),
2487 _mesa_enum_to_string(internalFormat),
2488 width, height);
2489 else
2490 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
2491 func,
2492 _mesa_enum_to_string(target),
2493 _mesa_enum_to_string(internalFormat),
2494 width, height, samples);
2495 }
2496
2497 if (target != GL_RENDERBUFFER_EXT) {
2498 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
2499 return;
2500 }
2501
2502 if (!ctx->CurrentRenderbuffer) {
2503 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
2504 func);
2505 return;
2506 }
2507
2508 renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
2509 height, samples, storageSamples, func);
2510 }
2511
2512
2513 void GLAPIENTRY
2514 _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
2515 {
2516 struct gl_renderbuffer *rb;
2517 GET_CURRENT_CONTEXT(ctx);
2518
2519 if (!ctx->Extensions.OES_EGL_image) {
2520 _mesa_error(ctx, GL_INVALID_OPERATION,
2521 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
2522 return;
2523 }
2524
2525 if (target != GL_RENDERBUFFER) {
2526 _mesa_error(ctx, GL_INVALID_ENUM,
2527 "EGLImageTargetRenderbufferStorageOES");
2528 return;
2529 }
2530
2531 rb = ctx->CurrentRenderbuffer;
2532 if (!rb) {
2533 _mesa_error(ctx, GL_INVALID_OPERATION,
2534 "EGLImageTargetRenderbufferStorageOES");
2535 return;
2536 }
2537
2538 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2539
2540 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
2541 }
2542
2543
2544 /**
2545 * Helper function for _mesa_GetRenderbufferParameteriv() and
2546 * _mesa_GetFramebufferAttachmentParameteriv()
2547 * We have to be careful to respect the base format. For example, if a
2548 * renderbuffer/texture was created with internalFormat=GL_RGB but the
2549 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
2550 * we need to return zero.
2551 */
2552 static GLint
2553 get_component_bits(GLenum pname, GLenum baseFormat, mesa_format format)
2554 {
2555 if (_mesa_base_format_has_channel(baseFormat, pname))
2556 return _mesa_get_format_bits(format, pname);
2557 else
2558 return 0;
2559 }
2560
2561
2562
2563 void GLAPIENTRY
2564 _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
2565 GLsizei width, GLsizei height)
2566 {
2567 /* GL_ARB_fbo says calling this function is equivalent to calling
2568 * glRenderbufferStorageMultisample() with samples=0. We pass in
2569 * a token value here just for error reporting purposes.
2570 */
2571 renderbuffer_storage_target(target, internalFormat, width, height,
2572 NO_SAMPLES, 0, "glRenderbufferStorage");
2573 }
2574
2575
2576 void GLAPIENTRY
2577 _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
2578 GLenum internalFormat,
2579 GLsizei width, GLsizei height)
2580 {
2581 renderbuffer_storage_target(target, internalFormat, width, height,
2582 samples, samples,
2583 "glRenderbufferStorageMultisample");
2584 }
2585
2586
2587 void GLAPIENTRY
2588 _mesa_RenderbufferStorageMultisampleAdvancedAMD(
2589 GLenum target, GLsizei samples, GLsizei storageSamples,
2590 GLenum internalFormat, GLsizei width, GLsizei height)
2591 {
2592 renderbuffer_storage_target(target, internalFormat, width, height,
2593 samples, storageSamples,
2594 "glRenderbufferStorageMultisampleAdvancedAMD");
2595 }
2596
2597
2598 /**
2599 * OpenGL ES version of glRenderBufferStorage.
2600 */
2601 void GLAPIENTRY
2602 _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
2603 GLsizei width, GLsizei height)
2604 {
2605 switch (internalFormat) {
2606 case GL_RGB565:
2607 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
2608 /* choose a closest format */
2609 internalFormat = GL_RGB5;
2610 break;
2611 default:
2612 break;
2613 }
2614
2615 renderbuffer_storage_target(target, internalFormat, width, height, 0, 0,
2616 "glRenderbufferStorageEXT");
2617 }
2618
2619 void GLAPIENTRY
2620 _mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
2621 GLsizei width, GLsizei height)
2622 {
2623 /* GL_ARB_fbo says calling this function is equivalent to calling
2624 * glRenderbufferStorageMultisample() with samples=0. We pass in
2625 * a token value here just for error reporting purposes.
2626 */
2627 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2628 NO_SAMPLES, 0, "glNamedRenderbufferStorage");
2629 }
2630
2631 void GLAPIENTRY
2632 _mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
2633 GLenum internalformat,
2634 GLsizei width, GLsizei height)
2635 {
2636 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2637 samples, samples,
2638 "glNamedRenderbufferStorageMultisample");
2639 }
2640
2641
2642 void GLAPIENTRY
2643 _mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
2644 GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
2645 GLenum internalformat, GLsizei width, GLsizei height)
2646 {
2647 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2648 samples, storageSamples,
2649 "glNamedRenderbufferStorageMultisampleAdvancedAMD");
2650 }
2651
2652
2653 static void
2654 get_render_buffer_parameteriv(struct gl_context *ctx,
2655 struct gl_renderbuffer *rb, GLenum pname,
2656 GLint *params, const char *func)
2657 {
2658 /* No need to flush here since we're just quering state which is
2659 * not effected by rendering.
2660 */
2661
2662 switch (pname) {
2663 case GL_RENDERBUFFER_WIDTH_EXT:
2664 *params = rb->Width;
2665 return;
2666 case GL_RENDERBUFFER_HEIGHT_EXT:
2667 *params = rb->Height;
2668 return;
2669 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
2670 *params = rb->InternalFormat;
2671 return;
2672 case GL_RENDERBUFFER_RED_SIZE_EXT:
2673 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
2674 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
2675 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
2676 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
2677 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
2678 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
2679 return;
2680 case GL_RENDERBUFFER_SAMPLES:
2681 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
2682 || _mesa_is_gles3(ctx)) {
2683 *params = rb->NumSamples;
2684 return;
2685 }
2686 break;
2687 case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
2688 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
2689 *params = rb->NumStorageSamples;
2690 return;
2691 }
2692 break;
2693 }
2694
2695 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
2696 _mesa_enum_to_string(pname));
2697 }
2698
2699
2700 void GLAPIENTRY
2701 _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
2702 {
2703 GET_CURRENT_CONTEXT(ctx);
2704
2705 if (target != GL_RENDERBUFFER_EXT) {
2706 _mesa_error(ctx, GL_INVALID_ENUM,
2707 "glGetRenderbufferParameterivEXT(target)");
2708 return;
2709 }
2710
2711 if (!ctx->CurrentRenderbuffer) {
2712 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
2713 "(no renderbuffer bound)");
2714 return;
2715 }
2716
2717 get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
2718 params, "glGetRenderbufferParameteriv");
2719 }
2720
2721
2722 void GLAPIENTRY
2723 _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
2724 GLint *params)
2725 {
2726 GET_CURRENT_CONTEXT(ctx);
2727
2728 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2729 if (!rb || rb == &DummyRenderbuffer) {
2730 /* ID was reserved, but no real renderbuffer object made yet */
2731 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
2732 "(invalid renderbuffer %i)", renderbuffer);
2733 return;
2734 }
2735
2736 get_render_buffer_parameteriv(ctx, rb, pname, params,
2737 "glGetNamedRenderbufferParameteriv");
2738 }
2739
2740
2741 GLboolean GLAPIENTRY
2742 _mesa_IsFramebuffer(GLuint framebuffer)
2743 {
2744 GET_CURRENT_CONTEXT(ctx);
2745 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2746 if (framebuffer) {
2747 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
2748 if (rb != NULL && rb != &DummyFramebuffer)
2749 return GL_TRUE;
2750 }
2751 return GL_FALSE;
2752 }
2753
2754
2755 /**
2756 * Check if any of the attachments of the given framebuffer are textures
2757 * (render to texture). Call ctx->Driver.RenderTexture() for such
2758 * attachments.
2759 */
2760 static void
2761 check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
2762 {
2763 GLuint i;
2764 assert(ctx->Driver.RenderTexture);
2765
2766 if (_mesa_is_winsys_fbo(fb))
2767 return; /* can't render to texture with winsys framebuffers */
2768
2769 for (i = 0; i < BUFFER_COUNT; i++) {
2770 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2771 if (att->Texture && att->Renderbuffer->TexImage
2772 && driver_RenderTexture_is_safe(att)) {
2773 ctx->Driver.RenderTexture(ctx, fb, att);
2774 }
2775 }
2776 }
2777
2778
2779 /**
2780 * Examine all the framebuffer's attachments to see if any are textures.
2781 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
2782 * notify the device driver that the texture image may have changed.
2783 */
2784 static void
2785 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
2786 {
2787 /* Skip if we know NeedsFinishRenderTexture won't be set. */
2788 if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
2789 return;
2790
2791 if (ctx->Driver.FinishRenderTexture) {
2792 GLuint i;
2793 for (i = 0; i < BUFFER_COUNT; i++) {
2794 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2795 struct gl_renderbuffer *rb = att->Renderbuffer;
2796 if (rb && rb->NeedsFinishRenderTexture) {
2797 ctx->Driver.FinishRenderTexture(ctx, rb);
2798 }
2799 }
2800 }
2801 }
2802
2803
2804 static void
2805 bind_framebuffer(GLenum target, GLuint framebuffer)
2806 {
2807 struct gl_framebuffer *newDrawFb, *newReadFb;
2808 GLboolean bindReadBuf, bindDrawBuf;
2809 GET_CURRENT_CONTEXT(ctx);
2810
2811 switch (target) {
2812 case GL_DRAW_FRAMEBUFFER_EXT:
2813 bindDrawBuf = GL_TRUE;
2814 bindReadBuf = GL_FALSE;
2815 break;
2816 case GL_READ_FRAMEBUFFER_EXT:
2817 bindDrawBuf = GL_FALSE;
2818 bindReadBuf = GL_TRUE;
2819 break;
2820 case GL_FRAMEBUFFER_EXT:
2821 bindDrawBuf = GL_TRUE;
2822 bindReadBuf = GL_TRUE;
2823 break;
2824 default:
2825 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2826 return;
2827 }
2828
2829 if (framebuffer) {
2830 /* Binding a user-created framebuffer object */
2831 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
2832 if (newDrawFb == &DummyFramebuffer) {
2833 /* ID was reserved, but no real framebuffer object made yet */
2834 newDrawFb = NULL;
2835 }
2836 else if (!newDrawFb && ctx->API == API_OPENGL_CORE) {
2837 /* All FBO IDs must be Gen'd */
2838 _mesa_error(ctx, GL_INVALID_OPERATION,
2839 "glBindFramebuffer(non-gen name)");
2840 return;
2841 }
2842
2843 if (!newDrawFb) {
2844 /* create new framebuffer object */
2845 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
2846 if (!newDrawFb) {
2847 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
2848 return;
2849 }
2850 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
2851 }
2852 newReadFb = newDrawFb;
2853 }
2854 else {
2855 /* Binding the window system framebuffer (which was originally set
2856 * with MakeCurrent).
2857 */
2858 newDrawFb = ctx->WinSysDrawBuffer;
2859 newReadFb = ctx->WinSysReadBuffer;
2860 }
2861
2862 _mesa_bind_framebuffers(ctx,
2863 bindDrawBuf ? newDrawFb : ctx->DrawBuffer,
2864 bindReadBuf ? newReadFb : ctx->ReadBuffer);
2865 }
2866
2867 void
2868 _mesa_bind_framebuffers(struct gl_context *ctx,
2869 struct gl_framebuffer *newDrawFb,
2870 struct gl_framebuffer *newReadFb)
2871 {
2872 struct gl_framebuffer *const oldDrawFb = ctx->DrawBuffer;
2873 struct gl_framebuffer *const oldReadFb = ctx->ReadBuffer;
2874 const bool bindDrawBuf = oldDrawFb != newDrawFb;
2875 const bool bindReadBuf = oldReadFb != newReadFb;
2876
2877 assert(newDrawFb);
2878 assert(newDrawFb != &DummyFramebuffer);
2879
2880 /*
2881 * OK, now bind the new Draw/Read framebuffers, if they're changing.
2882 *
2883 * We also check if we're beginning and/or ending render-to-texture.
2884 * When a framebuffer with texture attachments is unbound, call
2885 * ctx->Driver.FinishRenderTexture().
2886 * When a framebuffer with texture attachments is bound, call
2887 * ctx->Driver.RenderTexture().
2888 *
2889 * Note that if the ReadBuffer has texture attachments we don't consider
2890 * that a render-to-texture case.
2891 */
2892 if (bindReadBuf) {
2893 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2894
2895 /* check if old readbuffer was render-to-texture */
2896 check_end_texture_render(ctx, oldReadFb);
2897
2898 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
2899 }
2900
2901 if (bindDrawBuf) {
2902 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2903 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
2904
2905 /* check if old framebuffer had any texture attachments */
2906 if (oldDrawFb)
2907 check_end_texture_render(ctx, oldDrawFb);
2908
2909 /* check if newly bound framebuffer has any texture attachments */
2910 check_begin_texture_render(ctx, newDrawFb);
2911
2912 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
2913 }
2914
2915 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
2916 /* The few classic drivers that actually hook this function really only
2917 * want to know if the draw framebuffer changed.
2918 */
2919 ctx->Driver.BindFramebuffer(ctx,
2920 bindDrawBuf ? GL_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
2921 newDrawFb, newReadFb);
2922 }
2923 }
2924
2925 void GLAPIENTRY
2926 _mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
2927 {
2928 /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
2929 * point, but they allow the use of user-generated names.
2930 */
2931 bind_framebuffer(target, framebuffer);
2932 }
2933
2934
2935 void GLAPIENTRY
2936 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
2937 {
2938 bind_framebuffer(target, framebuffer);
2939 }
2940
2941
2942 void GLAPIENTRY
2943 _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
2944 {
2945 GLint i;
2946 GET_CURRENT_CONTEXT(ctx);
2947
2948 if (n < 0) {
2949 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
2950 return;
2951 }
2952
2953 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2954
2955 for (i = 0; i < n; i++) {
2956 if (framebuffers[i] > 0) {
2957 struct gl_framebuffer *fb;
2958 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
2959 if (fb) {
2960 assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
2961
2962 /* check if deleting currently bound framebuffer object */
2963 if (fb == ctx->DrawBuffer) {
2964 /* bind default */
2965 assert(fb->RefCount >= 2);
2966 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2967 }
2968 if (fb == ctx->ReadBuffer) {
2969 /* bind default */
2970 assert(fb->RefCount >= 2);
2971 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
2972 }
2973
2974 /* remove from hash table immediately, to free the ID */
2975 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
2976
2977 if (fb != &DummyFramebuffer) {
2978 /* But the object will not be freed until it's no longer
2979 * bound in any context.
2980 */
2981 _mesa_reference_framebuffer(&fb, NULL);
2982 }
2983 }
2984 }
2985 }
2986 }
2987
2988
2989 /**
2990 * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
2991 * It is not exposed to the rest of Mesa to encourage the use of
2992 * nameless buffers in driver internals.
2993 */
2994 static void
2995 create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
2996 {
2997 GET_CURRENT_CONTEXT(ctx);
2998 GLuint first;
2999 GLint i;
3000 struct gl_framebuffer *fb;
3001
3002 const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
3003
3004 if (n < 0) {
3005 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
3006 return;
3007 }
3008
3009 if (!framebuffers)
3010 return;
3011
3012 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
3013
3014 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
3015
3016 for (i = 0; i < n; i++) {
3017 GLuint name = first + i;
3018 framebuffers[i] = name;
3019
3020 if (dsa) {
3021 fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
3022 if (!fb) {
3023 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
3024 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
3025 return;
3026 }
3027 }
3028 else
3029 fb = &DummyFramebuffer;
3030
3031 _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, name, fb);
3032 }
3033
3034 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
3035 }
3036
3037
3038 void GLAPIENTRY
3039 _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
3040 {
3041 create_framebuffers(n, framebuffers, false);
3042 }
3043
3044
3045 void GLAPIENTRY
3046 _mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
3047 {
3048 create_framebuffers(n, framebuffers, true);
3049 }
3050
3051
3052 GLenum
3053 _mesa_check_framebuffer_status(struct gl_context *ctx,
3054 struct gl_framebuffer *buffer)
3055 {
3056 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
3057
3058 if (_mesa_is_winsys_fbo(buffer)) {
3059 /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
3060 if (buffer != &IncompleteFramebuffer) {
3061 return GL_FRAMEBUFFER_COMPLETE_EXT;
3062 } else {
3063 return GL_FRAMEBUFFER_UNDEFINED;
3064 }
3065 }
3066
3067 /* No need to flush here */
3068
3069 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
3070 _mesa_test_framebuffer_completeness(ctx, buffer);
3071 }
3072
3073 return buffer->_Status;
3074 }
3075
3076
3077 GLenum GLAPIENTRY
3078 _mesa_CheckFramebufferStatus_no_error(GLenum target)
3079 {
3080 GET_CURRENT_CONTEXT(ctx);
3081
3082 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3083 return _mesa_check_framebuffer_status(ctx, fb);
3084 }
3085
3086
3087 GLenum GLAPIENTRY
3088 _mesa_CheckFramebufferStatus(GLenum target)
3089 {
3090 struct gl_framebuffer *fb;
3091 GET_CURRENT_CONTEXT(ctx);
3092
3093 if (MESA_VERBOSE & VERBOSE_API)
3094 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
3095 _mesa_enum_to_string(target));
3096
3097 fb = get_framebuffer_target(ctx, target);
3098 if (!fb) {
3099 _mesa_error(ctx, GL_INVALID_ENUM,
3100 "glCheckFramebufferStatus(invalid target %s)",
3101 _mesa_enum_to_string(target));
3102 return 0;
3103 }
3104
3105 return _mesa_check_framebuffer_status(ctx, fb);
3106 }
3107
3108
3109 GLenum GLAPIENTRY
3110 _mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
3111 {
3112 struct gl_framebuffer *fb;
3113 GET_CURRENT_CONTEXT(ctx);
3114
3115 /* Validate the target (for conformance's sake) and grab a reference to the
3116 * default framebuffer in case framebuffer = 0.
3117 * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
3118 * (30.10.2014, PDF page 336) says:
3119 * "If framebuffer is zero, then the status of the default read or
3120 * draw framebuffer (as determined by target) is returned."
3121 */
3122 switch (target) {
3123 case GL_DRAW_FRAMEBUFFER:
3124 case GL_FRAMEBUFFER:
3125 fb = ctx->WinSysDrawBuffer;
3126 break;
3127 case GL_READ_FRAMEBUFFER:
3128 fb = ctx->WinSysReadBuffer;
3129 break;
3130 default:
3131 _mesa_error(ctx, GL_INVALID_ENUM,
3132 "glCheckNamedFramebufferStatus(invalid target %s)",
3133 _mesa_enum_to_string(target));
3134 return 0;
3135 }
3136
3137 if (framebuffer) {
3138 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
3139 "glCheckNamedFramebufferStatus");
3140 if (!fb)
3141 return 0;
3142 }
3143
3144 return _mesa_check_framebuffer_status(ctx, fb);
3145 }
3146
3147
3148 /**
3149 * Replicate the src attachment point. Used by framebuffer_texture() when
3150 * the same texture is attached at GL_DEPTH_ATTACHMENT and
3151 * GL_STENCIL_ATTACHMENT.
3152 */
3153 static void
3154 reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
3155 gl_buffer_index dst,
3156 gl_buffer_index src)
3157 {
3158 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
3159 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
3160
3161 assert(src_att->Texture != NULL);
3162 assert(src_att->Renderbuffer != NULL);
3163
3164 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
3165 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
3166 dst_att->Type = src_att->Type;
3167 dst_att->Complete = src_att->Complete;
3168 dst_att->TextureLevel = src_att->TextureLevel;
3169 dst_att->CubeMapFace = src_att->CubeMapFace;
3170 dst_att->Zoffset = src_att->Zoffset;
3171 dst_att->Layered = src_att->Layered;
3172 }
3173
3174
3175 static struct gl_texture_object *
3176 get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
3177 {
3178 if (!texture)
3179 return NULL;
3180
3181 return _mesa_lookup_texture(ctx, texture);
3182 }
3183
3184
3185 /**
3186 * Common code called by gl*FramebufferTexture*() to retrieve the correct
3187 * texture object pointer.
3188 *
3189 * \param texObj where the pointer to the texture object is returned. Note
3190 * that a successful call may return texObj = NULL.
3191 *
3192 * \return true if no errors, false if errors
3193 */
3194 static bool
3195 get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
3196 bool layered, const char *caller,
3197 struct gl_texture_object **texObj)
3198 {
3199 *texObj = NULL; /* This will get returned if texture = 0. */
3200
3201 if (!texture)
3202 return true;
3203
3204 *texObj = _mesa_lookup_texture(ctx, texture);
3205 if (*texObj == NULL || (*texObj)->Target == 0) {
3206 /* Can't render to a non-existent texture object.
3207 *
3208 * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
3209 * Managing Framebuffer Objects specifies a different error
3210 * depending upon the calling function (PDF pages 325-328).
3211 * *FramebufferTexture (where layered = GL_TRUE) throws invalid
3212 * value, while the other commands throw invalid operation (where
3213 * layered = GL_FALSE).
3214 */
3215 const GLenum error = layered ? GL_INVALID_VALUE :
3216 GL_INVALID_OPERATION;
3217 _mesa_error(ctx, error,
3218 "%s(non-existent texture %u)", caller, texture);
3219 return false;
3220 }
3221
3222 return true;
3223 }
3224
3225
3226 /**
3227 * Common code called by gl*FramebufferTexture() to verify the texture target
3228 * and decide whether or not the attachment should truly be considered
3229 * layered.
3230 *
3231 * \param layered true if attachment should be considered layered, false if
3232 * not
3233 *
3234 * \return true if no errors, false if errors
3235 */
3236 static bool
3237 check_layered_texture_target(struct gl_context *ctx, GLenum target,
3238 const char *caller, GLboolean *layered)
3239 {
3240 *layered = GL_TRUE;
3241
3242 switch (target) {
3243 case GL_TEXTURE_3D:
3244 case GL_TEXTURE_1D_ARRAY_EXT:
3245 case GL_TEXTURE_2D_ARRAY_EXT:
3246 case GL_TEXTURE_CUBE_MAP:
3247 case GL_TEXTURE_CUBE_MAP_ARRAY:
3248 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3249 return true;
3250 case GL_TEXTURE_1D:
3251 case GL_TEXTURE_2D:
3252 case GL_TEXTURE_RECTANGLE:
3253 case GL_TEXTURE_2D_MULTISAMPLE:
3254 /* These texture types are valid to pass to
3255 * glFramebufferTexture(), but since they aren't layered, it
3256 * is equivalent to calling glFramebufferTexture{1D,2D}().
3257 */
3258 *layered = GL_FALSE;
3259 return true;
3260 }
3261
3262 _mesa_error(ctx, GL_INVALID_OPERATION,
3263 "%s(invalid texture target %s)", caller,
3264 _mesa_enum_to_string(target));
3265 return false;
3266 }
3267
3268
3269 /**
3270 * Common code called by gl*FramebufferTextureLayer() to verify the texture
3271 * target.
3272 *
3273 * \return true if no errors, false if errors
3274 */
3275 static bool
3276 check_texture_target(struct gl_context *ctx, GLenum target,
3277 const char *caller)
3278 {
3279 /* We're being called by glFramebufferTextureLayer().
3280 * The only legal texture types for that function are 3D,
3281 * cube-map, and 1D/2D/cube-map array textures.
3282 *
3283 * We don't need to check for GL_ARB_texture_cube_map_array because the
3284 * application wouldn't have been able to create a texture with a
3285 * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
3286 */
3287 switch (target) {
3288 case GL_TEXTURE_3D:
3289 case GL_TEXTURE_1D_ARRAY:
3290 case GL_TEXTURE_2D_ARRAY:
3291 case GL_TEXTURE_CUBE_MAP_ARRAY:
3292 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3293 return true;
3294 case GL_TEXTURE_CUBE_MAP:
3295 /* GL_TEXTURE_CUBE_MAP is only allowed by OpenGL 4.5 here, which
3296 * includes the DSA API.
3297 *
3298 * Because DSA is only enabled for GL 3.1+ and this can be called
3299 * from _mesa_FramebufferTextureLayer in compatibility profile,
3300 * we need to check the version.
3301 */
3302 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
3303 }
3304
3305 _mesa_error(ctx, GL_INVALID_OPERATION,
3306 "%s(invalid texture target %s)", caller,
3307 _mesa_enum_to_string(target));
3308 return false;
3309 }
3310
3311
3312 /**
3313 * Common code called by glFramebufferTexture*D() to verify the texture
3314 * target.
3315 *
3316 * \return true if no errors, false if errors
3317 */
3318 static bool
3319 check_textarget(struct gl_context *ctx, int dims, GLenum target,
3320 GLenum textarget, const char *caller)
3321 {
3322 bool err = false;
3323
3324 switch (textarget) {
3325 case GL_TEXTURE_1D:
3326 err = dims != 1;
3327 break;
3328 case GL_TEXTURE_1D_ARRAY:
3329 err = dims != 1 || !ctx->Extensions.EXT_texture_array;
3330 break;
3331 case GL_TEXTURE_2D:
3332 err = dims != 2;
3333 break;
3334 case GL_TEXTURE_2D_ARRAY:
3335 err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
3336 (_mesa_is_gles(ctx) && ctx->Version < 30);
3337 break;
3338 case GL_TEXTURE_2D_MULTISAMPLE:
3339 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3340 err = dims != 2 ||
3341 !ctx->Extensions.ARB_texture_multisample ||
3342 (_mesa_is_gles(ctx) && ctx->Version < 31);
3343 break;
3344 case GL_TEXTURE_RECTANGLE:
3345 err = dims != 2 || _mesa_is_gles(ctx) ||
3346 !ctx->Extensions.NV_texture_rectangle;
3347 break;
3348 case GL_TEXTURE_CUBE_MAP:
3349 case GL_TEXTURE_CUBE_MAP_ARRAY:
3350 err = true;
3351 break;
3352 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3353 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3354 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3355 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3356 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3357 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3358 err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
3359 break;
3360 case GL_TEXTURE_3D:
3361 err = dims != 3;
3362 break;
3363 default:
3364 _mesa_error(ctx, GL_INVALID_ENUM,
3365 "%s(unknown textarget 0x%x)", caller, textarget);
3366 return false;
3367 }
3368
3369 if (err) {
3370 _mesa_error(ctx, GL_INVALID_OPERATION,
3371 "%s(invalid textarget %s)",
3372 caller, _mesa_enum_to_string(textarget));
3373 return false;
3374 }
3375
3376 /* Make sure textarget is consistent with the texture's type */
3377 err = (target == GL_TEXTURE_CUBE_MAP) ?
3378 !_mesa_is_cube_face(textarget): (target != textarget);
3379
3380 if (err) {
3381 _mesa_error(ctx, GL_INVALID_OPERATION,
3382 "%s(mismatched texture target)", caller);
3383 return false;
3384 }
3385
3386 return true;
3387 }
3388
3389
3390 /**
3391 * Common code called by gl*FramebufferTextureLayer() and
3392 * glFramebufferTexture3D() to validate the layer.
3393 *
3394 * \return true if no errors, false if errors
3395 */
3396 static bool
3397 check_layer(struct gl_context *ctx, GLenum target, GLint layer,
3398 const char *caller)
3399 {
3400 /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
3401 * spec says:
3402 *
3403 * "An INVALID_VALUE error is generated if texture is non-zero
3404 * and layer is negative."
3405 */
3406 if (layer < 0) {
3407 _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
3408 return false;
3409 }
3410
3411 if (target == GL_TEXTURE_3D) {
3412 const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
3413 if (layer >= maxSize) {
3414 _mesa_error(ctx, GL_INVALID_VALUE,
3415 "%s(invalid layer %u)", caller, layer);
3416 return false;
3417 }
3418 }
3419 else if ((target == GL_TEXTURE_1D_ARRAY) ||
3420 (target == GL_TEXTURE_2D_ARRAY) ||
3421 (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
3422 (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
3423 if (layer >= ctx->Const.MaxArrayTextureLayers) {
3424 _mesa_error(ctx, GL_INVALID_VALUE,
3425 "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
3426 caller, layer);
3427 return false;
3428 }
3429 }
3430 else if (target == GL_TEXTURE_CUBE_MAP) {
3431 if (layer >= 6) {
3432 _mesa_error(ctx, GL_INVALID_VALUE,
3433 "%s(layer %u >= 6)", caller, layer);
3434 return false;
3435 }
3436 }
3437
3438 return true;
3439 }
3440
3441
3442 /**
3443 * Common code called by all gl*FramebufferTexture*() entry points to verify
3444 * the level.
3445 *
3446 * \return true if no errors, false if errors
3447 */
3448 static bool
3449 check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
3450 GLenum target, GLint level, const char *caller)
3451 {
3452 /* Section 9.2.8 of the OpenGL 4.6 specification says:
3453 *
3454 * "If texture refers to an immutable-format texture, level must be
3455 * greater than or equal to zero and smaller than the value of
3456 * TEXTURE_VIEW_NUM_LEVELS for texture."
3457 */
3458 const int max_levels = texObj->Immutable ? texObj->ImmutableLevels :
3459 _mesa_max_texture_levels(ctx, target);
3460
3461 if (level < 0 || level >= max_levels) {
3462 _mesa_error(ctx, GL_INVALID_VALUE,
3463 "%s(invalid level %d)", caller, level);
3464 return false;
3465 }
3466
3467 return true;
3468 }
3469
3470
3471 struct gl_renderbuffer_attachment *
3472 _mesa_get_and_validate_attachment(struct gl_context *ctx,
3473 struct gl_framebuffer *fb,
3474 GLenum attachment, const char *caller)
3475 {
3476 /* The window-system framebuffer object is immutable */
3477 if (_mesa_is_winsys_fbo(fb)) {
3478 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
3479 caller);
3480 return NULL;
3481 }
3482
3483 /* Not a hash lookup, so we can afford to get the attachment here. */
3484 bool is_color_attachment;
3485 struct gl_renderbuffer_attachment *att =
3486 get_attachment(ctx, fb, attachment, &is_color_attachment);
3487 if (att == NULL) {
3488 if (is_color_attachment) {
3489 _mesa_error(ctx, GL_INVALID_OPERATION,
3490 "%s(invalid color attachment %s)", caller,
3491 _mesa_enum_to_string(attachment));
3492 } else {
3493 _mesa_error(ctx, GL_INVALID_ENUM,
3494 "%s(invalid attachment %s)", caller,
3495 _mesa_enum_to_string(attachment));
3496 }
3497 return NULL;
3498 }
3499
3500 return att;
3501 }
3502
3503
3504 void
3505 _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
3506 GLenum attachment,
3507 struct gl_renderbuffer_attachment *att,
3508 struct gl_texture_object *texObj, GLenum textarget,
3509 GLint level, GLsizei samples,
3510 GLuint layer, GLboolean layered)
3511 {
3512 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3513
3514 simple_mtx_lock(&fb->Mutex);
3515 if (texObj) {
3516 if (attachment == GL_DEPTH_ATTACHMENT &&
3517 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
3518 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
3519 _mesa_tex_target_to_face(textarget) ==
3520 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
3521 samples == fb->Attachment[BUFFER_STENCIL].NumSamples &&
3522 layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
3523 /* The texture object is already attached to the stencil attachment
3524 * point. Don't create a new renderbuffer; just reuse the stencil
3525 * attachment's. This is required to prevent a GL error in
3526 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
3527 */
3528 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
3529 BUFFER_STENCIL);
3530 } else if (attachment == GL_STENCIL_ATTACHMENT &&
3531 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
3532 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
3533 _mesa_tex_target_to_face(textarget) ==
3534 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
3535 samples == fb->Attachment[BUFFER_DEPTH].NumSamples &&
3536 layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
3537 /* As above, but with depth and stencil transposed. */
3538 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
3539 BUFFER_DEPTH);
3540 } else {
3541 set_texture_attachment(ctx, fb, att, texObj, textarget,
3542 level, samples, layer, layered);
3543
3544 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3545 /* Above we created a new renderbuffer and attached it to the
3546 * depth attachment point. Now attach it to the stencil attachment
3547 * point too.
3548 */
3549 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3550 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
3551 BUFFER_DEPTH);
3552 }
3553 }
3554
3555 /* Set the render-to-texture flag. We'll check this flag in
3556 * glTexImage() and friends to determine if we need to revalidate
3557 * any FBOs that might be rendering into this texture.
3558 * This flag never gets cleared since it's non-trivial to determine
3559 * when all FBOs might be done rendering to this texture. That's OK
3560 * though since it's uncommon to render to a texture then repeatedly
3561 * call glTexImage() to change images in the texture.
3562 */
3563 texObj->_RenderToTexture = GL_TRUE;
3564 }
3565 else {
3566 remove_attachment(ctx, att);
3567 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3568 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3569 remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
3570 }
3571 }
3572
3573 invalidate_framebuffer(fb);
3574
3575 simple_mtx_unlock(&fb->Mutex);
3576 }
3577
3578
3579 static void
3580 framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
3581 GLenum textarget, GLuint texture,
3582 GLint level, GLint layer)
3583 {
3584 GET_CURRENT_CONTEXT(ctx);
3585
3586 /* Get the framebuffer object */
3587 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3588
3589 /* Get the texture object */
3590 struct gl_texture_object *texObj =
3591 get_texture_for_framebuffer(ctx, texture);
3592
3593 struct gl_renderbuffer_attachment *att =
3594 get_attachment(ctx, fb, attachment, NULL);
3595
3596 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3597 level, 0, layer, GL_FALSE);
3598 }
3599
3600
3601 static void
3602 framebuffer_texture_with_dims(int dims, GLenum target,
3603 GLenum attachment, GLenum textarget,
3604 GLuint texture, GLint level, GLsizei samples,
3605 GLint layer, const char *caller)
3606 {
3607 GET_CURRENT_CONTEXT(ctx);
3608 struct gl_framebuffer *fb;
3609 struct gl_texture_object *texObj;
3610
3611 /* Get the framebuffer object */
3612 fb = get_framebuffer_target(ctx, target);
3613 if (!fb) {
3614 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
3615 _mesa_enum_to_string(target));
3616 return;
3617 }
3618
3619 /* Get the texture object */
3620 if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
3621 return;
3622
3623 if (texObj) {
3624 if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
3625 return;
3626
3627 if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
3628 return;
3629
3630 if (!check_level(ctx, texObj, textarget, level, caller))
3631 return;
3632 }
3633
3634 struct gl_renderbuffer_attachment *att =
3635 _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
3636 if (!att)
3637 return;
3638
3639 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3640 level, samples, layer, GL_FALSE);
3641 }
3642
3643
3644 void GLAPIENTRY
3645 _mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
3646 GLenum textarget, GLuint texture,
3647 GLint level)
3648 {
3649 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3650 texture, level, 0);
3651 }
3652
3653
3654 void GLAPIENTRY
3655 _mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
3656 GLenum textarget, GLuint texture, GLint level)
3657 {
3658 framebuffer_texture_with_dims(1, target, attachment, textarget, texture,
3659 level, 0, 0, "glFramebufferTexture1D");
3660 }
3661
3662
3663 void GLAPIENTRY
3664 _mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
3665 GLenum textarget, GLuint texture,
3666 GLint level)
3667 {
3668 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3669 texture, level, 0);
3670 }
3671
3672
3673 void GLAPIENTRY
3674 _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
3675 GLenum textarget, GLuint texture, GLint level)
3676 {
3677 framebuffer_texture_with_dims(2, target, attachment, textarget, texture,
3678 level, 0, 0, "glFramebufferTexture2D");
3679 }
3680
3681
3682 void GLAPIENTRY
3683 _mesa_FramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment,
3684 GLenum textarget, GLuint texture,
3685 GLint level, GLsizei samples)
3686 {
3687 framebuffer_texture_with_dims(2, target, attachment, textarget, texture,
3688 level, samples, 0, "glFramebufferTexture2DMultisampleEXT");
3689 }
3690
3691
3692 void GLAPIENTRY
3693 _mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
3694 GLenum textarget, GLuint texture,
3695 GLint level, GLint layer)
3696 {
3697 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3698 texture, level, layer);
3699 }
3700
3701
3702 void GLAPIENTRY
3703 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
3704 GLenum textarget, GLuint texture,
3705 GLint level, GLint layer)
3706 {
3707 framebuffer_texture_with_dims(3, target, attachment, textarget, texture,
3708 level, 0, layer, "glFramebufferTexture3D");
3709 }
3710
3711
3712 static ALWAYS_INLINE void
3713 frame_buffer_texture(GLuint framebuffer, GLenum target,
3714 GLenum attachment, GLuint texture,
3715 GLint level, GLint layer, const char *func,
3716 bool dsa, bool no_error, bool check_layered)
3717 {
3718 GET_CURRENT_CONTEXT(ctx);
3719 GLboolean layered = GL_FALSE;
3720
3721 if (!no_error && check_layered) {
3722 if (!_mesa_has_geometry_shaders(ctx)) {
3723 _mesa_error(ctx, GL_INVALID_OPERATION,
3724 "unsupported function (%s) called", func);
3725 return;
3726 }
3727 }
3728
3729 /* Get the framebuffer object */
3730 struct gl_framebuffer *fb;
3731 if (no_error) {
3732 if (dsa) {
3733 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
3734 } else {
3735 fb = get_framebuffer_target(ctx, target);
3736 }
3737 } else {
3738 if (dsa) {
3739 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
3740 if (!fb)
3741 return;
3742 } else {
3743 fb = get_framebuffer_target(ctx, target);
3744 if (!fb) {
3745 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
3746 func, _mesa_enum_to_string(target));
3747 return;
3748 }
3749 }
3750 }
3751
3752 /* Get the texture object and framebuffer attachment*/
3753 struct gl_renderbuffer_attachment *att;
3754 struct gl_texture_object *texObj;
3755 if (no_error) {
3756 texObj = get_texture_for_framebuffer(ctx, texture);
3757 att = get_attachment(ctx, fb, attachment, NULL);
3758 } else {
3759 if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
3760 &texObj))
3761 return;
3762
3763 att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
3764 if (!att)
3765 return;
3766 }
3767
3768 GLenum textarget = 0;
3769 if (texObj) {
3770 if (check_layered) {
3771 /* We do this regardless of no_error because this sets layered */
3772 if (!check_layered_texture_target(ctx, texObj->Target, func,
3773 &layered))
3774 return;
3775 }
3776
3777 if (!no_error) {
3778 if (!check_layered) {
3779 if (!check_texture_target(ctx, texObj->Target, func))
3780 return;
3781
3782 if (!check_layer(ctx, texObj->Target, layer, func))
3783 return;
3784 }
3785
3786 if (!check_level(ctx, texObj, texObj->Target, level, func))
3787 return;
3788 }
3789
3790 if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
3791 assert(layer >= 0 && layer < 6);
3792 textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
3793 layer = 0;
3794 }
3795 }
3796
3797 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3798 level, 0, layer, layered);
3799 }
3800
3801 void GLAPIENTRY
3802 _mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
3803 GLuint texture, GLint level,
3804 GLint layer)
3805 {
3806 frame_buffer_texture(0, target, attachment, texture, level, layer,
3807 "glFramebufferTextureLayer", false, true, false);
3808 }
3809
3810
3811 void GLAPIENTRY
3812 _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
3813 GLuint texture, GLint level, GLint layer)
3814 {
3815 frame_buffer_texture(0, target, attachment, texture, level, layer,
3816 "glFramebufferTextureLayer", false, false, false);
3817 }
3818
3819
3820 void GLAPIENTRY
3821 _mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
3822 GLenum attachment,
3823 GLuint texture, GLint level,
3824 GLint layer)
3825 {
3826 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3827 "glNamedFramebufferTextureLayer", true, true, false);
3828 }
3829
3830
3831 void GLAPIENTRY
3832 _mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
3833 GLuint texture, GLint level, GLint layer)
3834 {
3835 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3836 "glNamedFramebufferTextureLayer", true, false, false);
3837 }
3838
3839
3840 void GLAPIENTRY
3841 _mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
3842 GLuint texture, GLint level)
3843 {
3844 frame_buffer_texture(0, target, attachment, texture, level, 0,
3845 "glFramebufferTexture", false, true, true);
3846 }
3847
3848
3849 void GLAPIENTRY
3850 _mesa_FramebufferTexture(GLenum target, GLenum attachment,
3851 GLuint texture, GLint level)
3852 {
3853 frame_buffer_texture(0, target, attachment, texture, level, 0,
3854 "glFramebufferTexture", false, false, true);
3855 }
3856
3857 void GLAPIENTRY
3858 _mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
3859 GLuint texture, GLint level)
3860 {
3861 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
3862 "glNamedFramebufferTexture", true, true, true);
3863 }
3864
3865
3866 void GLAPIENTRY
3867 _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
3868 GLuint texture, GLint level)
3869 {
3870 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
3871 "glNamedFramebufferTexture", true, false, true);
3872 }
3873
3874
3875 void
3876 _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
3877 struct gl_framebuffer *fb,
3878 GLenum attachment,
3879 struct gl_renderbuffer *rb)
3880 {
3881 assert(!_mesa_is_winsys_fbo(fb));
3882
3883 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3884
3885 assert(ctx->Driver.FramebufferRenderbuffer);
3886 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
3887
3888 /* Some subsequent GL commands may depend on the framebuffer's visual
3889 * after the binding is updated. Update visual info now.
3890 */
3891 _mesa_update_framebuffer_visual(ctx, fb);
3892 }
3893
3894 static ALWAYS_INLINE void
3895 framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
3896 GLenum attachment, GLenum renderbuffertarget,
3897 GLuint renderbuffer, const char *func, bool no_error)
3898 {
3899 struct gl_renderbuffer_attachment *att;
3900 struct gl_renderbuffer *rb;
3901 bool is_color_attachment;
3902
3903 if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
3904 _mesa_error(ctx, GL_INVALID_ENUM,
3905 "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
3906 return;
3907 }
3908
3909 if (renderbuffer) {
3910 if (!no_error) {
3911 rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
3912 if (!rb)
3913 return;
3914 } else {
3915 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
3916 }
3917 } else {
3918 /* remove renderbuffer attachment */
3919 rb = NULL;
3920 }
3921
3922 if (!no_error) {
3923 if (_mesa_is_winsys_fbo(fb)) {
3924 /* Can't attach new renderbuffers to a window system framebuffer */
3925 _mesa_error(ctx, GL_INVALID_OPERATION,
3926 "%s(window-system framebuffer)", func);
3927 return;
3928 }
3929
3930 att = get_attachment(ctx, fb, attachment, &is_color_attachment);
3931 if (att == NULL) {
3932 /*
3933 * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
3934 * to a Framebuffer":
3935 *
3936 * "An INVALID_OPERATION error is generated if attachment is
3937 * COLOR_- ATTACHMENTm where m is greater than or equal to the
3938 * value of MAX_COLOR_- ATTACHMENTS ."
3939 *
3940 * If we are at this point, is because the attachment is not valid, so
3941 * if is_color_attachment is true, is because of the previous reason.
3942 */
3943 if (is_color_attachment) {
3944 _mesa_error(ctx, GL_INVALID_OPERATION,
3945 "%s(invalid color attachment %s)", func,
3946 _mesa_enum_to_string(attachment));
3947 } else {
3948 _mesa_error(ctx, GL_INVALID_ENUM,
3949 "%s(invalid attachment %s)", func,
3950 _mesa_enum_to_string(attachment));
3951 }
3952
3953 return;
3954 }
3955
3956 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
3957 rb && rb->Format != MESA_FORMAT_NONE) {
3958 /* make sure the renderbuffer is a depth/stencil format */
3959 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
3960 if (baseFormat != GL_DEPTH_STENCIL) {
3961 _mesa_error(ctx, GL_INVALID_OPERATION,
3962 "%s(renderbuffer is not DEPTH_STENCIL format)", func);
3963 return;
3964 }
3965 }
3966 }
3967
3968 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
3969 }
3970
3971 static void
3972 framebuffer_renderbuffer_error(struct gl_context *ctx,
3973 struct gl_framebuffer *fb, GLenum attachment,
3974 GLenum renderbuffertarget,
3975 GLuint renderbuffer, const char *func)
3976 {
3977 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
3978 renderbuffer, func, false);
3979 }
3980
3981 static void
3982 framebuffer_renderbuffer_no_error(struct gl_context *ctx,
3983 struct gl_framebuffer *fb, GLenum attachment,
3984 GLenum renderbuffertarget,
3985 GLuint renderbuffer, const char *func)
3986 {
3987 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
3988 renderbuffer, func, true);
3989 }
3990
3991 void GLAPIENTRY
3992 _mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
3993 GLenum renderbuffertarget,
3994 GLuint renderbuffer)
3995 {
3996 GET_CURRENT_CONTEXT(ctx);
3997
3998 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3999 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4000 renderbuffer, "glFramebufferRenderbuffer");
4001 }
4002
4003 void GLAPIENTRY
4004 _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
4005 GLenum renderbuffertarget,
4006 GLuint renderbuffer)
4007 {
4008 struct gl_framebuffer *fb;
4009 GET_CURRENT_CONTEXT(ctx);
4010
4011 fb = get_framebuffer_target(ctx, target);
4012 if (!fb) {
4013 _mesa_error(ctx, GL_INVALID_ENUM,
4014 "glFramebufferRenderbuffer(invalid target %s)",
4015 _mesa_enum_to_string(target));
4016 return;
4017 }
4018
4019 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4020 renderbuffer, "glFramebufferRenderbuffer");
4021 }
4022
4023 void GLAPIENTRY
4024 _mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
4025 GLenum attachment,
4026 GLenum renderbuffertarget,
4027 GLuint renderbuffer)
4028 {
4029 GET_CURRENT_CONTEXT(ctx);
4030
4031 struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4032 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4033 renderbuffer,
4034 "glNamedFramebufferRenderbuffer");
4035 }
4036
4037 void GLAPIENTRY
4038 _mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
4039 GLenum renderbuffertarget,
4040 GLuint renderbuffer)
4041 {
4042 struct gl_framebuffer *fb;
4043 GET_CURRENT_CONTEXT(ctx);
4044
4045 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4046 "glNamedFramebufferRenderbuffer");
4047 if (!fb)
4048 return;
4049
4050 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4051 renderbuffer,
4052 "glNamedFramebufferRenderbuffer");
4053 }
4054
4055
4056 static void
4057 get_framebuffer_attachment_parameter(struct gl_context *ctx,
4058 struct gl_framebuffer *buffer,
4059 GLenum attachment, GLenum pname,
4060 GLint *params, const char *caller)
4061 {
4062 const struct gl_renderbuffer_attachment *att;
4063 bool is_color_attachment = false;
4064 GLenum err;
4065
4066 /* The error code for an attachment type of GL_NONE differs between APIs.
4067 *
4068 * From the ES 2.0.25 specification, page 127:
4069 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4070 * querying any other pname will generate INVALID_ENUM."
4071 *
4072 * From the OpenGL 3.0 specification, page 337, or identically,
4073 * the OpenGL ES 3.0.4 specification, page 240:
4074 *
4075 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no
4076 * framebuffer is bound to target. In this case querying pname
4077 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero, and all other
4078 * queries will generate an INVALID_OPERATION error."
4079 */
4080 err = ctx->API == API_OPENGLES2 && ctx->Version < 30 ?
4081 GL_INVALID_ENUM : GL_INVALID_OPERATION;
4082
4083 if (_mesa_is_winsys_fbo(buffer)) {
4084 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
4085 * says:
4086 *
4087 * "If the framebuffer currently bound to target is zero, then
4088 * INVALID_OPERATION is generated."
4089 *
4090 * The EXT_framebuffer_object spec has the same wording, and the
4091 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
4092 * spec.
4093 */
4094 if ((!_mesa_is_desktop_gl(ctx) ||
4095 !ctx->Extensions.ARB_framebuffer_object)
4096 && !_mesa_is_gles3(ctx)) {
4097 _mesa_error(ctx, GL_INVALID_OPERATION,
4098 "%s(window-system framebuffer)", caller);
4099 return;
4100 }
4101
4102 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
4103 attachment != GL_DEPTH && attachment != GL_STENCIL) {
4104 _mesa_error(ctx, GL_INVALID_ENUM,
4105 "%s(invalid attachment %s)", caller,
4106 _mesa_enum_to_string(attachment));
4107 return;
4108 }
4109
4110 /* The specs are not clear about how to handle
4111 * GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME with the default framebuffer,
4112 * but dEQP-GLES3 expects an INVALID_ENUM error. This has also been
4113 * discussed in:
4114 *
4115 * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=12928#c1
4116 * and https://bugs.freedesktop.org/show_bug.cgi?id=31947
4117 */
4118 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4119 _mesa_error(ctx, GL_INVALID_ENUM,
4120 "%s(requesting GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME "
4121 "when GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
4122 "GL_FRAMEBUFFER_DEFAULT is not allowed)", caller);
4123 return;
4124 }
4125
4126 /* the default / window-system FBO */
4127 att = get_fb0_attachment(ctx, buffer, attachment);
4128 }
4129 else {
4130 /* user-created framebuffer FBO */
4131 att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
4132 }
4133
4134 if (att == NULL) {
4135 /*
4136 * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
4137 *
4138 * "An INVALID_OPERATION error is generated if a framebuffer object
4139 * is bound to target and attachment is COLOR_ATTACHMENTm where m is
4140 * greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
4141 *
4142 * If we are at this point, is because the attachment is not valid, so
4143 * if is_color_attachment is true, is because of the previous reason.
4144 */
4145 if (is_color_attachment) {
4146 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
4147 caller, _mesa_enum_to_string(attachment));
4148 } else {
4149 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
4150 _mesa_enum_to_string(attachment));
4151 }
4152 return;
4153 }
4154
4155 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
4156 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
4157 if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
4158 /* This behavior is first specified in OpenGL 4.4 specification.
4159 *
4160 * From the OpenGL 4.4 spec page 275:
4161 * "This query cannot be performed for a combined depth+stencil
4162 * attachment, since it does not have a single format."
4163 */
4164 _mesa_error(ctx, GL_INVALID_OPERATION,
4165 "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
4166 " is invalid for depth+stencil attachment)", caller);
4167 return;
4168 }
4169 /* the depth and stencil attachments must point to the same buffer */
4170 depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
4171 stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
4172 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
4173 _mesa_error(ctx, GL_INVALID_OPERATION,
4174 "%s(DEPTH/STENCIL attachments differ)", caller);
4175 return;
4176 }
4177 }
4178
4179 /* No need to flush here */
4180
4181 switch (pname) {
4182 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
4183 /* From the OpenGL spec, 9.2. Binding and Managing Framebuffer Objects:
4184 *
4185 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4186 * either no framebuffer is bound to target; or the default framebuffer
4187 * is bound, attachment is DEPTH or STENCIL, and the number of depth or
4188 * stencil bits, respectively, is zero."
4189 *
4190 * Note that we don't need explicit checks on DEPTH and STENCIL, because
4191 * on the case the spec is pointing, att->Type is already NONE, so we
4192 * just need to check att->Type.
4193 */
4194 *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
4195 GL_FRAMEBUFFER_DEFAULT : att->Type;
4196 return;
4197 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
4198 if (att->Type == GL_RENDERBUFFER_EXT) {
4199 *params = att->Renderbuffer->Name;
4200 }
4201 else if (att->Type == GL_TEXTURE) {
4202 *params = att->Texture->Name;
4203 }
4204 else {
4205 assert(att->Type == GL_NONE);
4206 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
4207 *params = 0;
4208 } else {
4209 goto invalid_pname_enum;
4210 }
4211 }
4212 return;
4213 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
4214 if (att->Type == GL_TEXTURE) {
4215 *params = att->TextureLevel;
4216 }
4217 else if (att->Type == GL_NONE) {
4218 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4219 _mesa_enum_to_string(pname));
4220 }
4221 else {
4222 goto invalid_pname_enum;
4223 }
4224 return;
4225 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
4226 if (att->Type == GL_TEXTURE) {
4227 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
4228 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
4229 }
4230 else {
4231 *params = 0;
4232 }
4233 }
4234 else if (att->Type == GL_NONE) {
4235 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4236 _mesa_enum_to_string(pname));
4237 }
4238 else {
4239 goto invalid_pname_enum;
4240 }
4241 return;
4242 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
4243 if (ctx->API == API_OPENGLES) {
4244 goto invalid_pname_enum;
4245 } else if (att->Type == GL_NONE) {
4246 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4247 _mesa_enum_to_string(pname));
4248 } else if (att->Type == GL_TEXTURE) {
4249 if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
4250 att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
4251 *params = att->Zoffset;
4252 }
4253 else {
4254 *params = 0;
4255 }
4256 }
4257 else {
4258 goto invalid_pname_enum;
4259 }
4260 return;
4261 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4262 if ((!_mesa_is_desktop_gl(ctx) ||
4263 !ctx->Extensions.ARB_framebuffer_object)
4264 && !_mesa_is_gles3(ctx)) {
4265 goto invalid_pname_enum;
4266 }
4267 else if (att->Type == GL_NONE) {
4268 if (_mesa_is_winsys_fbo(buffer) &&
4269 (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
4270 *params = GL_LINEAR;
4271 } else {
4272 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4273 _mesa_enum_to_string(pname));
4274 }
4275 }
4276 else {
4277 if (ctx->Extensions.EXT_sRGB) {
4278 *params =
4279 _mesa_get_format_color_encoding(att->Renderbuffer->Format);
4280 }
4281 else {
4282 /* According to ARB_framebuffer_sRGB, we should return LINEAR
4283 * if the sRGB conversion is unsupported. */
4284 *params = GL_LINEAR;
4285 }
4286 }
4287 return;
4288 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4289 if ((ctx->API != API_OPENGL_COMPAT ||
4290 !ctx->Extensions.ARB_framebuffer_object)
4291 && ctx->API != API_OPENGL_CORE
4292 && !_mesa_is_gles3(ctx)) {
4293 goto invalid_pname_enum;
4294 }
4295 else if (att->Type == GL_NONE) {
4296 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4297 _mesa_enum_to_string(pname));
4298 }
4299 else {
4300 mesa_format format = att->Renderbuffer->Format;
4301
4302 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
4303 * 3.0.1 spec says:
4304 *
4305 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
4306 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
4307 * generate an INVALID_OPERATION error.
4308 */
4309 if (_mesa_is_gles3(ctx) &&
4310 attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
4311 _mesa_error(ctx, GL_INVALID_OPERATION,
4312 "%s(cannot query "
4313 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
4314 "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
4315 return;
4316 }
4317
4318 if (format == MESA_FORMAT_S_UINT8) {
4319 /* special cases */
4320 *params = GL_INDEX;
4321 }
4322 else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
4323 /* depends on the attachment parameter */
4324 if (attachment == GL_STENCIL_ATTACHMENT) {
4325 *params = GL_INDEX;
4326 }
4327 else {
4328 *params = GL_FLOAT;
4329 }
4330 }
4331 else {
4332 *params = _mesa_get_format_datatype(format);
4333 }
4334 }
4335 return;
4336 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4337 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4338 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4339 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4340 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4341 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4342 if ((!_mesa_is_desktop_gl(ctx) ||
4343 !ctx->Extensions.ARB_framebuffer_object)
4344 && !_mesa_is_gles3(ctx)) {
4345 goto invalid_pname_enum;
4346 }
4347 else if (att->Texture) {
4348 const struct gl_texture_image *texImage =
4349 _mesa_select_tex_image(att->Texture, att->Texture->Target,
4350 att->TextureLevel);
4351 if (texImage) {
4352 *params = get_component_bits(pname, texImage->_BaseFormat,
4353 texImage->TexFormat);
4354 }
4355 else {
4356 *params = 0;
4357 }
4358 }
4359 else if (att->Renderbuffer) {
4360 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
4361 att->Renderbuffer->Format);
4362 }
4363 else {
4364 assert(att->Type == GL_NONE);
4365 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4366 _mesa_enum_to_string(pname));
4367 }
4368 return;
4369 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
4370 if (!_mesa_has_geometry_shaders(ctx)) {
4371 goto invalid_pname_enum;
4372 } else if (att->Type == GL_TEXTURE) {
4373 *params = att->Layered;
4374 } else if (att->Type == GL_NONE) {
4375 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4376 _mesa_enum_to_string(pname));
4377 } else {
4378 goto invalid_pname_enum;
4379 }
4380 return;
4381 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4382 if (!ctx->Extensions.EXT_multisampled_render_to_texture) {
4383 goto invalid_pname_enum;
4384 } else if (att->Type == GL_TEXTURE) {
4385 *params = att->NumSamples;
4386 } else if (att->Type == GL_NONE) {
4387 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4388 _mesa_enum_to_string(pname));
4389 } else {
4390 goto invalid_pname_enum;
4391 }
4392 return;
4393 default:
4394 goto invalid_pname_enum;
4395 }
4396
4397 return;
4398
4399 invalid_pname_enum:
4400 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
4401 _mesa_enum_to_string(pname));
4402 return;
4403 }
4404
4405
4406 void GLAPIENTRY
4407 _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
4408 GLenum pname, GLint *params)
4409 {
4410 GET_CURRENT_CONTEXT(ctx);
4411 struct gl_framebuffer *buffer;
4412
4413 buffer = get_framebuffer_target(ctx, target);
4414 if (!buffer) {
4415 _mesa_error(ctx, GL_INVALID_ENUM,
4416 "glGetFramebufferAttachmentParameteriv(invalid target %s)",
4417 _mesa_enum_to_string(target));
4418 return;
4419 }
4420
4421 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4422 params,
4423 "glGetFramebufferAttachmentParameteriv");
4424 }
4425
4426
4427 void GLAPIENTRY
4428 _mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
4429 GLenum attachment,
4430 GLenum pname, GLint *params)
4431 {
4432 GET_CURRENT_CONTEXT(ctx);
4433 struct gl_framebuffer *buffer;
4434
4435 if (framebuffer) {
4436 buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4437 "glGetNamedFramebufferAttachmentParameteriv");
4438 if (!buffer)
4439 return;
4440 }
4441 else {
4442 /*
4443 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4444 * 4.5 core spec (30.10.2014, PDF page 314):
4445 * "If framebuffer is zero, then the default draw framebuffer is
4446 * queried."
4447 */
4448 buffer = ctx->WinSysDrawBuffer;
4449 }
4450
4451 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4452 params,
4453 "glGetNamedFramebufferAttachmentParameteriv");
4454 }
4455
4456
4457 void GLAPIENTRY
4458 _mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
4459 GLint param)
4460 {
4461 GET_CURRENT_CONTEXT(ctx);
4462 struct gl_framebuffer *fb = NULL;
4463
4464 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
4465 !ctx->Extensions.ARB_sample_locations) {
4466 _mesa_error(ctx, GL_INVALID_OPERATION,
4467 "glNamedFramebufferParameteri("
4468 "neither ARB_framebuffer_no_attachments nor "
4469 "ARB_sample_locations is available)");
4470 return;
4471 }
4472
4473 if (framebuffer) {
4474 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4475 "glNamedFramebufferParameteri");
4476 } else {
4477 fb = ctx->WinSysDrawBuffer;
4478 }
4479
4480 if (fb) {
4481 framebuffer_parameteri(ctx, fb, pname, param,
4482 "glNamedFramebufferParameteriv");
4483 }
4484 }
4485
4486
4487 void GLAPIENTRY
4488 _mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
4489 GLint *param)
4490 {
4491 GET_CURRENT_CONTEXT(ctx);
4492 struct gl_framebuffer *fb;
4493
4494 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4495 _mesa_error(ctx, GL_INVALID_OPERATION,
4496 "glNamedFramebufferParameteriv("
4497 "neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
4498 " is available)");
4499 return;
4500 }
4501
4502 if (framebuffer)
4503 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4504 "glGetNamedFramebufferParameteriv");
4505 else
4506 fb = ctx->WinSysDrawBuffer;
4507
4508 if (fb) {
4509 get_framebuffer_parameteriv(ctx, fb, pname, param,
4510 "glGetNamedFramebufferParameteriv");
4511 }
4512 }
4513
4514
4515 static void
4516 invalidate_framebuffer_storage(struct gl_context *ctx,
4517 struct gl_framebuffer *fb,
4518 GLsizei numAttachments,
4519 const GLenum *attachments, GLint x, GLint y,
4520 GLsizei width, GLsizei height, const char *name)
4521 {
4522 int i;
4523
4524 /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
4525 * Spec (2.2.2015, PDF page 522) says:
4526 * "An INVALID_VALUE error is generated if numAttachments, width, or
4527 * height is negative."
4528 */
4529 if (numAttachments < 0) {
4530 _mesa_error(ctx, GL_INVALID_VALUE,
4531 "%s(numAttachments < 0)", name);
4532 return;
4533 }
4534
4535 if (width < 0) {
4536 _mesa_error(ctx, GL_INVALID_VALUE,
4537 "%s(width < 0)", name);
4538 return;
4539 }
4540
4541 if (height < 0) {
4542 _mesa_error(ctx, GL_INVALID_VALUE,
4543 "%s(height < 0)", name);
4544 return;
4545 }
4546
4547 /* The GL_ARB_invalidate_subdata spec says:
4548 *
4549 * "If an attachment is specified that does not exist in the
4550 * framebuffer bound to <target>, it is ignored."
4551 *
4552 * It also says:
4553 *
4554 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
4555 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
4556 * INVALID_OPERATION is generated."
4557 *
4558 * No mention is made of GL_AUXi being out of range. Therefore, we allow
4559 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
4560 * set of retrictions).
4561 */
4562 for (i = 0; i < numAttachments; i++) {
4563 if (_mesa_is_winsys_fbo(fb)) {
4564 switch (attachments[i]) {
4565 case GL_ACCUM:
4566 case GL_AUX0:
4567 case GL_AUX1:
4568 case GL_AUX2:
4569 case GL_AUX3:
4570 /* Accumulation buffers and auxilary buffers were removed in
4571 * OpenGL 3.1, and they never existed in OpenGL ES.
4572 */
4573 if (ctx->API != API_OPENGL_COMPAT)
4574 goto invalid_enum;
4575 break;
4576 case GL_COLOR:
4577 case GL_DEPTH:
4578 case GL_STENCIL:
4579 break;
4580 case GL_BACK_LEFT:
4581 case GL_BACK_RIGHT:
4582 case GL_FRONT_LEFT:
4583 case GL_FRONT_RIGHT:
4584 if (!_mesa_is_desktop_gl(ctx))
4585 goto invalid_enum;
4586 break;
4587 default:
4588 goto invalid_enum;
4589 }
4590 } else {
4591 switch (attachments[i]) {
4592 case GL_DEPTH_ATTACHMENT:
4593 case GL_STENCIL_ATTACHMENT:
4594 break;
4595 case GL_DEPTH_STENCIL_ATTACHMENT:
4596 /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
4597 * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
4598 * extension does not make this attachment point valid on ES 2.0.
4599 */
4600 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
4601 break;
4602 /* fallthrough */
4603 case GL_COLOR_ATTACHMENT0:
4604 case GL_COLOR_ATTACHMENT1:
4605 case GL_COLOR_ATTACHMENT2:
4606 case GL_COLOR_ATTACHMENT3:
4607 case GL_COLOR_ATTACHMENT4:
4608 case GL_COLOR_ATTACHMENT5:
4609 case GL_COLOR_ATTACHMENT6:
4610 case GL_COLOR_ATTACHMENT7:
4611 case GL_COLOR_ATTACHMENT8:
4612 case GL_COLOR_ATTACHMENT9:
4613 case GL_COLOR_ATTACHMENT10:
4614 case GL_COLOR_ATTACHMENT11:
4615 case GL_COLOR_ATTACHMENT12:
4616 case GL_COLOR_ATTACHMENT13:
4617 case GL_COLOR_ATTACHMENT14:
4618 case GL_COLOR_ATTACHMENT15: {
4619 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
4620 if (k >= ctx->Const.MaxColorAttachments) {
4621 _mesa_error(ctx, GL_INVALID_OPERATION,
4622 "%s(attachment >= max. color attachments)", name);
4623 return;
4624 }
4625 break;
4626 }
4627 default:
4628 goto invalid_enum;
4629 }
4630 }
4631 }
4632
4633 /* We don't actually do anything for this yet. Just return after
4634 * validating the parameters and generating the required errors.
4635 */
4636 return;
4637
4638 invalid_enum:
4639 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
4640 _mesa_enum_to_string(attachments[i]));
4641 return;
4642 }
4643
4644 static struct gl_renderbuffer_attachment *
4645 get_fb_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
4646 const GLenum attachment)
4647 {
4648 switch (attachment) {
4649 case GL_COLOR:
4650 return &fb->Attachment[BUFFER_BACK_LEFT];
4651 case GL_COLOR_ATTACHMENT0:
4652 case GL_COLOR_ATTACHMENT1:
4653 case GL_COLOR_ATTACHMENT2:
4654 case GL_COLOR_ATTACHMENT3:
4655 case GL_COLOR_ATTACHMENT4:
4656 case GL_COLOR_ATTACHMENT5:
4657 case GL_COLOR_ATTACHMENT6:
4658 case GL_COLOR_ATTACHMENT7:
4659 case GL_COLOR_ATTACHMENT8:
4660 case GL_COLOR_ATTACHMENT9:
4661 case GL_COLOR_ATTACHMENT10:
4662 case GL_COLOR_ATTACHMENT11:
4663 case GL_COLOR_ATTACHMENT12:
4664 case GL_COLOR_ATTACHMENT13:
4665 case GL_COLOR_ATTACHMENT14:
4666 case GL_COLOR_ATTACHMENT15: {
4667 const unsigned i = attachment - GL_COLOR_ATTACHMENT0;
4668 if (i >= ctx->Const.MaxColorAttachments)
4669 return NULL;
4670 return &fb->Attachment[BUFFER_COLOR0 + i];
4671 }
4672 case GL_DEPTH:
4673 case GL_DEPTH_ATTACHMENT:
4674 case GL_DEPTH_STENCIL_ATTACHMENT:
4675 return &fb->Attachment[BUFFER_DEPTH];
4676 case GL_STENCIL:
4677 case GL_STENCIL_ATTACHMENT:
4678 return &fb->Attachment[BUFFER_STENCIL];
4679 default:
4680 return NULL;
4681 }
4682 }
4683
4684 static void
4685 discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
4686 GLsizei numAttachments, const GLenum *attachments)
4687 {
4688 if (!ctx->Driver.DiscardFramebuffer)
4689 return;
4690
4691 for (int i = 0; i < numAttachments; i++) {
4692 struct gl_renderbuffer_attachment *att =
4693 get_fb_attachment(ctx, fb, attachments[i]);
4694
4695 if (!att)
4696 continue;
4697
4698 /* If we're asked to invalidate just depth or just stencil, but the
4699 * attachment is packed depth/stencil, then we can only use
4700 * Driver.DiscardFramebuffer if the attachments list includes both depth
4701 * and stencil and they both point at the same renderbuffer.
4702 */
4703 if ((attachments[i] == GL_DEPTH_ATTACHMENT ||
4704 attachments[i] == GL_STENCIL_ATTACHMENT) &&
4705 (!att->Renderbuffer ||
4706 att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL)) {
4707 GLenum other_format = (attachments[i] == GL_DEPTH_ATTACHMENT ?
4708 GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
4709 bool has_both = false;
4710 for (int j = 0; j < numAttachments; j++) {
4711 if (attachments[j] == other_format)
4712 has_both = true;
4713 break;
4714 }
4715
4716 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer !=
4717 fb->Attachment[BUFFER_STENCIL].Renderbuffer || !has_both)
4718 continue;
4719 }
4720
4721 ctx->Driver.DiscardFramebuffer(ctx, fb, att);
4722 }
4723 }
4724
4725 void GLAPIENTRY
4726 _mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
4727 const GLenum *attachments, GLint x,
4728 GLint y, GLsizei width, GLsizei height)
4729 {
4730 /* no-op */
4731 }
4732
4733
4734 void GLAPIENTRY
4735 _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
4736 const GLenum *attachments, GLint x, GLint y,
4737 GLsizei width, GLsizei height)
4738 {
4739 struct gl_framebuffer *fb;
4740 GET_CURRENT_CONTEXT(ctx);
4741
4742 fb = get_framebuffer_target(ctx, target);
4743 if (!fb) {
4744 _mesa_error(ctx, GL_INVALID_ENUM,
4745 "glInvalidateSubFramebuffer(invalid target %s)",
4746 _mesa_enum_to_string(target));
4747 return;
4748 }
4749
4750 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4751 x, y, width, height,
4752 "glInvalidateSubFramebuffer");
4753 }
4754
4755
4756 void GLAPIENTRY
4757 _mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
4758 GLsizei numAttachments,
4759 const GLenum *attachments,
4760 GLint x, GLint y,
4761 GLsizei width, GLsizei height)
4762 {
4763 struct gl_framebuffer *fb;
4764 GET_CURRENT_CONTEXT(ctx);
4765
4766 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
4767 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
4768 * default draw framebuffer is affected."
4769 */
4770 if (framebuffer) {
4771 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4772 "glInvalidateNamedFramebufferSubData");
4773 if (!fb)
4774 return;
4775 }
4776 else
4777 fb = ctx->WinSysDrawBuffer;
4778
4779 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4780 x, y, width, height,
4781 "glInvalidateNamedFramebufferSubData");
4782 }
4783
4784 void GLAPIENTRY
4785 _mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
4786 const GLenum *attachments)
4787 {
4788 struct gl_framebuffer *fb;
4789 GET_CURRENT_CONTEXT(ctx);
4790
4791 fb = get_framebuffer_target(ctx, target);
4792 if (!fb)
4793 return;
4794
4795 discard_framebuffer(ctx, fb, numAttachments, attachments);
4796 }
4797
4798
4799 void GLAPIENTRY
4800 _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
4801 const GLenum *attachments)
4802 {
4803 struct gl_framebuffer *fb;
4804 GET_CURRENT_CONTEXT(ctx);
4805
4806 fb = get_framebuffer_target(ctx, target);
4807 if (!fb) {
4808 _mesa_error(ctx, GL_INVALID_ENUM,
4809 "glInvalidateFramebuffer(invalid target %s)",
4810 _mesa_enum_to_string(target));
4811 return;
4812 }
4813
4814 /* The GL_ARB_invalidate_subdata spec says:
4815 *
4816 * "The command
4817 *
4818 * void InvalidateFramebuffer(enum target,
4819 * sizei numAttachments,
4820 * const enum *attachments);
4821 *
4822 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
4823 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
4824 * <MAX_VIEWPORT_DIMS[1]> respectively."
4825 */
4826 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4827 0, 0,
4828 ctx->Const.MaxViewportWidth,
4829 ctx->Const.MaxViewportHeight,
4830 "glInvalidateFramebuffer");
4831
4832 discard_framebuffer(ctx, fb, numAttachments, attachments);
4833 }
4834
4835
4836 void GLAPIENTRY
4837 _mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
4838 GLsizei numAttachments,
4839 const GLenum *attachments)
4840 {
4841 struct gl_framebuffer *fb;
4842 GET_CURRENT_CONTEXT(ctx);
4843
4844 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
4845 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
4846 * default draw framebuffer is affected."
4847 */
4848 if (framebuffer) {
4849 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4850 "glInvalidateNamedFramebufferData");
4851 if (!fb)
4852 return;
4853 }
4854 else
4855 fb = ctx->WinSysDrawBuffer;
4856
4857 /* The GL_ARB_invalidate_subdata spec says:
4858 *
4859 * "The command
4860 *
4861 * void InvalidateFramebuffer(enum target,
4862 * sizei numAttachments,
4863 * const enum *attachments);
4864 *
4865 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
4866 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
4867 * <MAX_VIEWPORT_DIMS[1]> respectively."
4868 */
4869 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4870 0, 0,
4871 ctx->Const.MaxViewportWidth,
4872 ctx->Const.MaxViewportHeight,
4873 "glInvalidateNamedFramebufferData");
4874 }
4875
4876
4877 void GLAPIENTRY
4878 _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
4879 const GLenum *attachments)
4880 {
4881 struct gl_framebuffer *fb;
4882 GLint i;
4883
4884 GET_CURRENT_CONTEXT(ctx);
4885
4886 fb = get_framebuffer_target(ctx, target);
4887 if (!fb) {
4888 _mesa_error(ctx, GL_INVALID_ENUM,
4889 "glDiscardFramebufferEXT(target %s)",
4890 _mesa_enum_to_string(target));
4891 return;
4892 }
4893
4894 if (numAttachments < 0) {
4895 _mesa_error(ctx, GL_INVALID_VALUE,
4896 "glDiscardFramebufferEXT(numAttachments < 0)");
4897 return;
4898 }
4899
4900 for (i = 0; i < numAttachments; i++) {
4901 switch (attachments[i]) {
4902 case GL_COLOR:
4903 case GL_DEPTH:
4904 case GL_STENCIL:
4905 if (_mesa_is_user_fbo(fb))
4906 goto invalid_enum;
4907 break;
4908 case GL_COLOR_ATTACHMENT0:
4909 case GL_DEPTH_ATTACHMENT:
4910 case GL_STENCIL_ATTACHMENT:
4911 if (_mesa_is_winsys_fbo(fb))
4912 goto invalid_enum;
4913 break;
4914 default:
4915 goto invalid_enum;
4916 }
4917 }
4918
4919 discard_framebuffer(ctx, fb, numAttachments, attachments);
4920
4921 return;
4922
4923 invalid_enum:
4924 _mesa_error(ctx, GL_INVALID_ENUM,
4925 "glDiscardFramebufferEXT(attachment %s)",
4926 _mesa_enum_to_string(attachments[i]));
4927 }
4928
4929 static void
4930 sample_locations(struct gl_context *ctx, struct gl_framebuffer *fb,
4931 GLuint start, GLsizei count, const GLfloat *v, bool no_error,
4932 const char *name)
4933 {
4934 GLsizei i;
4935
4936 if (!no_error) {
4937 if (!ctx->Extensions.ARB_sample_locations) {
4938 _mesa_error(ctx, GL_INVALID_OPERATION,
4939 "%s not supported "
4940 "(ARB_sample_locations not available)", name);
4941 return;
4942 }
4943
4944 if (start + count > MAX_SAMPLE_LOCATION_TABLE_SIZE) {
4945 _mesa_error(ctx, GL_INVALID_VALUE,
4946 "%s(start+size > sample location table size)", name);
4947 return;
4948 }
4949 }
4950
4951 if (!fb->SampleLocationTable) {
4952 size_t size = MAX_SAMPLE_LOCATION_TABLE_SIZE * 2 * sizeof(GLfloat);
4953 fb->SampleLocationTable = malloc(size);
4954 if (!fb->SampleLocationTable) {
4955 _mesa_error(ctx, GL_OUT_OF_MEMORY,
4956 "Cannot allocate sample location table");
4957 return;
4958 }
4959 for (i = 0; i < MAX_SAMPLE_LOCATION_TABLE_SIZE * 2; i++)
4960 fb->SampleLocationTable[i] = 0.5f;
4961 }
4962
4963 for (i = 0; i < count * 2; i++) {
4964 /* The ARB_sample_locations spec says:
4965 *
4966 * Sample locations outside of [0,1] result in undefined
4967 * behavior.
4968 *
4969 * To simplify driver implementations, we choose to clamp to
4970 * [0,1] and change NaN into 0.5.
4971 */
4972 if (isnan(v[i]) || v[i] < 0.0f || v[i] > 1.0f) {
4973 static GLuint msg_id = 0;
4974 static const char* msg = "Invalid sample location specified";
4975 _mesa_debug_get_id(&msg_id);
4976
4977 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_UNDEFINED,
4978 msg_id, MESA_DEBUG_SEVERITY_HIGH, strlen(msg), msg);
4979 }
4980
4981 if (isnan(v[i]))
4982 fb->SampleLocationTable[start * 2 + i] = 0.5f;
4983 else
4984 fb->SampleLocationTable[start * 2 + i] = CLAMP(v[i], 0.0f, 1.0f);
4985 }
4986
4987 if (fb == ctx->DrawBuffer)
4988 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
4989 }
4990
4991 void GLAPIENTRY
4992 _mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
4993 GLsizei count, const GLfloat *v)
4994 {
4995 struct gl_framebuffer *fb;
4996
4997 GET_CURRENT_CONTEXT(ctx);
4998
4999 fb = get_framebuffer_target(ctx, target);
5000 if (!fb) {
5001 _mesa_error(ctx, GL_INVALID_ENUM,
5002 "glFramebufferSampleLocationsfvARB(target %s)",
5003 _mesa_enum_to_string(target));
5004 return;
5005 }
5006
5007 sample_locations(ctx, fb, start, count, v, false,
5008 "glFramebufferSampleLocationsfvARB");
5009 }
5010
5011 void GLAPIENTRY
5012 _mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
5013 GLsizei count, const GLfloat *v)
5014 {
5015 struct gl_framebuffer *fb;
5016
5017 GET_CURRENT_CONTEXT(ctx);
5018
5019 if (framebuffer) {
5020 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5021 "glNamedFramebufferSampleLocationsfvARB");
5022 if (!fb)
5023 return;
5024 }
5025 else
5026 fb = ctx->WinSysDrawBuffer;
5027
5028 sample_locations(ctx, fb, start, count, v, false,
5029 "glNamedFramebufferSampleLocationsfvARB");
5030 }
5031
5032 void GLAPIENTRY
5033 _mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
5034 GLsizei count, const GLfloat *v)
5035 {
5036 GET_CURRENT_CONTEXT(ctx);
5037 sample_locations(ctx, get_framebuffer_target(ctx, target), start,
5038 count, v, true, "glFramebufferSampleLocationsfvARB");
5039 }
5040
5041 void GLAPIENTRY
5042 _mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
5043 GLuint start, GLsizei count,
5044 const GLfloat *v)
5045 {
5046 GET_CURRENT_CONTEXT(ctx);
5047 sample_locations(ctx, _mesa_lookup_framebuffer(ctx, framebuffer), start,
5048 count, v, true, "glNamedFramebufferSampleLocationsfvARB");
5049 }
5050
5051 void GLAPIENTRY
5052 _mesa_EvaluateDepthValuesARB(void)
5053 {
5054 GET_CURRENT_CONTEXT(ctx);
5055
5056 if (!ctx->Extensions.ARB_sample_locations) {
5057 _mesa_error(ctx, GL_INVALID_OPERATION,
5058 "EvaluateDepthValuesARB not supported (neither "
5059 "ARB_sample_locations nor NV_sample_locations is available)");
5060 return;
5061 }
5062
5063 if (ctx->Driver.EvaluateDepthValues)
5064 ctx->Driver.EvaluateDepthValues(ctx);
5065 }