ea89565cfe2a4ee45f8ed5e8fafc9f0e90cfdba1
[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_NamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer, GLsizei samples,
2739 GLenum internalformat,
2740 GLsizei width, GLsizei height)
2741 {
2742 GET_CURRENT_CONTEXT(ctx);
2743 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2744 if (!rb || rb == &DummyRenderbuffer) {
2745 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2746 rb = allocate_renderbuffer_locked(ctx, renderbuffer,
2747 "glNamedRenderbufferStorageMultisampleEXT");
2748 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2749 }
2750 renderbuffer_storage(ctx, rb, internalformat, width, height,
2751 samples, samples,
2752 "glNamedRenderbufferStorageMultisample");
2753 }
2754
2755
2756 void GLAPIENTRY
2757 _mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
2758 GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
2759 GLenum internalformat, GLsizei width, GLsizei height)
2760 {
2761 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2762 samples, storageSamples,
2763 "glNamedRenderbufferStorageMultisampleAdvancedAMD");
2764 }
2765
2766
2767 static void
2768 get_render_buffer_parameteriv(struct gl_context *ctx,
2769 struct gl_renderbuffer *rb, GLenum pname,
2770 GLint *params, const char *func)
2771 {
2772 /* No need to flush here since we're just quering state which is
2773 * not effected by rendering.
2774 */
2775
2776 switch (pname) {
2777 case GL_RENDERBUFFER_WIDTH_EXT:
2778 *params = rb->Width;
2779 return;
2780 case GL_RENDERBUFFER_HEIGHT_EXT:
2781 *params = rb->Height;
2782 return;
2783 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
2784 *params = rb->InternalFormat;
2785 return;
2786 case GL_RENDERBUFFER_RED_SIZE_EXT:
2787 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
2788 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
2789 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
2790 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
2791 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
2792 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
2793 return;
2794 case GL_RENDERBUFFER_SAMPLES:
2795 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
2796 || _mesa_is_gles3(ctx)) {
2797 *params = rb->NumSamples;
2798 return;
2799 }
2800 break;
2801 case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
2802 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
2803 *params = rb->NumStorageSamples;
2804 return;
2805 }
2806 break;
2807 }
2808
2809 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
2810 _mesa_enum_to_string(pname));
2811 }
2812
2813
2814 void GLAPIENTRY
2815 _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
2816 {
2817 GET_CURRENT_CONTEXT(ctx);
2818
2819 if (target != GL_RENDERBUFFER_EXT) {
2820 _mesa_error(ctx, GL_INVALID_ENUM,
2821 "glGetRenderbufferParameterivEXT(target)");
2822 return;
2823 }
2824
2825 if (!ctx->CurrentRenderbuffer) {
2826 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
2827 "(no renderbuffer bound)");
2828 return;
2829 }
2830
2831 get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
2832 params, "glGetRenderbufferParameteriv");
2833 }
2834
2835
2836 void GLAPIENTRY
2837 _mesa_GetNamedRenderbufferParameteriv(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 /* ID was reserved, but no real renderbuffer object made yet */
2845 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
2846 "(invalid renderbuffer %i)", renderbuffer);
2847 return;
2848 }
2849
2850 get_render_buffer_parameteriv(ctx, rb, pname, params,
2851 "glGetNamedRenderbufferParameteriv");
2852 }
2853
2854
2855 void GLAPIENTRY
2856 _mesa_GetNamedRenderbufferParameterivEXT(GLuint renderbuffer, GLenum pname,
2857 GLint *params)
2858 {
2859 GET_CURRENT_CONTEXT(ctx);
2860
2861 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2862 if (!rb || rb == &DummyRenderbuffer) {
2863 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2864 rb = allocate_renderbuffer_locked(ctx, renderbuffer, "glGetNamedRenderbufferParameterivEXT");
2865 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2866 }
2867
2868 get_render_buffer_parameteriv(ctx, rb, pname, params,
2869 "glGetNamedRenderbufferParameterivEXT");
2870 }
2871
2872
2873 GLboolean GLAPIENTRY
2874 _mesa_IsFramebuffer(GLuint framebuffer)
2875 {
2876 GET_CURRENT_CONTEXT(ctx);
2877 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2878 if (framebuffer) {
2879 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
2880 if (rb != NULL && rb != &DummyFramebuffer)
2881 return GL_TRUE;
2882 }
2883 return GL_FALSE;
2884 }
2885
2886
2887 /**
2888 * Check if any of the attachments of the given framebuffer are textures
2889 * (render to texture). Call ctx->Driver.RenderTexture() for such
2890 * attachments.
2891 */
2892 static void
2893 check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
2894 {
2895 GLuint i;
2896 assert(ctx->Driver.RenderTexture);
2897
2898 if (_mesa_is_winsys_fbo(fb))
2899 return; /* can't render to texture with winsys framebuffers */
2900
2901 for (i = 0; i < BUFFER_COUNT; i++) {
2902 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2903 if (att->Texture && att->Renderbuffer->TexImage
2904 && driver_RenderTexture_is_safe(att)) {
2905 ctx->Driver.RenderTexture(ctx, fb, att);
2906 }
2907 }
2908 }
2909
2910
2911 /**
2912 * Examine all the framebuffer's attachments to see if any are textures.
2913 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
2914 * notify the device driver that the texture image may have changed.
2915 */
2916 static void
2917 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
2918 {
2919 /* Skip if we know NeedsFinishRenderTexture won't be set. */
2920 if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
2921 return;
2922
2923 if (ctx->Driver.FinishRenderTexture) {
2924 GLuint i;
2925 for (i = 0; i < BUFFER_COUNT; i++) {
2926 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2927 struct gl_renderbuffer *rb = att->Renderbuffer;
2928 if (rb && rb->NeedsFinishRenderTexture) {
2929 ctx->Driver.FinishRenderTexture(ctx, rb);
2930 }
2931 }
2932 }
2933 }
2934
2935
2936 static void
2937 bind_framebuffer(GLenum target, GLuint framebuffer)
2938 {
2939 struct gl_framebuffer *newDrawFb, *newReadFb;
2940 GLboolean bindReadBuf, bindDrawBuf;
2941 GET_CURRENT_CONTEXT(ctx);
2942
2943 switch (target) {
2944 case GL_DRAW_FRAMEBUFFER_EXT:
2945 bindDrawBuf = GL_TRUE;
2946 bindReadBuf = GL_FALSE;
2947 break;
2948 case GL_READ_FRAMEBUFFER_EXT:
2949 bindDrawBuf = GL_FALSE;
2950 bindReadBuf = GL_TRUE;
2951 break;
2952 case GL_FRAMEBUFFER_EXT:
2953 bindDrawBuf = GL_TRUE;
2954 bindReadBuf = GL_TRUE;
2955 break;
2956 default:
2957 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2958 return;
2959 }
2960
2961 if (framebuffer) {
2962 /* Binding a user-created framebuffer object */
2963 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
2964 if (newDrawFb == &DummyFramebuffer) {
2965 /* ID was reserved, but no real framebuffer object made yet */
2966 newDrawFb = NULL;
2967 }
2968 else if (!newDrawFb && ctx->API == API_OPENGL_CORE) {
2969 /* All FBO IDs must be Gen'd */
2970 _mesa_error(ctx, GL_INVALID_OPERATION,
2971 "glBindFramebuffer(non-gen name)");
2972 return;
2973 }
2974
2975 if (!newDrawFb) {
2976 /* create new framebuffer object */
2977 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
2978 if (!newDrawFb) {
2979 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
2980 return;
2981 }
2982 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
2983 }
2984 newReadFb = newDrawFb;
2985 }
2986 else {
2987 /* Binding the window system framebuffer (which was originally set
2988 * with MakeCurrent).
2989 */
2990 newDrawFb = ctx->WinSysDrawBuffer;
2991 newReadFb = ctx->WinSysReadBuffer;
2992 }
2993
2994 _mesa_bind_framebuffers(ctx,
2995 bindDrawBuf ? newDrawFb : ctx->DrawBuffer,
2996 bindReadBuf ? newReadFb : ctx->ReadBuffer);
2997 }
2998
2999 void
3000 _mesa_bind_framebuffers(struct gl_context *ctx,
3001 struct gl_framebuffer *newDrawFb,
3002 struct gl_framebuffer *newReadFb)
3003 {
3004 struct gl_framebuffer *const oldDrawFb = ctx->DrawBuffer;
3005 struct gl_framebuffer *const oldReadFb = ctx->ReadBuffer;
3006 const bool bindDrawBuf = oldDrawFb != newDrawFb;
3007 const bool bindReadBuf = oldReadFb != newReadFb;
3008
3009 assert(newDrawFb);
3010 assert(newDrawFb != &DummyFramebuffer);
3011
3012 /*
3013 * OK, now bind the new Draw/Read framebuffers, if they're changing.
3014 *
3015 * We also check if we're beginning and/or ending render-to-texture.
3016 * When a framebuffer with texture attachments is unbound, call
3017 * ctx->Driver.FinishRenderTexture().
3018 * When a framebuffer with texture attachments is bound, call
3019 * ctx->Driver.RenderTexture().
3020 *
3021 * Note that if the ReadBuffer has texture attachments we don't consider
3022 * that a render-to-texture case.
3023 */
3024 if (bindReadBuf) {
3025 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3026
3027 /* check if old readbuffer was render-to-texture */
3028 check_end_texture_render(ctx, oldReadFb);
3029
3030 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
3031 }
3032
3033 if (bindDrawBuf) {
3034 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3035 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
3036
3037 /* check if old framebuffer had any texture attachments */
3038 if (oldDrawFb)
3039 check_end_texture_render(ctx, oldDrawFb);
3040
3041 /* check if newly bound framebuffer has any texture attachments */
3042 check_begin_texture_render(ctx, newDrawFb);
3043
3044 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
3045 }
3046
3047 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
3048 /* The few classic drivers that actually hook this function really only
3049 * want to know if the draw framebuffer changed.
3050 */
3051 ctx->Driver.BindFramebuffer(ctx,
3052 bindDrawBuf ? GL_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
3053 newDrawFb, newReadFb);
3054 }
3055 }
3056
3057 void GLAPIENTRY
3058 _mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
3059 {
3060 /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
3061 * point, but they allow the use of user-generated names.
3062 */
3063 bind_framebuffer(target, framebuffer);
3064 }
3065
3066
3067 void GLAPIENTRY
3068 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
3069 {
3070 bind_framebuffer(target, framebuffer);
3071 }
3072
3073
3074 void GLAPIENTRY
3075 _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
3076 {
3077 GLint i;
3078 GET_CURRENT_CONTEXT(ctx);
3079
3080 if (n < 0) {
3081 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
3082 return;
3083 }
3084
3085 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3086
3087 for (i = 0; i < n; i++) {
3088 if (framebuffers[i] > 0) {
3089 struct gl_framebuffer *fb;
3090 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
3091 if (fb) {
3092 assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
3093
3094 /* check if deleting currently bound framebuffer object */
3095 if (fb == ctx->DrawBuffer) {
3096 /* bind default */
3097 assert(fb->RefCount >= 2);
3098 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3099 }
3100 if (fb == ctx->ReadBuffer) {
3101 /* bind default */
3102 assert(fb->RefCount >= 2);
3103 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
3104 }
3105
3106 /* remove from hash table immediately, to free the ID */
3107 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
3108
3109 if (fb != &DummyFramebuffer) {
3110 /* But the object will not be freed until it's no longer
3111 * bound in any context.
3112 */
3113 _mesa_reference_framebuffer(&fb, NULL);
3114 }
3115 }
3116 }
3117 }
3118 }
3119
3120
3121 /**
3122 * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
3123 * It is not exposed to the rest of Mesa to encourage the use of
3124 * nameless buffers in driver internals.
3125 */
3126 static void
3127 create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
3128 {
3129 GET_CURRENT_CONTEXT(ctx);
3130 GLuint first;
3131 GLint i;
3132 struct gl_framebuffer *fb;
3133
3134 const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
3135
3136 if (n < 0) {
3137 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
3138 return;
3139 }
3140
3141 if (!framebuffers)
3142 return;
3143
3144 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
3145
3146 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
3147
3148 for (i = 0; i < n; i++) {
3149 GLuint name = first + i;
3150 framebuffers[i] = name;
3151
3152 if (dsa) {
3153 fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
3154 if (!fb) {
3155 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
3156 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
3157 return;
3158 }
3159 }
3160 else
3161 fb = &DummyFramebuffer;
3162
3163 _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, name, fb);
3164 }
3165
3166 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
3167 }
3168
3169
3170 void GLAPIENTRY
3171 _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
3172 {
3173 create_framebuffers(n, framebuffers, false);
3174 }
3175
3176
3177 void GLAPIENTRY
3178 _mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
3179 {
3180 create_framebuffers(n, framebuffers, true);
3181 }
3182
3183
3184 GLenum
3185 _mesa_check_framebuffer_status(struct gl_context *ctx,
3186 struct gl_framebuffer *buffer)
3187 {
3188 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
3189
3190 if (_mesa_is_winsys_fbo(buffer)) {
3191 /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
3192 if (buffer != &IncompleteFramebuffer) {
3193 return GL_FRAMEBUFFER_COMPLETE_EXT;
3194 } else {
3195 return GL_FRAMEBUFFER_UNDEFINED;
3196 }
3197 }
3198
3199 /* No need to flush here */
3200
3201 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
3202 _mesa_test_framebuffer_completeness(ctx, buffer);
3203 }
3204
3205 return buffer->_Status;
3206 }
3207
3208
3209 GLenum GLAPIENTRY
3210 _mesa_CheckFramebufferStatus_no_error(GLenum target)
3211 {
3212 GET_CURRENT_CONTEXT(ctx);
3213
3214 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3215 return _mesa_check_framebuffer_status(ctx, fb);
3216 }
3217
3218
3219 GLenum GLAPIENTRY
3220 _mesa_CheckFramebufferStatus(GLenum target)
3221 {
3222 struct gl_framebuffer *fb;
3223 GET_CURRENT_CONTEXT(ctx);
3224
3225 if (MESA_VERBOSE & VERBOSE_API)
3226 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
3227 _mesa_enum_to_string(target));
3228
3229 fb = get_framebuffer_target(ctx, target);
3230 if (!fb) {
3231 _mesa_error(ctx, GL_INVALID_ENUM,
3232 "glCheckFramebufferStatus(invalid target %s)",
3233 _mesa_enum_to_string(target));
3234 return 0;
3235 }
3236
3237 return _mesa_check_framebuffer_status(ctx, fb);
3238 }
3239
3240
3241 GLenum GLAPIENTRY
3242 _mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
3243 {
3244 struct gl_framebuffer *fb;
3245 GET_CURRENT_CONTEXT(ctx);
3246
3247 /* Validate the target (for conformance's sake) and grab a reference to the
3248 * default framebuffer in case framebuffer = 0.
3249 * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
3250 * (30.10.2014, PDF page 336) says:
3251 * "If framebuffer is zero, then the status of the default read or
3252 * draw framebuffer (as determined by target) is returned."
3253 */
3254 switch (target) {
3255 case GL_DRAW_FRAMEBUFFER:
3256 case GL_FRAMEBUFFER:
3257 fb = ctx->WinSysDrawBuffer;
3258 break;
3259 case GL_READ_FRAMEBUFFER:
3260 fb = ctx->WinSysReadBuffer;
3261 break;
3262 default:
3263 _mesa_error(ctx, GL_INVALID_ENUM,
3264 "glCheckNamedFramebufferStatus(invalid target %s)",
3265 _mesa_enum_to_string(target));
3266 return 0;
3267 }
3268
3269 if (framebuffer) {
3270 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
3271 "glCheckNamedFramebufferStatus");
3272 if (!fb)
3273 return 0;
3274 }
3275
3276 return _mesa_check_framebuffer_status(ctx, fb);
3277 }
3278
3279
3280 GLenum GLAPIENTRY
3281 _mesa_CheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target)
3282 {
3283 struct gl_framebuffer *fb;
3284 GET_CURRENT_CONTEXT(ctx);
3285
3286 switch (target) {
3287 case GL_DRAW_FRAMEBUFFER:
3288 case GL_FRAMEBUFFER:
3289 case GL_READ_FRAMEBUFFER:
3290 break;
3291 default:
3292 _mesa_error(ctx, GL_INVALID_ENUM,
3293 "glCheckNamedFramebufferStatusEXT(invalid target %s)",
3294 _mesa_enum_to_string(target));
3295 return 0;
3296 }
3297
3298 if (framebuffer == 0) {
3299 return _mesa_CheckNamedFramebufferStatus(0, target);
3300 }
3301
3302 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
3303 "glCheckNamedFramebufferStatusEXT");
3304 if (!fb)
3305 return 0;
3306
3307 return _mesa_check_framebuffer_status(ctx, fb);
3308 }
3309
3310
3311 /**
3312 * Replicate the src attachment point. Used by framebuffer_texture() when
3313 * the same texture is attached at GL_DEPTH_ATTACHMENT and
3314 * GL_STENCIL_ATTACHMENT.
3315 */
3316 static void
3317 reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
3318 gl_buffer_index dst,
3319 gl_buffer_index src)
3320 {
3321 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
3322 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
3323
3324 assert(src_att->Texture != NULL);
3325 assert(src_att->Renderbuffer != NULL);
3326
3327 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
3328 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
3329 dst_att->Type = src_att->Type;
3330 dst_att->Complete = src_att->Complete;
3331 dst_att->TextureLevel = src_att->TextureLevel;
3332 dst_att->CubeMapFace = src_att->CubeMapFace;
3333 dst_att->Zoffset = src_att->Zoffset;
3334 dst_att->Layered = src_att->Layered;
3335 }
3336
3337
3338 static struct gl_texture_object *
3339 get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
3340 {
3341 if (!texture)
3342 return NULL;
3343
3344 return _mesa_lookup_texture(ctx, texture);
3345 }
3346
3347
3348 /**
3349 * Common code called by gl*FramebufferTexture*() to retrieve the correct
3350 * texture object pointer.
3351 *
3352 * \param texObj where the pointer to the texture object is returned. Note
3353 * that a successful call may return texObj = NULL.
3354 *
3355 * \return true if no errors, false if errors
3356 */
3357 static bool
3358 get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
3359 bool layered, const char *caller,
3360 struct gl_texture_object **texObj)
3361 {
3362 *texObj = NULL; /* This will get returned if texture = 0. */
3363
3364 if (!texture)
3365 return true;
3366
3367 *texObj = _mesa_lookup_texture(ctx, texture);
3368 if (*texObj == NULL || (*texObj)->Target == 0) {
3369 /* Can't render to a non-existent texture object.
3370 *
3371 * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
3372 * Managing Framebuffer Objects specifies a different error
3373 * depending upon the calling function (PDF pages 325-328).
3374 * *FramebufferTexture (where layered = GL_TRUE) throws invalid
3375 * value, while the other commands throw invalid operation (where
3376 * layered = GL_FALSE).
3377 */
3378 const GLenum error = layered ? GL_INVALID_VALUE :
3379 GL_INVALID_OPERATION;
3380 _mesa_error(ctx, error,
3381 "%s(non-existent texture %u)", caller, texture);
3382 return false;
3383 }
3384
3385 return true;
3386 }
3387
3388
3389 /**
3390 * Common code called by gl*FramebufferTexture() to verify the texture target
3391 * and decide whether or not the attachment should truly be considered
3392 * layered.
3393 *
3394 * \param layered true if attachment should be considered layered, false if
3395 * not
3396 *
3397 * \return true if no errors, false if errors
3398 */
3399 static bool
3400 check_layered_texture_target(struct gl_context *ctx, GLenum target,
3401 const char *caller, GLboolean *layered)
3402 {
3403 *layered = GL_TRUE;
3404
3405 switch (target) {
3406 case GL_TEXTURE_3D:
3407 case GL_TEXTURE_1D_ARRAY_EXT:
3408 case GL_TEXTURE_2D_ARRAY_EXT:
3409 case GL_TEXTURE_CUBE_MAP:
3410 case GL_TEXTURE_CUBE_MAP_ARRAY:
3411 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3412 return true;
3413 case GL_TEXTURE_1D:
3414 case GL_TEXTURE_2D:
3415 case GL_TEXTURE_RECTANGLE:
3416 case GL_TEXTURE_2D_MULTISAMPLE:
3417 /* These texture types are valid to pass to
3418 * glFramebufferTexture(), but since they aren't layered, it
3419 * is equivalent to calling glFramebufferTexture{1D,2D}().
3420 */
3421 *layered = GL_FALSE;
3422 return true;
3423 }
3424
3425 _mesa_error(ctx, GL_INVALID_OPERATION,
3426 "%s(invalid texture target %s)", caller,
3427 _mesa_enum_to_string(target));
3428 return false;
3429 }
3430
3431
3432 /**
3433 * Common code called by gl*FramebufferTextureLayer() to verify the texture
3434 * target.
3435 *
3436 * \return true if no errors, false if errors
3437 */
3438 static bool
3439 check_texture_target(struct gl_context *ctx, GLenum target,
3440 const char *caller)
3441 {
3442 /* We're being called by glFramebufferTextureLayer().
3443 * The only legal texture types for that function are 3D,
3444 * cube-map, and 1D/2D/cube-map array textures.
3445 *
3446 * We don't need to check for GL_ARB_texture_cube_map_array because the
3447 * application wouldn't have been able to create a texture with a
3448 * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
3449 */
3450 switch (target) {
3451 case GL_TEXTURE_3D:
3452 case GL_TEXTURE_1D_ARRAY:
3453 case GL_TEXTURE_2D_ARRAY:
3454 case GL_TEXTURE_CUBE_MAP_ARRAY:
3455 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3456 return true;
3457 case GL_TEXTURE_CUBE_MAP:
3458 /* GL_TEXTURE_CUBE_MAP is only allowed by OpenGL 4.5 here, which
3459 * includes the DSA API.
3460 *
3461 * Because DSA is only enabled for GL 3.1+ and this can be called
3462 * from _mesa_FramebufferTextureLayer in compatibility profile,
3463 * we need to check the version.
3464 */
3465 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
3466 }
3467
3468 _mesa_error(ctx, GL_INVALID_OPERATION,
3469 "%s(invalid texture target %s)", caller,
3470 _mesa_enum_to_string(target));
3471 return false;
3472 }
3473
3474
3475 /**
3476 * Common code called by glFramebufferTexture*D() to verify the texture
3477 * target.
3478 *
3479 * \return true if no errors, false if errors
3480 */
3481 static bool
3482 check_textarget(struct gl_context *ctx, int dims, GLenum target,
3483 GLenum textarget, const char *caller)
3484 {
3485 bool err = false;
3486
3487 switch (textarget) {
3488 case GL_TEXTURE_1D:
3489 err = dims != 1;
3490 break;
3491 case GL_TEXTURE_1D_ARRAY:
3492 err = dims != 1 || !ctx->Extensions.EXT_texture_array;
3493 break;
3494 case GL_TEXTURE_2D:
3495 err = dims != 2;
3496 break;
3497 case GL_TEXTURE_2D_ARRAY:
3498 err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
3499 (_mesa_is_gles(ctx) && ctx->Version < 30);
3500 break;
3501 case GL_TEXTURE_2D_MULTISAMPLE:
3502 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3503 err = dims != 2 ||
3504 !ctx->Extensions.ARB_texture_multisample ||
3505 (_mesa_is_gles(ctx) && ctx->Version < 31);
3506 break;
3507 case GL_TEXTURE_RECTANGLE:
3508 err = dims != 2 || _mesa_is_gles(ctx) ||
3509 !ctx->Extensions.NV_texture_rectangle;
3510 break;
3511 case GL_TEXTURE_CUBE_MAP:
3512 case GL_TEXTURE_CUBE_MAP_ARRAY:
3513 err = true;
3514 break;
3515 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3516 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3517 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3518 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3519 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3520 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3521 err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
3522 break;
3523 case GL_TEXTURE_3D:
3524 err = dims != 3;
3525 break;
3526 default:
3527 _mesa_error(ctx, GL_INVALID_ENUM,
3528 "%s(unknown textarget 0x%x)", caller, textarget);
3529 return false;
3530 }
3531
3532 if (err) {
3533 _mesa_error(ctx, GL_INVALID_OPERATION,
3534 "%s(invalid textarget %s)",
3535 caller, _mesa_enum_to_string(textarget));
3536 return false;
3537 }
3538
3539 /* Make sure textarget is consistent with the texture's type */
3540 err = (target == GL_TEXTURE_CUBE_MAP) ?
3541 !_mesa_is_cube_face(textarget): (target != textarget);
3542
3543 if (err) {
3544 _mesa_error(ctx, GL_INVALID_OPERATION,
3545 "%s(mismatched texture target)", caller);
3546 return false;
3547 }
3548
3549 return true;
3550 }
3551
3552
3553 /**
3554 * Common code called by gl*FramebufferTextureLayer() and
3555 * glFramebufferTexture3D() to validate the layer.
3556 *
3557 * \return true if no errors, false if errors
3558 */
3559 static bool
3560 check_layer(struct gl_context *ctx, GLenum target, GLint layer,
3561 const char *caller)
3562 {
3563 /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
3564 * spec says:
3565 *
3566 * "An INVALID_VALUE error is generated if texture is non-zero
3567 * and layer is negative."
3568 */
3569 if (layer < 0) {
3570 _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
3571 return false;
3572 }
3573
3574 if (target == GL_TEXTURE_3D) {
3575 const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
3576 if (layer >= maxSize) {
3577 _mesa_error(ctx, GL_INVALID_VALUE,
3578 "%s(invalid layer %u)", caller, layer);
3579 return false;
3580 }
3581 }
3582 else if ((target == GL_TEXTURE_1D_ARRAY) ||
3583 (target == GL_TEXTURE_2D_ARRAY) ||
3584 (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
3585 (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
3586 if (layer >= ctx->Const.MaxArrayTextureLayers) {
3587 _mesa_error(ctx, GL_INVALID_VALUE,
3588 "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
3589 caller, layer);
3590 return false;
3591 }
3592 }
3593 else if (target == GL_TEXTURE_CUBE_MAP) {
3594 if (layer >= 6) {
3595 _mesa_error(ctx, GL_INVALID_VALUE,
3596 "%s(layer %u >= 6)", caller, layer);
3597 return false;
3598 }
3599 }
3600
3601 return true;
3602 }
3603
3604
3605 /**
3606 * Common code called by all gl*FramebufferTexture*() entry points to verify
3607 * the level.
3608 *
3609 * \return true if no errors, false if errors
3610 */
3611 static bool
3612 check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
3613 GLenum target, GLint level, const char *caller)
3614 {
3615 /* Section 9.2.8 of the OpenGL 4.6 specification says:
3616 *
3617 * "If texture refers to an immutable-format texture, level must be
3618 * greater than or equal to zero and smaller than the value of
3619 * TEXTURE_VIEW_NUM_LEVELS for texture."
3620 */
3621 const int max_levels = texObj->Immutable ? texObj->ImmutableLevels :
3622 _mesa_max_texture_levels(ctx, target);
3623
3624 if (level < 0 || level >= max_levels) {
3625 _mesa_error(ctx, GL_INVALID_VALUE,
3626 "%s(invalid level %d)", caller, level);
3627 return false;
3628 }
3629
3630 return true;
3631 }
3632
3633
3634 struct gl_renderbuffer_attachment *
3635 _mesa_get_and_validate_attachment(struct gl_context *ctx,
3636 struct gl_framebuffer *fb,
3637 GLenum attachment, const char *caller)
3638 {
3639 /* The window-system framebuffer object is immutable */
3640 if (_mesa_is_winsys_fbo(fb)) {
3641 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
3642 caller);
3643 return NULL;
3644 }
3645
3646 /* Not a hash lookup, so we can afford to get the attachment here. */
3647 bool is_color_attachment;
3648 struct gl_renderbuffer_attachment *att =
3649 get_attachment(ctx, fb, attachment, &is_color_attachment);
3650 if (att == NULL) {
3651 if (is_color_attachment) {
3652 _mesa_error(ctx, GL_INVALID_OPERATION,
3653 "%s(invalid color attachment %s)", caller,
3654 _mesa_enum_to_string(attachment));
3655 } else {
3656 _mesa_error(ctx, GL_INVALID_ENUM,
3657 "%s(invalid attachment %s)", caller,
3658 _mesa_enum_to_string(attachment));
3659 }
3660 return NULL;
3661 }
3662
3663 return att;
3664 }
3665
3666
3667 void
3668 _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
3669 GLenum attachment,
3670 struct gl_renderbuffer_attachment *att,
3671 struct gl_texture_object *texObj, GLenum textarget,
3672 GLint level, GLsizei samples,
3673 GLuint layer, GLboolean layered)
3674 {
3675 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3676
3677 simple_mtx_lock(&fb->Mutex);
3678 if (texObj) {
3679 if (attachment == GL_DEPTH_ATTACHMENT &&
3680 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
3681 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
3682 _mesa_tex_target_to_face(textarget) ==
3683 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
3684 samples == fb->Attachment[BUFFER_STENCIL].NumSamples &&
3685 layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
3686 /* The texture object is already attached to the stencil attachment
3687 * point. Don't create a new renderbuffer; just reuse the stencil
3688 * attachment's. This is required to prevent a GL error in
3689 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
3690 */
3691 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
3692 BUFFER_STENCIL);
3693 } else if (attachment == GL_STENCIL_ATTACHMENT &&
3694 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
3695 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
3696 _mesa_tex_target_to_face(textarget) ==
3697 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
3698 samples == fb->Attachment[BUFFER_DEPTH].NumSamples &&
3699 layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
3700 /* As above, but with depth and stencil transposed. */
3701 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
3702 BUFFER_DEPTH);
3703 } else {
3704 set_texture_attachment(ctx, fb, att, texObj, textarget,
3705 level, samples, layer, layered);
3706
3707 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3708 /* Above we created a new renderbuffer and attached it to the
3709 * depth attachment point. Now attach it to the stencil attachment
3710 * point too.
3711 */
3712 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3713 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
3714 BUFFER_DEPTH);
3715 }
3716 }
3717
3718 /* Set the render-to-texture flag. We'll check this flag in
3719 * glTexImage() and friends to determine if we need to revalidate
3720 * any FBOs that might be rendering into this texture.
3721 * This flag never gets cleared since it's non-trivial to determine
3722 * when all FBOs might be done rendering to this texture. That's OK
3723 * though since it's uncommon to render to a texture then repeatedly
3724 * call glTexImage() to change images in the texture.
3725 */
3726 texObj->_RenderToTexture = GL_TRUE;
3727 }
3728 else {
3729 remove_attachment(ctx, att);
3730 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3731 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3732 remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
3733 }
3734 }
3735
3736 invalidate_framebuffer(fb);
3737
3738 simple_mtx_unlock(&fb->Mutex);
3739 }
3740
3741
3742 static void
3743 framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
3744 GLenum textarget, GLuint texture,
3745 GLint level, GLint layer)
3746 {
3747 GET_CURRENT_CONTEXT(ctx);
3748
3749 /* Get the framebuffer object */
3750 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3751
3752 /* Get the texture object */
3753 struct gl_texture_object *texObj =
3754 get_texture_for_framebuffer(ctx, texture);
3755
3756 struct gl_renderbuffer_attachment *att =
3757 get_attachment(ctx, fb, attachment, NULL);
3758
3759 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3760 level, 0, layer, GL_FALSE);
3761 }
3762
3763
3764 static void
3765 framebuffer_texture_with_dims(int dims, GLenum target, GLuint framebuffer,
3766 GLenum attachment, GLenum textarget,
3767 GLuint texture, GLint level, GLsizei samples,
3768 GLint layer, const char *caller, bool dsa)
3769 {
3770 GET_CURRENT_CONTEXT(ctx);
3771 struct gl_framebuffer *fb;
3772 struct gl_texture_object *texObj;
3773
3774 /* Get the framebuffer object */
3775 if (dsa) {
3776 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer, caller);
3777 } else {
3778 fb = get_framebuffer_target(ctx, target);
3779 }
3780 if (!fb) {
3781 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
3782 _mesa_enum_to_string(target));
3783 return;
3784 }
3785
3786 /* Get the texture object */
3787 if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
3788 return;
3789
3790 if (texObj) {
3791 if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
3792 return;
3793
3794 if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
3795 return;
3796
3797 if (!check_level(ctx, texObj, textarget, level, caller))
3798 return;
3799 }
3800
3801 struct gl_renderbuffer_attachment *att =
3802 _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
3803 if (!att)
3804 return;
3805
3806 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3807 level, samples, layer, GL_FALSE);
3808 }
3809
3810
3811 void GLAPIENTRY
3812 _mesa_FramebufferTexture1D_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_FramebufferTexture1D(GLenum target, GLenum attachment,
3823 GLenum textarget, GLuint texture, GLint level)
3824 {
3825 framebuffer_texture_with_dims(1, target, 0, attachment, textarget, texture,
3826 level, 0, 0, "glFramebufferTexture1D", false);
3827 }
3828
3829
3830 void GLAPIENTRY
3831 _mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
3832 GLenum textarget, GLuint texture,
3833 GLint level)
3834 {
3835 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3836 texture, level, 0);
3837 }
3838
3839
3840 void GLAPIENTRY
3841 _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
3842 GLenum textarget, GLuint texture, GLint level)
3843 {
3844 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3845 level, 0, 0, "glFramebufferTexture2D", false);
3846 }
3847
3848
3849 void GLAPIENTRY
3850 _mesa_FramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment,
3851 GLenum textarget, GLuint texture,
3852 GLint level, GLsizei samples)
3853 {
3854 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3855 level, samples, 0,
3856 "glFramebufferTexture2DMultisampleEXT",
3857 false);
3858 }
3859
3860
3861 void GLAPIENTRY
3862 _mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
3863 GLenum textarget, GLuint texture,
3864 GLint level, GLint layer)
3865 {
3866 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3867 texture, level, layer);
3868 }
3869
3870
3871 void GLAPIENTRY
3872 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
3873 GLenum textarget, GLuint texture,
3874 GLint level, GLint layer)
3875 {
3876 framebuffer_texture_with_dims(3, target, 0, attachment, textarget, texture,
3877 level, 0, layer, "glFramebufferTexture3D", false);
3878 }
3879
3880
3881 static ALWAYS_INLINE void
3882 frame_buffer_texture(GLuint framebuffer, GLenum target,
3883 GLenum attachment, GLuint texture,
3884 GLint level, GLint layer, const char *func,
3885 bool dsa, bool no_error, bool check_layered)
3886 {
3887 GET_CURRENT_CONTEXT(ctx);
3888 GLboolean layered = GL_FALSE;
3889
3890 if (!no_error && check_layered) {
3891 if (!_mesa_has_geometry_shaders(ctx)) {
3892 _mesa_error(ctx, GL_INVALID_OPERATION,
3893 "unsupported function (%s) called", func);
3894 return;
3895 }
3896 }
3897
3898 /* Get the framebuffer object */
3899 struct gl_framebuffer *fb;
3900 if (no_error) {
3901 if (dsa) {
3902 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
3903 } else {
3904 fb = get_framebuffer_target(ctx, target);
3905 }
3906 } else {
3907 if (dsa) {
3908 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
3909 if (!fb)
3910 return;
3911 } else {
3912 fb = get_framebuffer_target(ctx, target);
3913 if (!fb) {
3914 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
3915 func, _mesa_enum_to_string(target));
3916 return;
3917 }
3918 }
3919 }
3920
3921 /* Get the texture object and framebuffer attachment*/
3922 struct gl_renderbuffer_attachment *att;
3923 struct gl_texture_object *texObj;
3924 if (no_error) {
3925 texObj = get_texture_for_framebuffer(ctx, texture);
3926 att = get_attachment(ctx, fb, attachment, NULL);
3927 } else {
3928 if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
3929 &texObj))
3930 return;
3931
3932 att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
3933 if (!att)
3934 return;
3935 }
3936
3937 GLenum textarget = 0;
3938 if (texObj) {
3939 if (check_layered) {
3940 /* We do this regardless of no_error because this sets layered */
3941 if (!check_layered_texture_target(ctx, texObj->Target, func,
3942 &layered))
3943 return;
3944 }
3945
3946 if (!no_error) {
3947 if (!check_layered) {
3948 if (!check_texture_target(ctx, texObj->Target, func))
3949 return;
3950
3951 if (!check_layer(ctx, texObj->Target, layer, func))
3952 return;
3953 }
3954
3955 if (!check_level(ctx, texObj, texObj->Target, level, func))
3956 return;
3957 }
3958
3959 if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
3960 assert(layer >= 0 && layer < 6);
3961 textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
3962 layer = 0;
3963 }
3964 }
3965
3966 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3967 level, 0, layer, layered);
3968 }
3969
3970 void GLAPIENTRY
3971 _mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
3972 GLuint texture, GLint level,
3973 GLint layer)
3974 {
3975 frame_buffer_texture(0, target, attachment, texture, level, layer,
3976 "glFramebufferTextureLayer", false, true, false);
3977 }
3978
3979
3980 void GLAPIENTRY
3981 _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
3982 GLuint texture, GLint level, GLint layer)
3983 {
3984 frame_buffer_texture(0, target, attachment, texture, level, layer,
3985 "glFramebufferTextureLayer", false, false, false);
3986 }
3987
3988
3989 void GLAPIENTRY
3990 _mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
3991 GLenum attachment,
3992 GLuint texture, GLint level,
3993 GLint layer)
3994 {
3995 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3996 "glNamedFramebufferTextureLayer", true, true, false);
3997 }
3998
3999
4000 void GLAPIENTRY
4001 _mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
4002 GLuint texture, GLint level, GLint layer)
4003 {
4004 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
4005 "glNamedFramebufferTextureLayer", true, false, false);
4006 }
4007
4008
4009 void GLAPIENTRY
4010 _mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
4011 GLuint texture, GLint level)
4012 {
4013 frame_buffer_texture(0, target, attachment, texture, level, 0,
4014 "glFramebufferTexture", false, true, true);
4015 }
4016
4017
4018 void GLAPIENTRY
4019 _mesa_FramebufferTexture(GLenum target, GLenum attachment,
4020 GLuint texture, GLint level)
4021 {
4022 frame_buffer_texture(0, target, attachment, texture, level, 0,
4023 "glFramebufferTexture", false, false, true);
4024 }
4025
4026 void GLAPIENTRY
4027 _mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
4028 GLuint texture, GLint level)
4029 {
4030 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4031 "glNamedFramebufferTexture", true, true, true);
4032 }
4033
4034
4035 void GLAPIENTRY
4036 _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
4037 GLuint texture, GLint level)
4038 {
4039 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4040 "glNamedFramebufferTexture", true, false, true);
4041 }
4042
4043
4044 void GLAPIENTRY
4045 _mesa_NamedFramebufferTexture1DEXT(GLuint framebuffer, GLenum attachment,
4046 GLenum textarget, GLuint texture, GLint level)
4047 {
4048 framebuffer_texture_with_dims(1, GL_FRAMEBUFFER, framebuffer, attachment,
4049 textarget, texture, level, 0, 0,
4050 "glNamedFramebufferTexture1DEXT", true);
4051 }
4052
4053
4054 void GLAPIENTRY
4055 _mesa_NamedFramebufferTexture2DEXT(GLuint framebuffer, GLenum attachment,
4056 GLenum textarget, GLuint texture, GLint level)
4057 {
4058 framebuffer_texture_with_dims(2, GL_FRAMEBUFFER, framebuffer, attachment,
4059 textarget, texture, level, 0, 0,
4060 "glNamedFramebufferTexture2DEXT", true);
4061 }
4062
4063
4064 void GLAPIENTRY
4065 _mesa_NamedFramebufferTexture3DEXT(GLuint framebuffer, GLenum attachment,
4066 GLenum textarget, GLuint texture,
4067 GLint level, GLint zoffset)
4068 {
4069 framebuffer_texture_with_dims(3, GL_FRAMEBUFFER, framebuffer, attachment,
4070 textarget, texture, level, 0, zoffset,
4071 "glNamedFramebufferTexture3DEXT", true);
4072 }
4073
4074
4075 void
4076 _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
4077 struct gl_framebuffer *fb,
4078 GLenum attachment,
4079 struct gl_renderbuffer *rb)
4080 {
4081 assert(!_mesa_is_winsys_fbo(fb));
4082
4083 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
4084
4085 assert(ctx->Driver.FramebufferRenderbuffer);
4086 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
4087
4088 /* Some subsequent GL commands may depend on the framebuffer's visual
4089 * after the binding is updated. Update visual info now.
4090 */
4091 _mesa_update_framebuffer_visual(ctx, fb);
4092 }
4093
4094 static ALWAYS_INLINE void
4095 framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
4096 GLenum attachment, GLenum renderbuffertarget,
4097 GLuint renderbuffer, const char *func, bool no_error)
4098 {
4099 struct gl_renderbuffer_attachment *att;
4100 struct gl_renderbuffer *rb;
4101 bool is_color_attachment;
4102
4103 if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
4104 _mesa_error(ctx, GL_INVALID_ENUM,
4105 "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
4106 return;
4107 }
4108
4109 if (renderbuffer) {
4110 if (!no_error) {
4111 rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
4112 if (!rb)
4113 return;
4114 } else {
4115 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
4116 }
4117 } else {
4118 /* remove renderbuffer attachment */
4119 rb = NULL;
4120 }
4121
4122 if (!no_error) {
4123 if (_mesa_is_winsys_fbo(fb)) {
4124 /* Can't attach new renderbuffers to a window system framebuffer */
4125 _mesa_error(ctx, GL_INVALID_OPERATION,
4126 "%s(window-system framebuffer)", func);
4127 return;
4128 }
4129
4130 att = get_attachment(ctx, fb, attachment, &is_color_attachment);
4131 if (att == NULL) {
4132 /*
4133 * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
4134 * to a Framebuffer":
4135 *
4136 * "An INVALID_OPERATION error is generated if attachment is
4137 * COLOR_- ATTACHMENTm where m is greater than or equal to the
4138 * value of MAX_COLOR_- ATTACHMENTS ."
4139 *
4140 * If we are at this point, is because the attachment is not valid, so
4141 * if is_color_attachment is true, is because of the previous reason.
4142 */
4143 if (is_color_attachment) {
4144 _mesa_error(ctx, GL_INVALID_OPERATION,
4145 "%s(invalid color attachment %s)", func,
4146 _mesa_enum_to_string(attachment));
4147 } else {
4148 _mesa_error(ctx, GL_INVALID_ENUM,
4149 "%s(invalid attachment %s)", func,
4150 _mesa_enum_to_string(attachment));
4151 }
4152
4153 return;
4154 }
4155
4156 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
4157 rb && rb->Format != MESA_FORMAT_NONE) {
4158 /* make sure the renderbuffer is a depth/stencil format */
4159 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
4160 if (baseFormat != GL_DEPTH_STENCIL) {
4161 _mesa_error(ctx, GL_INVALID_OPERATION,
4162 "%s(renderbuffer is not DEPTH_STENCIL format)", func);
4163 return;
4164 }
4165 }
4166 }
4167
4168 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
4169 }
4170
4171 static void
4172 framebuffer_renderbuffer_error(struct gl_context *ctx,
4173 struct gl_framebuffer *fb, GLenum attachment,
4174 GLenum renderbuffertarget,
4175 GLuint renderbuffer, const char *func)
4176 {
4177 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4178 renderbuffer, func, false);
4179 }
4180
4181 static void
4182 framebuffer_renderbuffer_no_error(struct gl_context *ctx,
4183 struct gl_framebuffer *fb, GLenum attachment,
4184 GLenum renderbuffertarget,
4185 GLuint renderbuffer, const char *func)
4186 {
4187 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4188 renderbuffer, func, true);
4189 }
4190
4191 void GLAPIENTRY
4192 _mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
4193 GLenum renderbuffertarget,
4194 GLuint renderbuffer)
4195 {
4196 GET_CURRENT_CONTEXT(ctx);
4197
4198 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
4199 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4200 renderbuffer, "glFramebufferRenderbuffer");
4201 }
4202
4203 void GLAPIENTRY
4204 _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
4205 GLenum renderbuffertarget,
4206 GLuint renderbuffer)
4207 {
4208 struct gl_framebuffer *fb;
4209 GET_CURRENT_CONTEXT(ctx);
4210
4211 fb = get_framebuffer_target(ctx, target);
4212 if (!fb) {
4213 _mesa_error(ctx, GL_INVALID_ENUM,
4214 "glFramebufferRenderbuffer(invalid target %s)",
4215 _mesa_enum_to_string(target));
4216 return;
4217 }
4218
4219 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4220 renderbuffer, "glFramebufferRenderbuffer");
4221 }
4222
4223 void GLAPIENTRY
4224 _mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
4225 GLenum attachment,
4226 GLenum renderbuffertarget,
4227 GLuint renderbuffer)
4228 {
4229 GET_CURRENT_CONTEXT(ctx);
4230
4231 struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4232 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4233 renderbuffer,
4234 "glNamedFramebufferRenderbuffer");
4235 }
4236
4237 void GLAPIENTRY
4238 _mesa_NamedFramebufferRenderbuffer(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_err(ctx, framebuffer,
4246 "glNamedFramebufferRenderbuffer");
4247 if (!fb)
4248 return;
4249
4250 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4251 renderbuffer,
4252 "glNamedFramebufferRenderbuffer");
4253 }
4254
4255
4256 void GLAPIENTRY
4257 _mesa_NamedFramebufferRenderbufferEXT(GLuint framebuffer, GLenum attachment,
4258 GLenum renderbuffertarget,
4259 GLuint renderbuffer)
4260 {
4261 struct gl_framebuffer *fb;
4262 GET_CURRENT_CONTEXT(ctx);
4263
4264 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4265 "glNamedFramebufferRenderbufferEXT");
4266 if (!fb)
4267 return;
4268
4269 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4270 renderbuffer,
4271 "glNamedFramebufferRenderbuffer");
4272 }
4273
4274
4275 static void
4276 get_framebuffer_attachment_parameter(struct gl_context *ctx,
4277 struct gl_framebuffer *buffer,
4278 GLenum attachment, GLenum pname,
4279 GLint *params, const char *caller)
4280 {
4281 const struct gl_renderbuffer_attachment *att;
4282 bool is_color_attachment = false;
4283 GLenum err;
4284
4285 /* The error code for an attachment type of GL_NONE differs between APIs.
4286 *
4287 * From the ES 2.0.25 specification, page 127:
4288 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4289 * querying any other pname will generate INVALID_ENUM."
4290 *
4291 * From the OpenGL 3.0 specification, page 337, or identically,
4292 * the OpenGL ES 3.0.4 specification, page 240:
4293 *
4294 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no
4295 * framebuffer is bound to target. In this case querying pname
4296 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero, and all other
4297 * queries will generate an INVALID_OPERATION error."
4298 */
4299 err = ctx->API == API_OPENGLES2 && ctx->Version < 30 ?
4300 GL_INVALID_ENUM : GL_INVALID_OPERATION;
4301
4302 if (_mesa_is_winsys_fbo(buffer)) {
4303 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
4304 * says:
4305 *
4306 * "If the framebuffer currently bound to target is zero, then
4307 * INVALID_OPERATION is generated."
4308 *
4309 * The EXT_framebuffer_object spec has the same wording, and the
4310 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
4311 * spec.
4312 */
4313 if ((!_mesa_is_desktop_gl(ctx) ||
4314 !ctx->Extensions.ARB_framebuffer_object)
4315 && !_mesa_is_gles3(ctx)) {
4316 _mesa_error(ctx, GL_INVALID_OPERATION,
4317 "%s(window-system framebuffer)", caller);
4318 return;
4319 }
4320
4321 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
4322 attachment != GL_DEPTH && attachment != GL_STENCIL) {
4323 _mesa_error(ctx, GL_INVALID_ENUM,
4324 "%s(invalid attachment %s)", caller,
4325 _mesa_enum_to_string(attachment));
4326 return;
4327 }
4328
4329 /* The specs are not clear about how to handle
4330 * GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME with the default framebuffer,
4331 * but dEQP-GLES3 expects an INVALID_ENUM error. This has also been
4332 * discussed in:
4333 *
4334 * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=12928#c1
4335 * and https://bugs.freedesktop.org/show_bug.cgi?id=31947
4336 */
4337 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4338 _mesa_error(ctx, GL_INVALID_ENUM,
4339 "%s(requesting GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME "
4340 "when GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
4341 "GL_FRAMEBUFFER_DEFAULT is not allowed)", caller);
4342 return;
4343 }
4344
4345 /* the default / window-system FBO */
4346 att = get_fb0_attachment(ctx, buffer, attachment);
4347 }
4348 else {
4349 /* user-created framebuffer FBO */
4350 att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
4351 }
4352
4353 if (att == NULL) {
4354 /*
4355 * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
4356 *
4357 * "An INVALID_OPERATION error is generated if a framebuffer object
4358 * is bound to target and attachment is COLOR_ATTACHMENTm where m is
4359 * greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
4360 *
4361 * If we are at this point, is because the attachment is not valid, so
4362 * if is_color_attachment is true, is because of the previous reason.
4363 */
4364 if (is_color_attachment) {
4365 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
4366 caller, _mesa_enum_to_string(attachment));
4367 } else {
4368 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
4369 _mesa_enum_to_string(attachment));
4370 }
4371 return;
4372 }
4373
4374 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
4375 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
4376 if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
4377 /* This behavior is first specified in OpenGL 4.4 specification.
4378 *
4379 * From the OpenGL 4.4 spec page 275:
4380 * "This query cannot be performed for a combined depth+stencil
4381 * attachment, since it does not have a single format."
4382 */
4383 _mesa_error(ctx, GL_INVALID_OPERATION,
4384 "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
4385 " is invalid for depth+stencil attachment)", caller);
4386 return;
4387 }
4388 /* the depth and stencil attachments must point to the same buffer */
4389 depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
4390 stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
4391 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
4392 _mesa_error(ctx, GL_INVALID_OPERATION,
4393 "%s(DEPTH/STENCIL attachments differ)", caller);
4394 return;
4395 }
4396 }
4397
4398 /* No need to flush here */
4399
4400 switch (pname) {
4401 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
4402 /* From the OpenGL spec, 9.2. Binding and Managing Framebuffer Objects:
4403 *
4404 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4405 * either no framebuffer is bound to target; or the default framebuffer
4406 * is bound, attachment is DEPTH or STENCIL, and the number of depth or
4407 * stencil bits, respectively, is zero."
4408 *
4409 * Note that we don't need explicit checks on DEPTH and STENCIL, because
4410 * on the case the spec is pointing, att->Type is already NONE, so we
4411 * just need to check att->Type.
4412 */
4413 *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
4414 GL_FRAMEBUFFER_DEFAULT : att->Type;
4415 return;
4416 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
4417 if (att->Type == GL_RENDERBUFFER_EXT) {
4418 *params = att->Renderbuffer->Name;
4419 }
4420 else if (att->Type == GL_TEXTURE) {
4421 *params = att->Texture->Name;
4422 }
4423 else {
4424 assert(att->Type == GL_NONE);
4425 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
4426 *params = 0;
4427 } else {
4428 goto invalid_pname_enum;
4429 }
4430 }
4431 return;
4432 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
4433 if (att->Type == GL_TEXTURE) {
4434 *params = att->TextureLevel;
4435 }
4436 else if (att->Type == GL_NONE) {
4437 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4438 _mesa_enum_to_string(pname));
4439 }
4440 else {
4441 goto invalid_pname_enum;
4442 }
4443 return;
4444 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
4445 if (att->Type == GL_TEXTURE) {
4446 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
4447 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
4448 }
4449 else {
4450 *params = 0;
4451 }
4452 }
4453 else if (att->Type == GL_NONE) {
4454 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4455 _mesa_enum_to_string(pname));
4456 }
4457 else {
4458 goto invalid_pname_enum;
4459 }
4460 return;
4461 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
4462 if (ctx->API == API_OPENGLES) {
4463 goto invalid_pname_enum;
4464 } else if (att->Type == GL_NONE) {
4465 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4466 _mesa_enum_to_string(pname));
4467 } else if (att->Type == GL_TEXTURE) {
4468 if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
4469 att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
4470 *params = att->Zoffset;
4471 }
4472 else {
4473 *params = 0;
4474 }
4475 }
4476 else {
4477 goto invalid_pname_enum;
4478 }
4479 return;
4480 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4481 if ((!_mesa_is_desktop_gl(ctx) ||
4482 !ctx->Extensions.ARB_framebuffer_object)
4483 && !_mesa_is_gles3(ctx)) {
4484 goto invalid_pname_enum;
4485 }
4486 else if (att->Type == GL_NONE) {
4487 if (_mesa_is_winsys_fbo(buffer) &&
4488 (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
4489 *params = GL_LINEAR;
4490 } else {
4491 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4492 _mesa_enum_to_string(pname));
4493 }
4494 }
4495 else {
4496 if (ctx->Extensions.EXT_sRGB) {
4497 *params = (_mesa_is_format_srgb(att->Renderbuffer->Format) ?
4498 GL_SRGB : GL_LINEAR);
4499 }
4500 else {
4501 /* According to ARB_framebuffer_sRGB, we should return LINEAR
4502 * if the sRGB conversion is unsupported. */
4503 *params = GL_LINEAR;
4504 }
4505 }
4506 return;
4507 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4508 if ((ctx->API != API_OPENGL_COMPAT ||
4509 !ctx->Extensions.ARB_framebuffer_object)
4510 && ctx->API != API_OPENGL_CORE
4511 && !_mesa_is_gles3(ctx)) {
4512 goto invalid_pname_enum;
4513 }
4514 else if (att->Type == GL_NONE) {
4515 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4516 _mesa_enum_to_string(pname));
4517 }
4518 else {
4519 mesa_format format = att->Renderbuffer->Format;
4520
4521 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
4522 * 3.0.1 spec says:
4523 *
4524 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
4525 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
4526 * generate an INVALID_OPERATION error.
4527 */
4528 if (_mesa_is_gles3(ctx) &&
4529 attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
4530 _mesa_error(ctx, GL_INVALID_OPERATION,
4531 "%s(cannot query "
4532 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
4533 "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
4534 return;
4535 }
4536
4537 if (format == MESA_FORMAT_S_UINT8) {
4538 /* special cases */
4539 *params = GL_INDEX;
4540 }
4541 else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
4542 /* depends on the attachment parameter */
4543 if (attachment == GL_STENCIL_ATTACHMENT) {
4544 *params = GL_INDEX;
4545 }
4546 else {
4547 *params = GL_FLOAT;
4548 }
4549 }
4550 else {
4551 *params = _mesa_get_format_datatype(format);
4552 }
4553 }
4554 return;
4555 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4556 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4557 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4558 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4559 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4560 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4561 if ((!_mesa_is_desktop_gl(ctx) ||
4562 !ctx->Extensions.ARB_framebuffer_object)
4563 && !_mesa_is_gles3(ctx)) {
4564 goto invalid_pname_enum;
4565 }
4566 else if (att->Texture) {
4567 const struct gl_texture_image *texImage =
4568 _mesa_select_tex_image(att->Texture, att->Texture->Target,
4569 att->TextureLevel);
4570 if (texImage) {
4571 *params = get_component_bits(pname, texImage->_BaseFormat,
4572 texImage->TexFormat);
4573 }
4574 else {
4575 *params = 0;
4576 }
4577 }
4578 else if (att->Renderbuffer) {
4579 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
4580 att->Renderbuffer->Format);
4581 }
4582 else {
4583 assert(att->Type == GL_NONE);
4584 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4585 _mesa_enum_to_string(pname));
4586 }
4587 return;
4588 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
4589 if (!_mesa_has_geometry_shaders(ctx)) {
4590 goto invalid_pname_enum;
4591 } else if (att->Type == GL_TEXTURE) {
4592 *params = att->Layered;
4593 } else if (att->Type == GL_NONE) {
4594 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4595 _mesa_enum_to_string(pname));
4596 } else {
4597 goto invalid_pname_enum;
4598 }
4599 return;
4600 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4601 if (!ctx->Extensions.EXT_multisampled_render_to_texture) {
4602 goto invalid_pname_enum;
4603 } else if (att->Type == GL_TEXTURE) {
4604 *params = att->NumSamples;
4605 } else if (att->Type == GL_NONE) {
4606 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4607 _mesa_enum_to_string(pname));
4608 } else {
4609 goto invalid_pname_enum;
4610 }
4611 return;
4612 default:
4613 goto invalid_pname_enum;
4614 }
4615
4616 return;
4617
4618 invalid_pname_enum:
4619 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
4620 _mesa_enum_to_string(pname));
4621 return;
4622 }
4623
4624
4625 void GLAPIENTRY
4626 _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
4627 GLenum pname, GLint *params)
4628 {
4629 GET_CURRENT_CONTEXT(ctx);
4630 struct gl_framebuffer *buffer;
4631
4632 buffer = get_framebuffer_target(ctx, target);
4633 if (!buffer) {
4634 _mesa_error(ctx, GL_INVALID_ENUM,
4635 "glGetFramebufferAttachmentParameteriv(invalid target %s)",
4636 _mesa_enum_to_string(target));
4637 return;
4638 }
4639
4640 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4641 params,
4642 "glGetFramebufferAttachmentParameteriv");
4643 }
4644
4645
4646 void GLAPIENTRY
4647 _mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
4648 GLenum attachment,
4649 GLenum pname, GLint *params)
4650 {
4651 GET_CURRENT_CONTEXT(ctx);
4652 struct gl_framebuffer *buffer;
4653
4654 if (framebuffer) {
4655 buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4656 "glGetNamedFramebufferAttachmentParameteriv");
4657 if (!buffer)
4658 return;
4659 }
4660 else {
4661 /*
4662 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4663 * 4.5 core spec (30.10.2014, PDF page 314):
4664 * "If framebuffer is zero, then the default draw framebuffer is
4665 * queried."
4666 */
4667 buffer = ctx->WinSysDrawBuffer;
4668 }
4669
4670 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4671 params,
4672 "glGetNamedFramebufferAttachmentParameteriv");
4673 }
4674
4675
4676 void GLAPIENTRY
4677 _mesa_GetNamedFramebufferAttachmentParameterivEXT(GLuint framebuffer,
4678 GLenum attachment,
4679 GLenum pname, GLint *params)
4680 {
4681 GET_CURRENT_CONTEXT(ctx);
4682 struct gl_framebuffer *buffer;
4683
4684 if (framebuffer) {
4685 buffer = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4686 "glGetNamedFramebufferAttachmentParameterivEXT");
4687 if (!buffer)
4688 return;
4689 }
4690 else {
4691 /*
4692 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4693 * 4.5 core spec (30.10.2014, PDF page 314):
4694 * "If framebuffer is zero, then the default draw framebuffer is
4695 * queried."
4696 */
4697 buffer = ctx->WinSysDrawBuffer;
4698 }
4699
4700 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4701 params,
4702 "glGetNamedFramebufferAttachmentParameterivEXT");
4703 }
4704
4705
4706 void GLAPIENTRY
4707 _mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
4708 GLint param)
4709 {
4710 GET_CURRENT_CONTEXT(ctx);
4711 struct gl_framebuffer *fb = NULL;
4712
4713 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
4714 !ctx->Extensions.ARB_sample_locations) {
4715 _mesa_error(ctx, GL_INVALID_OPERATION,
4716 "glNamedFramebufferParameteri("
4717 "neither ARB_framebuffer_no_attachments nor "
4718 "ARB_sample_locations is available)");
4719 return;
4720 }
4721
4722 if (framebuffer) {
4723 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4724 "glNamedFramebufferParameteri");
4725 } else {
4726 fb = ctx->WinSysDrawBuffer;
4727 }
4728
4729 if (fb) {
4730 framebuffer_parameteri(ctx, fb, pname, param,
4731 "glNamedFramebufferParameteriv");
4732 }
4733 }
4734
4735
4736 /* Helper function for ARB_framebuffer_no_attachments functions interacting with EXT_direct_state_access */
4737 static struct gl_framebuffer *
4738 lookup_named_framebuffer_ext_dsa(struct gl_context *ctx, GLuint framebuffer, const char* caller)
4739 {
4740 struct gl_framebuffer *fb = NULL;
4741
4742 if (framebuffer) {
4743 /* The ARB_framebuffer_no_attachments spec says:
4744 *
4745 * "The error INVALID_VALUE is generated if <framebuffer> is not
4746 * a name returned by GenFramebuffers. If a framebuffer object
4747 * named <framebuffer> does not yet exist, it will be created."
4748 *
4749 * This is different from the EXT_direct_state_access spec which says:
4750 *
4751 * "If the framebuffer object named by the framebuffer parameter has not
4752 * been previously bound or has been deleted since the last binding,
4753 * the GL first creates a new state vector in the same manner as when
4754 * BindFramebuffer creates a new framebuffer object"
4755 *
4756 * So first we verify that the name exists.
4757 */
4758 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4759 if (!fb) {
4760 _mesa_error(ctx, GL_INVALID_VALUE, "%s(frameBuffer)", caller);
4761 return NULL;
4762 }
4763 /* Then, make sure it's initialized */
4764 if (fb == &DummyFramebuffer) {
4765 fb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
4766 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
4767 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, fb);
4768 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
4769 }
4770 }
4771 else
4772 fb = ctx->WinSysDrawBuffer;
4773
4774 return fb;
4775 }
4776
4777
4778 void GLAPIENTRY
4779 _mesa_NamedFramebufferParameteriEXT(GLuint framebuffer, GLenum pname,
4780 GLint param)
4781 {
4782 GET_CURRENT_CONTEXT(ctx);
4783 struct gl_framebuffer *fb =
4784 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
4785 "glNamedFramebufferParameteriEXT");
4786
4787 if (!fb)
4788 return;
4789
4790 framebuffer_parameteri(ctx, fb, pname, param,
4791 "glNamedFramebufferParameteriEXT");
4792 }
4793
4794
4795 void GLAPIENTRY
4796 _mesa_GetFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4797 GLint *param)
4798 {
4799 GET_CURRENT_CONTEXT(ctx);
4800 struct gl_framebuffer *fb;
4801
4802 if (framebuffer)
4803 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4804 "glGetFramebufferParameterivEXT");
4805 else
4806 fb = ctx->WinSysDrawBuffer;
4807
4808 if (fb) {
4809 /* The GL_EXT_direct_state_access says:
4810 *
4811 * The pname parameter must be one of framebuffer dependent values
4812 * listed in either table 4.nnn (namely DRAW_BUFFER, READ_BUFFER,
4813 * or DRAW_BUFFER0 through DRAW_BUFFER15).
4814 */
4815 if (pname == GL_DRAW_BUFFER) {
4816 *param = fb->ColorDrawBuffer[0];
4817
4818 }
4819 else if (pname == GL_READ_BUFFER) {
4820 *param = fb->ColorReadBuffer;
4821 }
4822 else if (GL_DRAW_BUFFER0 <= pname && pname <= GL_DRAW_BUFFER15) {
4823 *param = fb->ColorDrawBuffer[pname - GL_DRAW_BUFFER0];
4824 }
4825 else {
4826 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
4827 }
4828 }
4829 }
4830
4831
4832 void GLAPIENTRY
4833 _mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
4834 GLint *param)
4835 {
4836 GET_CURRENT_CONTEXT(ctx);
4837 struct gl_framebuffer *fb;
4838
4839 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4840 _mesa_error(ctx, GL_INVALID_OPERATION,
4841 "glNamedFramebufferParameteriv("
4842 "neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
4843 " is available)");
4844 return;
4845 }
4846
4847 if (framebuffer)
4848 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4849 "glGetNamedFramebufferParameteriv");
4850 else
4851 fb = ctx->WinSysDrawBuffer;
4852
4853 if (fb) {
4854 get_framebuffer_parameteriv(ctx, fb, pname, param,
4855 "glGetNamedFramebufferParameteriv");
4856 }
4857 }
4858
4859
4860 void GLAPIENTRY
4861 _mesa_GetNamedFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4862 GLint *param)
4863 {
4864 GET_CURRENT_CONTEXT(ctx);
4865 struct gl_framebuffer *fb =
4866 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
4867 "glGetNamedFramebufferParameterivEXT");
4868
4869 if (!fb)
4870 return;
4871
4872 get_framebuffer_parameteriv(ctx, fb, pname, param,
4873 "glGetNamedFramebufferParameterivEXT");
4874 }
4875
4876
4877 static void
4878 invalidate_framebuffer_storage(struct gl_context *ctx,
4879 struct gl_framebuffer *fb,
4880 GLsizei numAttachments,
4881 const GLenum *attachments, GLint x, GLint y,
4882 GLsizei width, GLsizei height, const char *name)
4883 {
4884 int i;
4885
4886 /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
4887 * Spec (2.2.2015, PDF page 522) says:
4888 * "An INVALID_VALUE error is generated if numAttachments, width, or
4889 * height is negative."
4890 */
4891 if (numAttachments < 0) {
4892 _mesa_error(ctx, GL_INVALID_VALUE,
4893 "%s(numAttachments < 0)", name);
4894 return;
4895 }
4896
4897 if (width < 0) {
4898 _mesa_error(ctx, GL_INVALID_VALUE,
4899 "%s(width < 0)", name);
4900 return;
4901 }
4902
4903 if (height < 0) {
4904 _mesa_error(ctx, GL_INVALID_VALUE,
4905 "%s(height < 0)", name);
4906 return;
4907 }
4908
4909 /* The GL_ARB_invalidate_subdata spec says:
4910 *
4911 * "If an attachment is specified that does not exist in the
4912 * framebuffer bound to <target>, it is ignored."
4913 *
4914 * It also says:
4915 *
4916 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
4917 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
4918 * INVALID_OPERATION is generated."
4919 *
4920 * No mention is made of GL_AUXi being out of range. Therefore, we allow
4921 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
4922 * set of retrictions).
4923 */
4924 for (i = 0; i < numAttachments; i++) {
4925 if (_mesa_is_winsys_fbo(fb)) {
4926 switch (attachments[i]) {
4927 case GL_ACCUM:
4928 case GL_AUX0:
4929 case GL_AUX1:
4930 case GL_AUX2:
4931 case GL_AUX3:
4932 /* Accumulation buffers and auxilary buffers were removed in
4933 * OpenGL 3.1, and they never existed in OpenGL ES.
4934 */
4935 if (ctx->API != API_OPENGL_COMPAT)
4936 goto invalid_enum;
4937 break;
4938 case GL_COLOR:
4939 case GL_DEPTH:
4940 case GL_STENCIL:
4941 break;
4942 case GL_BACK_LEFT:
4943 case GL_BACK_RIGHT:
4944 case GL_FRONT_LEFT:
4945 case GL_FRONT_RIGHT:
4946 if (!_mesa_is_desktop_gl(ctx))
4947 goto invalid_enum;
4948 break;
4949 default:
4950 goto invalid_enum;
4951 }
4952 } else {
4953 switch (attachments[i]) {
4954 case GL_DEPTH_ATTACHMENT:
4955 case GL_STENCIL_ATTACHMENT:
4956 break;
4957 case GL_DEPTH_STENCIL_ATTACHMENT:
4958 /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
4959 * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
4960 * extension does not make this attachment point valid on ES 2.0.
4961 */
4962 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
4963 break;
4964 /* fallthrough */
4965 case GL_COLOR_ATTACHMENT0:
4966 case GL_COLOR_ATTACHMENT1:
4967 case GL_COLOR_ATTACHMENT2:
4968 case GL_COLOR_ATTACHMENT3:
4969 case GL_COLOR_ATTACHMENT4:
4970 case GL_COLOR_ATTACHMENT5:
4971 case GL_COLOR_ATTACHMENT6:
4972 case GL_COLOR_ATTACHMENT7:
4973 case GL_COLOR_ATTACHMENT8:
4974 case GL_COLOR_ATTACHMENT9:
4975 case GL_COLOR_ATTACHMENT10:
4976 case GL_COLOR_ATTACHMENT11:
4977 case GL_COLOR_ATTACHMENT12:
4978 case GL_COLOR_ATTACHMENT13:
4979 case GL_COLOR_ATTACHMENT14:
4980 case GL_COLOR_ATTACHMENT15: {
4981 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
4982 if (k >= ctx->Const.MaxColorAttachments) {
4983 _mesa_error(ctx, GL_INVALID_OPERATION,
4984 "%s(attachment >= max. color attachments)", name);
4985 return;
4986 }
4987 break;
4988 }
4989 default:
4990 goto invalid_enum;
4991 }
4992 }
4993 }
4994
4995 /* We don't actually do anything for this yet. Just return after
4996 * validating the parameters and generating the required errors.
4997 */
4998 return;
4999
5000 invalid_enum:
5001 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
5002 _mesa_enum_to_string(attachments[i]));
5003 return;
5004 }
5005
5006 static struct gl_renderbuffer_attachment *
5007 get_fb_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
5008 const GLenum attachment)
5009 {
5010 switch (attachment) {
5011 case GL_COLOR:
5012 return &fb->Attachment[BUFFER_BACK_LEFT];
5013 case GL_COLOR_ATTACHMENT0:
5014 case GL_COLOR_ATTACHMENT1:
5015 case GL_COLOR_ATTACHMENT2:
5016 case GL_COLOR_ATTACHMENT3:
5017 case GL_COLOR_ATTACHMENT4:
5018 case GL_COLOR_ATTACHMENT5:
5019 case GL_COLOR_ATTACHMENT6:
5020 case GL_COLOR_ATTACHMENT7:
5021 case GL_COLOR_ATTACHMENT8:
5022 case GL_COLOR_ATTACHMENT9:
5023 case GL_COLOR_ATTACHMENT10:
5024 case GL_COLOR_ATTACHMENT11:
5025 case GL_COLOR_ATTACHMENT12:
5026 case GL_COLOR_ATTACHMENT13:
5027 case GL_COLOR_ATTACHMENT14:
5028 case GL_COLOR_ATTACHMENT15: {
5029 const unsigned i = attachment - GL_COLOR_ATTACHMENT0;
5030 if (i >= ctx->Const.MaxColorAttachments)
5031 return NULL;
5032 return &fb->Attachment[BUFFER_COLOR0 + i];
5033 }
5034 case GL_DEPTH:
5035 case GL_DEPTH_ATTACHMENT:
5036 case GL_DEPTH_STENCIL_ATTACHMENT:
5037 return &fb->Attachment[BUFFER_DEPTH];
5038 case GL_STENCIL:
5039 case GL_STENCIL_ATTACHMENT:
5040 return &fb->Attachment[BUFFER_STENCIL];
5041 default:
5042 return NULL;
5043 }
5044 }
5045
5046 static void
5047 discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
5048 GLsizei numAttachments, const GLenum *attachments)
5049 {
5050 if (!ctx->Driver.DiscardFramebuffer)
5051 return;
5052
5053 for (int i = 0; i < numAttachments; i++) {
5054 struct gl_renderbuffer_attachment *att =
5055 get_fb_attachment(ctx, fb, attachments[i]);
5056
5057 if (!att)
5058 continue;
5059
5060 /* If we're asked to invalidate just depth or just stencil, but the
5061 * attachment is packed depth/stencil, then we can only use
5062 * Driver.DiscardFramebuffer if the attachments list includes both depth
5063 * and stencil and they both point at the same renderbuffer.
5064 */
5065 if ((attachments[i] == GL_DEPTH_ATTACHMENT ||
5066 attachments[i] == GL_STENCIL_ATTACHMENT) &&
5067 (!att->Renderbuffer ||
5068 att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL)) {
5069 GLenum other_format = (attachments[i] == GL_DEPTH_ATTACHMENT ?
5070 GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
5071 bool has_both = false;
5072 for (int j = 0; j < numAttachments; j++) {
5073 if (attachments[j] == other_format)
5074 has_both = true;
5075 break;
5076 }
5077
5078 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer !=
5079 fb->Attachment[BUFFER_STENCIL].Renderbuffer || !has_both)
5080 continue;
5081 }
5082
5083 ctx->Driver.DiscardFramebuffer(ctx, fb, att);
5084 }
5085 }
5086
5087 void GLAPIENTRY
5088 _mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5089 const GLenum *attachments, GLint x,
5090 GLint y, GLsizei width, GLsizei height)
5091 {
5092 /* no-op */
5093 }
5094
5095
5096 void GLAPIENTRY
5097 _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
5098 const GLenum *attachments, GLint x, GLint y,
5099 GLsizei width, GLsizei height)
5100 {
5101 struct gl_framebuffer *fb;
5102 GET_CURRENT_CONTEXT(ctx);
5103
5104 fb = get_framebuffer_target(ctx, target);
5105 if (!fb) {
5106 _mesa_error(ctx, GL_INVALID_ENUM,
5107 "glInvalidateSubFramebuffer(invalid target %s)",
5108 _mesa_enum_to_string(target));
5109 return;
5110 }
5111
5112 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5113 x, y, width, height,
5114 "glInvalidateSubFramebuffer");
5115 }
5116
5117
5118 void GLAPIENTRY
5119 _mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
5120 GLsizei numAttachments,
5121 const GLenum *attachments,
5122 GLint x, GLint y,
5123 GLsizei width, GLsizei height)
5124 {
5125 struct gl_framebuffer *fb;
5126 GET_CURRENT_CONTEXT(ctx);
5127
5128 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5129 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5130 * default draw framebuffer is affected."
5131 */
5132 if (framebuffer) {
5133 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5134 "glInvalidateNamedFramebufferSubData");
5135 if (!fb)
5136 return;
5137 }
5138 else
5139 fb = ctx->WinSysDrawBuffer;
5140
5141 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5142 x, y, width, height,
5143 "glInvalidateNamedFramebufferSubData");
5144 }
5145
5146 void GLAPIENTRY
5147 _mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5148 const GLenum *attachments)
5149 {
5150 struct gl_framebuffer *fb;
5151 GET_CURRENT_CONTEXT(ctx);
5152
5153 fb = get_framebuffer_target(ctx, target);
5154 if (!fb)
5155 return;
5156
5157 discard_framebuffer(ctx, fb, numAttachments, attachments);
5158 }
5159
5160
5161 void GLAPIENTRY
5162 _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
5163 const GLenum *attachments)
5164 {
5165 struct gl_framebuffer *fb;
5166 GET_CURRENT_CONTEXT(ctx);
5167
5168 fb = get_framebuffer_target(ctx, target);
5169 if (!fb) {
5170 _mesa_error(ctx, GL_INVALID_ENUM,
5171 "glInvalidateFramebuffer(invalid target %s)",
5172 _mesa_enum_to_string(target));
5173 return;
5174 }
5175
5176 /* The GL_ARB_invalidate_subdata spec says:
5177 *
5178 * "The command
5179 *
5180 * void InvalidateFramebuffer(enum target,
5181 * sizei numAttachments,
5182 * const enum *attachments);
5183 *
5184 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5185 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5186 * <MAX_VIEWPORT_DIMS[1]> respectively."
5187 */
5188 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5189 0, 0,
5190 ctx->Const.MaxViewportWidth,
5191 ctx->Const.MaxViewportHeight,
5192 "glInvalidateFramebuffer");
5193
5194 discard_framebuffer(ctx, fb, numAttachments, attachments);
5195 }
5196
5197
5198 void GLAPIENTRY
5199 _mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
5200 GLsizei numAttachments,
5201 const GLenum *attachments)
5202 {
5203 struct gl_framebuffer *fb;
5204 GET_CURRENT_CONTEXT(ctx);
5205
5206 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5207 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5208 * default draw framebuffer is affected."
5209 */
5210 if (framebuffer) {
5211 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5212 "glInvalidateNamedFramebufferData");
5213 if (!fb)
5214 return;
5215 }
5216 else
5217 fb = ctx->WinSysDrawBuffer;
5218
5219 /* The GL_ARB_invalidate_subdata spec says:
5220 *
5221 * "The command
5222 *
5223 * void InvalidateFramebuffer(enum target,
5224 * sizei numAttachments,
5225 * const enum *attachments);
5226 *
5227 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5228 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5229 * <MAX_VIEWPORT_DIMS[1]> respectively."
5230 */
5231 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5232 0, 0,
5233 ctx->Const.MaxViewportWidth,
5234 ctx->Const.MaxViewportHeight,
5235 "glInvalidateNamedFramebufferData");
5236 }
5237
5238
5239 void GLAPIENTRY
5240 _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
5241 const GLenum *attachments)
5242 {
5243 struct gl_framebuffer *fb;
5244 GLint i;
5245
5246 GET_CURRENT_CONTEXT(ctx);
5247
5248 fb = get_framebuffer_target(ctx, target);
5249 if (!fb) {
5250 _mesa_error(ctx, GL_INVALID_ENUM,
5251 "glDiscardFramebufferEXT(target %s)",
5252 _mesa_enum_to_string(target));
5253 return;
5254 }
5255
5256 if (numAttachments < 0) {
5257 _mesa_error(ctx, GL_INVALID_VALUE,
5258 "glDiscardFramebufferEXT(numAttachments < 0)");
5259 return;
5260 }
5261
5262 for (i = 0; i < numAttachments; i++) {
5263 switch (attachments[i]) {
5264 case GL_COLOR:
5265 case GL_DEPTH:
5266 case GL_STENCIL:
5267 if (_mesa_is_user_fbo(fb))
5268 goto invalid_enum;
5269 break;
5270 case GL_COLOR_ATTACHMENT0:
5271 case GL_DEPTH_ATTACHMENT:
5272 case GL_STENCIL_ATTACHMENT:
5273 if (_mesa_is_winsys_fbo(fb))
5274 goto invalid_enum;
5275 break;
5276 default:
5277 goto invalid_enum;
5278 }
5279 }
5280
5281 discard_framebuffer(ctx, fb, numAttachments, attachments);
5282
5283 return;
5284
5285 invalid_enum:
5286 _mesa_error(ctx, GL_INVALID_ENUM,
5287 "glDiscardFramebufferEXT(attachment %s)",
5288 _mesa_enum_to_string(attachments[i]));
5289 }
5290
5291 static void
5292 sample_locations(struct gl_context *ctx, struct gl_framebuffer *fb,
5293 GLuint start, GLsizei count, const GLfloat *v, bool no_error,
5294 const char *name)
5295 {
5296 GLsizei i;
5297
5298 if (!no_error) {
5299 if (!ctx->Extensions.ARB_sample_locations) {
5300 _mesa_error(ctx, GL_INVALID_OPERATION,
5301 "%s not supported "
5302 "(ARB_sample_locations not available)", name);
5303 return;
5304 }
5305
5306 if (start + count > MAX_SAMPLE_LOCATION_TABLE_SIZE) {
5307 _mesa_error(ctx, GL_INVALID_VALUE,
5308 "%s(start+size > sample location table size)", name);
5309 return;
5310 }
5311 }
5312
5313 if (!fb->SampleLocationTable) {
5314 size_t size = MAX_SAMPLE_LOCATION_TABLE_SIZE * 2 * sizeof(GLfloat);
5315 fb->SampleLocationTable = malloc(size);
5316 if (!fb->SampleLocationTable) {
5317 _mesa_error(ctx, GL_OUT_OF_MEMORY,
5318 "Cannot allocate sample location table");
5319 return;
5320 }
5321 for (i = 0; i < MAX_SAMPLE_LOCATION_TABLE_SIZE * 2; i++)
5322 fb->SampleLocationTable[i] = 0.5f;
5323 }
5324
5325 for (i = 0; i < count * 2; i++) {
5326 /* The ARB_sample_locations spec says:
5327 *
5328 * Sample locations outside of [0,1] result in undefined
5329 * behavior.
5330 *
5331 * To simplify driver implementations, we choose to clamp to
5332 * [0,1] and change NaN into 0.5.
5333 */
5334 if (isnan(v[i]) || v[i] < 0.0f || v[i] > 1.0f) {
5335 static GLuint msg_id = 0;
5336 static const char* msg = "Invalid sample location specified";
5337 _mesa_debug_get_id(&msg_id);
5338
5339 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_UNDEFINED,
5340 msg_id, MESA_DEBUG_SEVERITY_HIGH, strlen(msg), msg);
5341 }
5342
5343 if (isnan(v[i]))
5344 fb->SampleLocationTable[start * 2 + i] = 0.5f;
5345 else
5346 fb->SampleLocationTable[start * 2 + i] = CLAMP(v[i], 0.0f, 1.0f);
5347 }
5348
5349 if (fb == ctx->DrawBuffer)
5350 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
5351 }
5352
5353 void GLAPIENTRY
5354 _mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
5355 GLsizei count, const GLfloat *v)
5356 {
5357 struct gl_framebuffer *fb;
5358
5359 GET_CURRENT_CONTEXT(ctx);
5360
5361 fb = get_framebuffer_target(ctx, target);
5362 if (!fb) {
5363 _mesa_error(ctx, GL_INVALID_ENUM,
5364 "glFramebufferSampleLocationsfvARB(target %s)",
5365 _mesa_enum_to_string(target));
5366 return;
5367 }
5368
5369 sample_locations(ctx, fb, start, count, v, false,
5370 "glFramebufferSampleLocationsfvARB");
5371 }
5372
5373 void GLAPIENTRY
5374 _mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
5375 GLsizei count, const GLfloat *v)
5376 {
5377 struct gl_framebuffer *fb;
5378
5379 GET_CURRENT_CONTEXT(ctx);
5380
5381 if (framebuffer) {
5382 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5383 "glNamedFramebufferSampleLocationsfvARB");
5384 if (!fb)
5385 return;
5386 }
5387 else
5388 fb = ctx->WinSysDrawBuffer;
5389
5390 sample_locations(ctx, fb, start, count, v, false,
5391 "glNamedFramebufferSampleLocationsfvARB");
5392 }
5393
5394 void GLAPIENTRY
5395 _mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
5396 GLsizei count, const GLfloat *v)
5397 {
5398 GET_CURRENT_CONTEXT(ctx);
5399 sample_locations(ctx, get_framebuffer_target(ctx, target), start,
5400 count, v, true, "glFramebufferSampleLocationsfvARB");
5401 }
5402
5403 void GLAPIENTRY
5404 _mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
5405 GLuint start, GLsizei count,
5406 const GLfloat *v)
5407 {
5408 GET_CURRENT_CONTEXT(ctx);
5409 sample_locations(ctx, _mesa_lookup_framebuffer(ctx, framebuffer), start,
5410 count, v, true, "glNamedFramebufferSampleLocationsfvARB");
5411 }
5412
5413 void GLAPIENTRY
5414 _mesa_EvaluateDepthValuesARB(void)
5415 {
5416 GET_CURRENT_CONTEXT(ctx);
5417
5418 if (!ctx->Extensions.ARB_sample_locations) {
5419 _mesa_error(ctx, GL_INVALID_OPERATION,
5420 "EvaluateDepthValuesARB not supported (neither "
5421 "ARB_sample_locations nor NV_sample_locations is available)");
5422 return;
5423 }
5424
5425 if (ctx->Driver.EvaluateDepthValues)
5426 ctx->Driver.EvaluateDepthValues(ctx);
5427 }