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