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