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