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