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