mesa: Set query->EverBound in glQueryCounter().
[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 "enums.h"
39 #include "fbobject.h"
40 #include "formats.h"
41 #include "framebuffer.h"
42 #include "glformats.h"
43 #include "hash.h"
44 #include "macros.h"
45 #include "multisample.h"
46 #include "mtypes.h"
47 #include "renderbuffer.h"
48 #include "state.h"
49 #include "teximage.h"
50 #include "texobj.h"
51
52
53 /** Set this to 1 to debug/log glBlitFramebuffer() calls */
54 #define DEBUG_BLIT 0
55
56
57 /**
58 * Notes:
59 *
60 * None of the GL_EXT_framebuffer_object functions are compiled into
61 * display lists.
62 */
63
64
65
66 /*
67 * When glGenRender/FramebuffersEXT() is called we insert pointers to
68 * these placeholder objects into the hash table.
69 * Later, when the object ID is first bound, we replace the placeholder
70 * with the real frame/renderbuffer.
71 */
72 static struct gl_framebuffer DummyFramebuffer;
73 static struct gl_renderbuffer DummyRenderbuffer;
74
75 /* We bind this framebuffer when applications pass a NULL
76 * drawable/surface in make current. */
77 static struct gl_framebuffer IncompleteFramebuffer;
78
79
80 static void
81 delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
82 {
83 /* no op */
84 }
85
86 static void
87 delete_dummy_framebuffer(struct gl_framebuffer *fb)
88 {
89 /* no op */
90 }
91
92
93 void
94 _mesa_init_fbobjects(struct gl_context *ctx)
95 {
96 _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
97 _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
98 _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex);
99 DummyFramebuffer.Delete = delete_dummy_framebuffer;
100 DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
101 IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
102 }
103
104 struct gl_framebuffer *
105 _mesa_get_incomplete_framebuffer(void)
106 {
107 return &IncompleteFramebuffer;
108 }
109
110 /**
111 * Helper routine for getting a gl_renderbuffer.
112 */
113 struct gl_renderbuffer *
114 _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
115 {
116 struct gl_renderbuffer *rb;
117
118 if (id == 0)
119 return NULL;
120
121 rb = (struct gl_renderbuffer *)
122 _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
123 return rb;
124 }
125
126
127 /**
128 * Helper routine for getting a gl_framebuffer.
129 */
130 struct gl_framebuffer *
131 _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
132 {
133 struct gl_framebuffer *fb;
134
135 if (id == 0)
136 return NULL;
137
138 fb = (struct gl_framebuffer *)
139 _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
140 return fb;
141 }
142
143
144 /**
145 * Mark the given framebuffer as invalid. This will force the
146 * test for framebuffer completeness to be done before the framebuffer
147 * is used.
148 */
149 static void
150 invalidate_framebuffer(struct gl_framebuffer *fb)
151 {
152 fb->_Status = 0; /* "indeterminate" */
153 }
154
155
156 /**
157 * Return the gl_framebuffer object which corresponds to the given
158 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
159 * Check support for GL_EXT_framebuffer_blit to determine if certain
160 * targets are legal.
161 * \return gl_framebuffer pointer or NULL if target is illegal
162 */
163 static struct gl_framebuffer *
164 get_framebuffer_target(struct gl_context *ctx, GLenum target)
165 {
166 bool have_fb_blit = _mesa_is_gles3(ctx) ||
167 (ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx));
168 switch (target) {
169 case GL_DRAW_FRAMEBUFFER:
170 return have_fb_blit ? ctx->DrawBuffer : NULL;
171 case GL_READ_FRAMEBUFFER:
172 return have_fb_blit ? ctx->ReadBuffer : NULL;
173 case GL_FRAMEBUFFER_EXT:
174 return ctx->DrawBuffer;
175 default:
176 return NULL;
177 }
178 }
179
180
181 /**
182 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
183 * gl_renderbuffer_attachment object.
184 * This function is only used for user-created FB objects, not the
185 * default / window-system FB object.
186 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
187 * the depth buffer attachment point.
188 */
189 struct gl_renderbuffer_attachment *
190 _mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
191 GLenum attachment)
192 {
193 GLuint i;
194
195 assert(_mesa_is_user_fbo(fb));
196
197 switch (attachment) {
198 case GL_COLOR_ATTACHMENT0_EXT:
199 case GL_COLOR_ATTACHMENT1_EXT:
200 case GL_COLOR_ATTACHMENT2_EXT:
201 case GL_COLOR_ATTACHMENT3_EXT:
202 case GL_COLOR_ATTACHMENT4_EXT:
203 case GL_COLOR_ATTACHMENT5_EXT:
204 case GL_COLOR_ATTACHMENT6_EXT:
205 case GL_COLOR_ATTACHMENT7_EXT:
206 case GL_COLOR_ATTACHMENT8_EXT:
207 case GL_COLOR_ATTACHMENT9_EXT:
208 case GL_COLOR_ATTACHMENT10_EXT:
209 case GL_COLOR_ATTACHMENT11_EXT:
210 case GL_COLOR_ATTACHMENT12_EXT:
211 case GL_COLOR_ATTACHMENT13_EXT:
212 case GL_COLOR_ATTACHMENT14_EXT:
213 case GL_COLOR_ATTACHMENT15_EXT:
214 /* Only OpenGL ES 1.x forbids color attachments other than
215 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the
216 * hardware is used.
217 */
218 i = attachment - GL_COLOR_ATTACHMENT0_EXT;
219 if (i >= ctx->Const.MaxColorAttachments
220 || (i > 0 && ctx->API == API_OPENGLES)) {
221 return NULL;
222 }
223 return &fb->Attachment[BUFFER_COLOR0 + i];
224 case GL_DEPTH_STENCIL_ATTACHMENT:
225 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
226 return NULL;
227 /* fall-through */
228 case GL_DEPTH_ATTACHMENT_EXT:
229 return &fb->Attachment[BUFFER_DEPTH];
230 case GL_STENCIL_ATTACHMENT_EXT:
231 return &fb->Attachment[BUFFER_STENCIL];
232 default:
233 return NULL;
234 }
235 }
236
237
238 /**
239 * As above, but only used for getting attachments of the default /
240 * window-system framebuffer (not user-created framebuffer objects).
241 */
242 static struct gl_renderbuffer_attachment *
243 _mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
244 GLenum attachment)
245 {
246 assert(_mesa_is_winsys_fbo(fb));
247
248 if (_mesa_is_gles3(ctx)) {
249 assert(attachment == GL_BACK ||
250 attachment == GL_DEPTH ||
251 attachment == GL_STENCIL);
252 switch (attachment) {
253 case GL_BACK:
254 /* Since there is no stereo rendering in ES 3.0, only return the
255 * LEFT bits.
256 */
257 if (ctx->DrawBuffer->Visual.doubleBufferMode)
258 return &fb->Attachment[BUFFER_BACK_LEFT];
259 return &fb->Attachment[BUFFER_FRONT_LEFT];
260 case GL_DEPTH:
261 return &fb->Attachment[BUFFER_DEPTH];
262 case GL_STENCIL:
263 return &fb->Attachment[BUFFER_STENCIL];
264 }
265 }
266
267 switch (attachment) {
268 case GL_FRONT_LEFT:
269 return &fb->Attachment[BUFFER_FRONT_LEFT];
270 case GL_FRONT_RIGHT:
271 return &fb->Attachment[BUFFER_FRONT_RIGHT];
272 case GL_BACK_LEFT:
273 return &fb->Attachment[BUFFER_BACK_LEFT];
274 case GL_BACK_RIGHT:
275 return &fb->Attachment[BUFFER_BACK_RIGHT];
276 case GL_AUX0:
277 if (fb->Visual.numAuxBuffers == 1) {
278 return &fb->Attachment[BUFFER_AUX0];
279 }
280 return NULL;
281
282 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
283 *
284 * "If the default framebuffer is bound to target, then attachment must
285 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
286 * identifying a color buffer; DEPTH, identifying the depth buffer; or
287 * STENCIL, identifying the stencil buffer."
288 *
289 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
290 * language. However, revision #33 of the ARB_framebuffer_object spec
291 * says:
292 *
293 * "If the default framebuffer is bound to <target>, then <attachment>
294 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
295 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
296 * depth buffer, or the stencil buffer, and <pname> may be
297 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
298 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
299 *
300 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
301 * from glext.h, so shipping apps should not use those values.
302 *
303 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
304 * support queries of the window system FBO.
305 */
306 case GL_DEPTH:
307 return &fb->Attachment[BUFFER_DEPTH];
308 case GL_STENCIL:
309 return &fb->Attachment[BUFFER_STENCIL];
310 default:
311 return NULL;
312 }
313 }
314
315
316
317 /**
318 * Remove any texture or renderbuffer attached to the given attachment
319 * point. Update reference counts, etc.
320 */
321 void
322 _mesa_remove_attachment(struct gl_context *ctx,
323 struct gl_renderbuffer_attachment *att)
324 {
325 struct gl_renderbuffer *rb = att->Renderbuffer;
326
327 /* tell driver that we're done rendering to this texture. */
328 if (rb && rb->NeedsFinishRenderTexture)
329 ctx->Driver.FinishRenderTexture(ctx, rb);
330
331 if (att->Type == GL_TEXTURE) {
332 ASSERT(att->Texture);
333 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
334 ASSERT(!att->Texture);
335 }
336 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
337 ASSERT(!att->Texture);
338 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
339 ASSERT(!att->Renderbuffer);
340 }
341 att->Type = GL_NONE;
342 att->Complete = GL_TRUE;
343 }
344
345 /**
346 * Verify a couple error conditions that will lead to an incomplete FBO and
347 * may cause problems for the driver's RenderTexture path.
348 */
349 static bool
350 driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
351 {
352 const struct gl_texture_image *const texImage =
353 att->Texture->Image[att->CubeMapFace][att->TextureLevel];
354
355 if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
356 return false;
357
358 if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
359 && att->Zoffset >= texImage->Height)
360 || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
361 && att->Zoffset >= texImage->Depth))
362 return false;
363
364 return true;
365 }
366
367 /**
368 * Create a renderbuffer which will be set up by the driver to wrap the
369 * texture image slice.
370 *
371 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
372 * to share most of their framebuffer rendering code between winsys,
373 * renderbuffer, and texture attachments.
374 *
375 * The allocated renderbuffer uses a non-zero Name so that drivers can check
376 * it for determining vertical orientation, but we use ~0 to make it fairly
377 * unambiguous with actual user (non-texture) renderbuffers.
378 */
379 void
380 _mesa_update_texture_renderbuffer(struct gl_context *ctx,
381 struct gl_framebuffer *fb,
382 struct gl_renderbuffer_attachment *att)
383 {
384 struct gl_texture_image *texImage;
385 struct gl_renderbuffer *rb;
386
387 texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
388
389 rb = att->Renderbuffer;
390 if (!rb) {
391 rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
392 if (!rb) {
393 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
394 return;
395 }
396 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
397
398 /* This can't get called on a texture renderbuffer, so set it to NULL
399 * for clarity compared to user renderbuffers.
400 */
401 rb->AllocStorage = NULL;
402
403 rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
404 }
405
406 if (!texImage)
407 return;
408
409 rb->_BaseFormat = texImage->_BaseFormat;
410 rb->Format = texImage->TexFormat;
411 rb->InternalFormat = texImage->InternalFormat;
412 rb->Width = texImage->Width2;
413 rb->Height = texImage->Height2;
414 rb->NumSamples = texImage->NumSamples;
415 rb->TexImage = texImage;
416
417 if (driver_RenderTexture_is_safe(att))
418 ctx->Driver.RenderTexture(ctx, fb, att);
419 }
420
421 /**
422 * Bind a texture object to an attachment point.
423 * The previous binding, if any, will be removed first.
424 */
425 void
426 _mesa_set_texture_attachment(struct gl_context *ctx,
427 struct gl_framebuffer *fb,
428 struct gl_renderbuffer_attachment *att,
429 struct gl_texture_object *texObj,
430 GLenum texTarget, GLuint level, GLuint zoffset,
431 GLboolean layered)
432 {
433 struct gl_renderbuffer *rb = att->Renderbuffer;
434
435 if (rb && rb->NeedsFinishRenderTexture)
436 ctx->Driver.FinishRenderTexture(ctx, rb);
437
438 if (att->Texture == texObj) {
439 /* re-attaching same texture */
440 ASSERT(att->Type == GL_TEXTURE);
441 }
442 else {
443 /* new attachment */
444 _mesa_remove_attachment(ctx, att);
445 att->Type = GL_TEXTURE;
446 assert(!att->Texture);
447 _mesa_reference_texobj(&att->Texture, texObj);
448 }
449 invalidate_framebuffer(fb);
450
451 /* always update these fields */
452 att->TextureLevel = level;
453 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
454 att->Zoffset = zoffset;
455 att->Layered = layered;
456 att->Complete = GL_FALSE;
457
458 _mesa_update_texture_renderbuffer(ctx, fb, att);
459 }
460
461
462 /**
463 * Bind a renderbuffer to an attachment point.
464 * The previous binding, if any, will be removed first.
465 */
466 void
467 _mesa_set_renderbuffer_attachment(struct gl_context *ctx,
468 struct gl_renderbuffer_attachment *att,
469 struct gl_renderbuffer *rb)
470 {
471 /* XXX check if re-doing same attachment, exit early */
472 _mesa_remove_attachment(ctx, att);
473 att->Type = GL_RENDERBUFFER_EXT;
474 att->Texture = NULL; /* just to be safe */
475 att->Complete = GL_FALSE;
476 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
477 }
478
479
480 /**
481 * Fallback for ctx->Driver.FramebufferRenderbuffer()
482 * Attach a renderbuffer object to a framebuffer object.
483 */
484 void
485 _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
486 struct gl_framebuffer *fb,
487 GLenum attachment, struct gl_renderbuffer *rb)
488 {
489 struct gl_renderbuffer_attachment *att;
490
491 _glthread_LOCK_MUTEX(fb->Mutex);
492
493 att = _mesa_get_attachment(ctx, fb, attachment);
494 ASSERT(att);
495 if (rb) {
496 _mesa_set_renderbuffer_attachment(ctx, att, rb);
497 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
498 /* do stencil attachment here (depth already done above) */
499 att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
500 assert(att);
501 _mesa_set_renderbuffer_attachment(ctx, att, rb);
502 }
503 rb->AttachedAnytime = GL_TRUE;
504 }
505 else {
506 _mesa_remove_attachment(ctx, att);
507 }
508
509 invalidate_framebuffer(fb);
510
511 _glthread_UNLOCK_MUTEX(fb->Mutex);
512 }
513
514
515 /**
516 * Fallback for ctx->Driver.ValidateFramebuffer()
517 * Check if the renderbuffer's formats are supported by the software
518 * renderer.
519 * Drivers should probably override this.
520 */
521 void
522 _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
523 {
524 gl_buffer_index buf;
525 for (buf = 0; buf < BUFFER_COUNT; buf++) {
526 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
527 if (rb) {
528 switch (rb->_BaseFormat) {
529 case GL_ALPHA:
530 case GL_LUMINANCE_ALPHA:
531 case GL_LUMINANCE:
532 case GL_INTENSITY:
533 case GL_RED:
534 case GL_RG:
535 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
536 return;
537
538 default:
539 switch (rb->Format) {
540 /* XXX This list is likely incomplete. */
541 case MESA_FORMAT_RGB9_E5_FLOAT:
542 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
543 return;
544 default:;
545 /* render buffer format is supported by software rendering */
546 }
547 }
548 }
549 }
550 }
551
552
553 /**
554 * Return true if the framebuffer has a combined depth/stencil
555 * renderbuffer attached.
556 */
557 GLboolean
558 _mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
559 {
560 const struct gl_renderbuffer_attachment *depth =
561 &fb->Attachment[BUFFER_DEPTH];
562 const struct gl_renderbuffer_attachment *stencil =
563 &fb->Attachment[BUFFER_STENCIL];
564
565 if (depth->Type == stencil->Type) {
566 if (depth->Type == GL_RENDERBUFFER_EXT &&
567 depth->Renderbuffer == stencil->Renderbuffer)
568 return GL_TRUE;
569
570 if (depth->Type == GL_TEXTURE &&
571 depth->Texture == stencil->Texture)
572 return GL_TRUE;
573 }
574
575 return GL_FALSE;
576 }
577
578
579 /**
580 * For debug only.
581 */
582 static void
583 att_incomplete(const char *msg)
584 {
585 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
586 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
587 }
588 }
589
590
591 /**
592 * For debug only.
593 */
594 static void
595 fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
596 {
597 static GLuint msg_id;
598
599 _mesa_gl_debug(ctx, &msg_id,
600 MESA_DEBUG_TYPE_OTHER,
601 MESA_DEBUG_SEVERITY_MEDIUM,
602 "FBO incomplete: %s [%d]\n", msg, index);
603
604 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
605 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
606 }
607 }
608
609
610 /**
611 * Is the given base format a legal format for a color renderbuffer?
612 */
613 GLboolean
614 _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
615 {
616 switch (baseFormat) {
617 case GL_RGB:
618 case GL_RGBA:
619 return GL_TRUE;
620 case GL_LUMINANCE:
621 case GL_LUMINANCE_ALPHA:
622 case GL_INTENSITY:
623 case GL_ALPHA:
624 return ctx->API == API_OPENGL_COMPAT &&
625 ctx->Extensions.ARB_framebuffer_object;
626 case GL_RED:
627 case GL_RG:
628 return ctx->Extensions.ARB_texture_rg;
629 default:
630 return GL_FALSE;
631 }
632 }
633
634
635 /**
636 * Is the given base format a legal format for a color renderbuffer?
637 */
638 static GLboolean
639 is_format_color_renderable(const struct gl_context *ctx, gl_format format, GLenum internalFormat)
640 {
641 const GLenum baseFormat =
642 _mesa_get_format_base_format(format);
643 GLboolean valid;
644
645 valid = _mesa_is_legal_color_format(ctx, baseFormat);
646 if (!valid || _mesa_is_desktop_gl(ctx)) {
647 return valid;
648 }
649
650 /* Reject additional cases for GLES */
651 switch (internalFormat) {
652 case GL_RGBA8_SNORM:
653 case GL_RGB32F:
654 case GL_RGB32I:
655 case GL_RGB32UI:
656 case GL_RGB16F:
657 case GL_RGB16I:
658 case GL_RGB16UI:
659 case GL_RGB8_SNORM:
660 case GL_RGB8I:
661 case GL_RGB8UI:
662 case GL_SRGB8:
663 case GL_RGB9_E5:
664 case GL_RG8_SNORM:
665 case GL_R8_SNORM:
666 return GL_FALSE;
667 default:
668 break;
669 }
670
671 if (format == MESA_FORMAT_ARGB2101010 && internalFormat != GL_RGB10_A2) {
672 return GL_FALSE;
673 }
674
675 return GL_TRUE;
676 }
677
678
679 /**
680 * Is the given base format a legal format for a depth/stencil renderbuffer?
681 */
682 static GLboolean
683 is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
684 {
685 switch (baseFormat) {
686 case GL_DEPTH_COMPONENT:
687 case GL_DEPTH_STENCIL_EXT:
688 return GL_TRUE;
689 default:
690 return GL_FALSE;
691 }
692 }
693
694
695 /**
696 * Test if an attachment point is complete and update its Complete field.
697 * \param format if GL_COLOR, this is a color attachment point,
698 * if GL_DEPTH, this is a depth component attachment point,
699 * if GL_STENCIL, this is a stencil component attachment point.
700 */
701 static void
702 test_attachment_completeness(const struct gl_context *ctx, GLenum format,
703 struct gl_renderbuffer_attachment *att)
704 {
705 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
706
707 /* assume complete */
708 att->Complete = GL_TRUE;
709
710 /* Look for reasons why the attachment might be incomplete */
711 if (att->Type == GL_TEXTURE) {
712 const struct gl_texture_object *texObj = att->Texture;
713 struct gl_texture_image *texImage;
714 GLenum baseFormat;
715
716 if (!texObj) {
717 att_incomplete("no texobj");
718 att->Complete = GL_FALSE;
719 return;
720 }
721
722 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
723 if (!texImage) {
724 att_incomplete("no teximage");
725 att->Complete = GL_FALSE;
726 return;
727 }
728 if (texImage->Width < 1 || texImage->Height < 1) {
729 att_incomplete("teximage width/height=0");
730 att->Complete = GL_FALSE;
731 return;
732 }
733
734 switch (texObj->Target) {
735 case GL_TEXTURE_3D:
736 if (att->Zoffset >= texImage->Depth) {
737 att_incomplete("bad z offset");
738 att->Complete = GL_FALSE;
739 return;
740 }
741 break;
742 case GL_TEXTURE_1D_ARRAY:
743 if (att->Zoffset >= texImage->Height) {
744 att_incomplete("bad 1D-array layer");
745 att->Complete = GL_FALSE;
746 return;
747 }
748 break;
749 case GL_TEXTURE_2D_ARRAY:
750 if (att->Zoffset >= texImage->Depth) {
751 att_incomplete("bad 2D-array layer");
752 att->Complete = GL_FALSE;
753 return;
754 }
755 break;
756 case GL_TEXTURE_CUBE_MAP_ARRAY:
757 if (att->Zoffset >= texImage->Depth) {
758 att_incomplete("bad cube-array layer");
759 att->Complete = GL_FALSE;
760 return;
761 }
762 break;
763 }
764
765 baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
766
767 if (format == GL_COLOR) {
768 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
769 att_incomplete("bad format");
770 att->Complete = GL_FALSE;
771 return;
772 }
773 if (_mesa_is_format_compressed(texImage->TexFormat)) {
774 att_incomplete("compressed internalformat");
775 att->Complete = GL_FALSE;
776 return;
777 }
778 }
779 else if (format == GL_DEPTH) {
780 if (baseFormat == GL_DEPTH_COMPONENT) {
781 /* OK */
782 }
783 else if (ctx->Extensions.EXT_packed_depth_stencil &&
784 ctx->Extensions.ARB_depth_texture &&
785 baseFormat == GL_DEPTH_STENCIL_EXT) {
786 /* OK */
787 }
788 else {
789 att->Complete = GL_FALSE;
790 att_incomplete("bad depth format");
791 return;
792 }
793 }
794 else {
795 ASSERT(format == GL_STENCIL);
796 if (ctx->Extensions.EXT_packed_depth_stencil &&
797 ctx->Extensions.ARB_depth_texture &&
798 baseFormat == GL_DEPTH_STENCIL_EXT) {
799 /* OK */
800 }
801 else {
802 /* no such thing as stencil-only textures */
803 att_incomplete("illegal stencil texture");
804 att->Complete = GL_FALSE;
805 return;
806 }
807 }
808 }
809 else if (att->Type == GL_RENDERBUFFER_EXT) {
810 const GLenum baseFormat =
811 _mesa_get_format_base_format(att->Renderbuffer->Format);
812
813 ASSERT(att->Renderbuffer);
814 if (!att->Renderbuffer->InternalFormat ||
815 att->Renderbuffer->Width < 1 ||
816 att->Renderbuffer->Height < 1) {
817 att_incomplete("0x0 renderbuffer");
818 att->Complete = GL_FALSE;
819 return;
820 }
821 if (format == GL_COLOR) {
822 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
823 att_incomplete("bad renderbuffer color format");
824 att->Complete = GL_FALSE;
825 return;
826 }
827 }
828 else if (format == GL_DEPTH) {
829 if (baseFormat == GL_DEPTH_COMPONENT) {
830 /* OK */
831 }
832 else if (ctx->Extensions.EXT_packed_depth_stencil &&
833 baseFormat == GL_DEPTH_STENCIL_EXT) {
834 /* OK */
835 }
836 else {
837 att_incomplete("bad renderbuffer depth format");
838 att->Complete = GL_FALSE;
839 return;
840 }
841 }
842 else {
843 assert(format == GL_STENCIL);
844 if (baseFormat == GL_STENCIL_INDEX) {
845 /* OK */
846 }
847 else if (ctx->Extensions.EXT_packed_depth_stencil &&
848 baseFormat == GL_DEPTH_STENCIL_EXT) {
849 /* OK */
850 }
851 else {
852 att->Complete = GL_FALSE;
853 att_incomplete("bad renderbuffer stencil format");
854 return;
855 }
856 }
857 }
858 else {
859 ASSERT(att->Type == GL_NONE);
860 /* complete */
861 return;
862 }
863 }
864
865
866 /**
867 * Test if the given framebuffer object is complete and update its
868 * Status field with the results.
869 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
870 * driver to make hardware-specific validation/completeness checks.
871 * Also update the framebuffer's Width and Height fields if the
872 * framebuffer is complete.
873 */
874 void
875 _mesa_test_framebuffer_completeness(struct gl_context *ctx,
876 struct gl_framebuffer *fb)
877 {
878 GLuint numImages;
879 GLenum intFormat = GL_NONE; /* color buffers' internal format */
880 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
881 GLint numSamples = -1;
882 GLint fixedSampleLocations = -1;
883 GLint i;
884 GLuint j;
885 bool layer_count_valid = false;
886 GLuint layer_count = 0, att_layer_count;
887
888 assert(_mesa_is_user_fbo(fb));
889
890 /* we're changing framebuffer fields here */
891 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
892
893 numImages = 0;
894 fb->Width = 0;
895 fb->Height = 0;
896 fb->_AllColorBuffersFixedPoint = GL_TRUE;
897 fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
898
899 /* Start at -2 to more easily loop over all attachment points.
900 * -2: depth buffer
901 * -1: stencil buffer
902 * >=0: color buffer
903 */
904 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
905 struct gl_renderbuffer_attachment *att;
906 GLenum f;
907 gl_format attFormat;
908
909 /*
910 * XXX for ARB_fbo, only check color buffers that are named by
911 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
912 */
913
914 /* check for attachment completeness
915 */
916 if (i == -2) {
917 att = &fb->Attachment[BUFFER_DEPTH];
918 test_attachment_completeness(ctx, GL_DEPTH, att);
919 if (!att->Complete) {
920 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
921 fbo_incomplete(ctx, "depth attachment incomplete", -1);
922 return;
923 }
924 }
925 else if (i == -1) {
926 att = &fb->Attachment[BUFFER_STENCIL];
927 test_attachment_completeness(ctx, GL_STENCIL, att);
928 if (!att->Complete) {
929 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
930 fbo_incomplete(ctx, "stencil attachment incomplete", -1);
931 return;
932 }
933 }
934 else {
935 att = &fb->Attachment[BUFFER_COLOR0 + i];
936 test_attachment_completeness(ctx, GL_COLOR, att);
937 if (!att->Complete) {
938 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
939 fbo_incomplete(ctx, "color attachment incomplete", i);
940 return;
941 }
942 }
943
944 /* get width, height, format of the renderbuffer/texture
945 */
946 if (att->Type == GL_TEXTURE) {
947 const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
948 minWidth = MIN2(minWidth, texImg->Width);
949 maxWidth = MAX2(maxWidth, texImg->Width);
950 minHeight = MIN2(minHeight, texImg->Height);
951 maxHeight = MAX2(maxHeight, texImg->Height);
952 f = texImg->_BaseFormat;
953 attFormat = texImg->TexFormat;
954 numImages++;
955
956 if (!is_format_color_renderable(ctx, attFormat, texImg->InternalFormat) &&
957 !is_legal_depth_format(ctx, f)) {
958 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
959 fbo_incomplete(ctx, "texture attachment incomplete", -1);
960 return;
961 }
962
963 if (numSamples < 0)
964 numSamples = texImg->NumSamples;
965 else if (numSamples != texImg->NumSamples) {
966 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
967 fbo_incomplete(ctx, "inconsistent sample count", -1);
968 return;
969 }
970
971 if (fixedSampleLocations < 0)
972 fixedSampleLocations = texImg->FixedSampleLocations;
973 else if (fixedSampleLocations != texImg->FixedSampleLocations) {
974 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
975 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
976 return;
977 }
978 }
979 else if (att->Type == GL_RENDERBUFFER_EXT) {
980 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
981 maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
982 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
983 maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
984 f = att->Renderbuffer->InternalFormat;
985 attFormat = att->Renderbuffer->Format;
986 numImages++;
987
988 if (numSamples < 0)
989 numSamples = att->Renderbuffer->NumSamples;
990 else if (numSamples != att->Renderbuffer->NumSamples) {
991 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
992 fbo_incomplete(ctx, "inconsistent sample count", -1);
993 return;
994 }
995
996 /* RENDERBUFFER has fixedSampleLocations implicitly true */
997 if (fixedSampleLocations < 0)
998 fixedSampleLocations = GL_TRUE;
999 else if (fixedSampleLocations != GL_TRUE) {
1000 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1001 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1002 return;
1003 }
1004 }
1005 else {
1006 assert(att->Type == GL_NONE);
1007 continue;
1008 }
1009
1010 /* check if integer color */
1011 fb->_IntegerColor = _mesa_is_format_integer_color(attFormat);
1012
1013 /* Update _AllColorBuffersFixedPoint and _HasSNormOrFloatColorBuffer. */
1014 if (i >= 0) {
1015 GLenum type = _mesa_get_format_datatype(attFormat);
1016
1017 fb->_AllColorBuffersFixedPoint =
1018 fb->_AllColorBuffersFixedPoint &&
1019 (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
1020
1021 fb->_HasSNormOrFloatColorBuffer =
1022 fb->_HasSNormOrFloatColorBuffer ||
1023 type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
1024 }
1025
1026 /* Error-check width, height, format */
1027 if (numImages == 1) {
1028 /* save format */
1029 if (i >= 0) {
1030 intFormat = f;
1031 }
1032 }
1033 else {
1034 if (!ctx->Extensions.ARB_framebuffer_object) {
1035 /* check that width, height, format are same */
1036 if (minWidth != maxWidth || minHeight != maxHeight) {
1037 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
1038 fbo_incomplete(ctx, "width or height mismatch", -1);
1039 return;
1040 }
1041 /* check that all color buffers are the same format */
1042 if (intFormat != GL_NONE && f != intFormat) {
1043 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
1044 fbo_incomplete(ctx, "format mismatch", -1);
1045 return;
1046 }
1047 }
1048 }
1049
1050 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1051 */
1052 if (att->Type == GL_RENDERBUFFER &&
1053 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1054 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1055 fbo_incomplete(ctx, "unsupported renderbuffer format", i);
1056 return;
1057 }
1058
1059 /* Check that layered rendering is consistent. */
1060 att_layer_count = att->Layered ? att->Renderbuffer->Depth : 0;
1061 if (!layer_count_valid) {
1062 layer_count = att_layer_count;
1063 layer_count_valid = true;
1064 } else if (layer_count != att_layer_count) {
1065 if (layer_count == 0 || att_layer_count == 0) {
1066 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1067 fbo_incomplete(ctx, "framebuffer attachment layer mode is inconsistent", i);
1068 } else {
1069 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB;
1070 fbo_incomplete(ctx, "framebuffer attachment layer count is inconsistent", i);
1071 }
1072 return;
1073 }
1074 }
1075
1076 fb->Layered = layer_count > 0;
1077
1078 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
1079 /* Check that all DrawBuffers are present */
1080 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
1081 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1082 const struct gl_renderbuffer_attachment *att
1083 = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
1084 assert(att);
1085 if (att->Type == GL_NONE) {
1086 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1087 fbo_incomplete(ctx, "missing drawbuffer", j);
1088 return;
1089 }
1090 }
1091 }
1092
1093 /* Check that the ReadBuffer is present */
1094 if (fb->ColorReadBuffer != GL_NONE) {
1095 const struct gl_renderbuffer_attachment *att
1096 = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
1097 assert(att);
1098 if (att->Type == GL_NONE) {
1099 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
1100 fbo_incomplete(ctx, "missing readbuffer", -1);
1101 return;
1102 }
1103 }
1104 }
1105
1106 if (numImages == 0) {
1107 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1108 fbo_incomplete(ctx, "no attachments", -1);
1109 return;
1110 }
1111
1112 /* Provisionally set status = COMPLETE ... */
1113 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
1114
1115 /* ... but the driver may say the FB is incomplete.
1116 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1117 * if anything.
1118 */
1119 if (ctx->Driver.ValidateFramebuffer) {
1120 ctx->Driver.ValidateFramebuffer(ctx, fb);
1121 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1122 fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
1123 }
1124 }
1125
1126 if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
1127 /*
1128 * Note that if ARB_framebuffer_object is supported and the attached
1129 * renderbuffers/textures are different sizes, the framebuffer
1130 * width/height will be set to the smallest width/height.
1131 */
1132 fb->Width = minWidth;
1133 fb->Height = minHeight;
1134
1135 /* finally, update the visual info for the framebuffer */
1136 _mesa_update_framebuffer_visual(ctx, fb);
1137 }
1138 }
1139
1140
1141 GLboolean GLAPIENTRY
1142 _mesa_IsRenderbuffer(GLuint renderbuffer)
1143 {
1144 GET_CURRENT_CONTEXT(ctx);
1145 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1146 if (renderbuffer) {
1147 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1148 if (rb != NULL && rb != &DummyRenderbuffer)
1149 return GL_TRUE;
1150 }
1151 return GL_FALSE;
1152 }
1153
1154
1155 static void
1156 bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
1157 {
1158 struct gl_renderbuffer *newRb;
1159 GET_CURRENT_CONTEXT(ctx);
1160
1161 if (target != GL_RENDERBUFFER_EXT) {
1162 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
1163 return;
1164 }
1165
1166 /* No need to flush here since the render buffer binding has no
1167 * effect on rendering state.
1168 */
1169
1170 if (renderbuffer) {
1171 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1172 if (newRb == &DummyRenderbuffer) {
1173 /* ID was reserved, but no real renderbuffer object made yet */
1174 newRb = NULL;
1175 }
1176 else if (!newRb && !allow_user_names) {
1177 /* All RB IDs must be Gen'd */
1178 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
1179 return;
1180 }
1181
1182 if (!newRb) {
1183 /* create new renderbuffer object */
1184 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1185 if (!newRb) {
1186 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
1187 return;
1188 }
1189 ASSERT(newRb->AllocStorage);
1190 _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
1191 newRb->RefCount = 1; /* referenced by hash table */
1192 }
1193 }
1194 else {
1195 newRb = NULL;
1196 }
1197
1198 ASSERT(newRb != &DummyRenderbuffer);
1199
1200 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
1201 }
1202
1203 void GLAPIENTRY
1204 _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1205 {
1206 GET_CURRENT_CONTEXT(ctx);
1207
1208 /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1209 * entry point, but they allow the use of user-generated names.
1210 */
1211 bind_renderbuffer(target, renderbuffer, _mesa_is_gles(ctx));
1212 }
1213
1214 void GLAPIENTRY
1215 _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1216 {
1217 /* This function should not be in the dispatch table for core profile /
1218 * OpenGL 3.1, so execution should never get here in those cases -- no
1219 * need for an explicit test.
1220 */
1221 bind_renderbuffer(target, renderbuffer, true);
1222 }
1223
1224
1225 /**
1226 * Remove the specified renderbuffer or texture from any attachment point in
1227 * the framebuffer.
1228 *
1229 * \returns
1230 * \c true if the renderbuffer was detached from an attachment point. \c
1231 * false otherwise.
1232 */
1233 bool
1234 _mesa_detach_renderbuffer(struct gl_context *ctx,
1235 struct gl_framebuffer *fb,
1236 const void *att)
1237 {
1238 unsigned i;
1239 bool progress = false;
1240
1241 for (i = 0; i < BUFFER_COUNT; i++) {
1242 if (fb->Attachment[i].Texture == att
1243 || fb->Attachment[i].Renderbuffer == att) {
1244 _mesa_remove_attachment(ctx, &fb->Attachment[i]);
1245 progress = true;
1246 }
1247 }
1248
1249 /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1250 * Completeness," of the OpenGL 3.1 spec says:
1251 *
1252 * "Performing any of the following actions may change whether the
1253 * framebuffer is considered complete or incomplete:
1254 *
1255 * ...
1256 *
1257 * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1258 * containing an image that is attached to a framebuffer object
1259 * that is bound to the framebuffer."
1260 */
1261 if (progress)
1262 invalidate_framebuffer(fb);
1263
1264 return progress;
1265 }
1266
1267
1268 void GLAPIENTRY
1269 _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
1270 {
1271 GLint i;
1272 GET_CURRENT_CONTEXT(ctx);
1273
1274 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1275
1276 for (i = 0; i < n; i++) {
1277 if (renderbuffers[i] > 0) {
1278 struct gl_renderbuffer *rb;
1279 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
1280 if (rb) {
1281 /* check if deleting currently bound renderbuffer object */
1282 if (rb == ctx->CurrentRenderbuffer) {
1283 /* bind default */
1284 ASSERT(rb->RefCount >= 2);
1285 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
1286 }
1287
1288 /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
1289 * subsection "Attaching Renderbuffer Images to a Framebuffer," of
1290 * the OpenGL 3.1 spec says:
1291 *
1292 * "If a renderbuffer object is deleted while its image is
1293 * attached to one or more attachment points in the currently
1294 * bound framebuffer, then it is as if FramebufferRenderbuffer
1295 * had been called, with a renderbuffer of 0, for each
1296 * attachment point to which this image was attached in the
1297 * currently bound framebuffer. In other words, this
1298 * renderbuffer image is first detached from all attachment
1299 * points in the currently bound framebuffer. Note that the
1300 * renderbuffer image is specifically not detached from any
1301 * non-bound framebuffers. Detaching the image from any
1302 * non-bound framebuffers is the responsibility of the
1303 * application.
1304 */
1305 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1306 _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
1307 }
1308 if (_mesa_is_user_fbo(ctx->ReadBuffer)
1309 && ctx->ReadBuffer != ctx->DrawBuffer) {
1310 _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
1311 }
1312
1313 /* Remove from hash table immediately, to free the ID.
1314 * But the object will not be freed until it's no longer
1315 * referenced anywhere else.
1316 */
1317 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
1318
1319 if (rb != &DummyRenderbuffer) {
1320 /* no longer referenced by hash table */
1321 _mesa_reference_renderbuffer(&rb, NULL);
1322 }
1323 }
1324 }
1325 }
1326 }
1327
1328
1329 void GLAPIENTRY
1330 _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
1331 {
1332 GET_CURRENT_CONTEXT(ctx);
1333 GLuint first;
1334 GLint i;
1335
1336 if (n < 0) {
1337 _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
1338 return;
1339 }
1340
1341 if (!renderbuffers)
1342 return;
1343
1344 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1345
1346 for (i = 0; i < n; i++) {
1347 GLuint name = first + i;
1348 renderbuffers[i] = name;
1349 /* insert dummy placeholder into hash table */
1350 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1351 _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
1352 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1353 }
1354 }
1355
1356
1357 /**
1358 * Given an internal format token for a render buffer, return the
1359 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
1360 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
1361 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
1362 *
1363 * This is similar to _mesa_base_tex_format() but the set of valid
1364 * internal formats is different.
1365 *
1366 * Note that even if a format is determined to be legal here, validation
1367 * of the FBO may fail if the format is not supported by the driver/GPU.
1368 *
1369 * \param internalFormat as passed to glRenderbufferStorage()
1370 * \return the base internal format, or 0 if internalFormat is illegal
1371 */
1372 GLenum
1373 _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
1374 {
1375 /*
1376 * Notes: some formats such as alpha, luminance, etc. were added
1377 * with GL_ARB_framebuffer_object.
1378 */
1379 switch (internalFormat) {
1380 case GL_ALPHA:
1381 case GL_ALPHA4:
1382 case GL_ALPHA8:
1383 case GL_ALPHA12:
1384 case GL_ALPHA16:
1385 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1386 ? GL_ALPHA : 0;
1387 case GL_LUMINANCE:
1388 case GL_LUMINANCE4:
1389 case GL_LUMINANCE8:
1390 case GL_LUMINANCE12:
1391 case GL_LUMINANCE16:
1392 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1393 ? GL_LUMINANCE : 0;
1394 case GL_LUMINANCE_ALPHA:
1395 case GL_LUMINANCE4_ALPHA4:
1396 case GL_LUMINANCE6_ALPHA2:
1397 case GL_LUMINANCE8_ALPHA8:
1398 case GL_LUMINANCE12_ALPHA4:
1399 case GL_LUMINANCE12_ALPHA12:
1400 case GL_LUMINANCE16_ALPHA16:
1401 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1402 ? GL_LUMINANCE_ALPHA : 0;
1403 case GL_INTENSITY:
1404 case GL_INTENSITY4:
1405 case GL_INTENSITY8:
1406 case GL_INTENSITY12:
1407 case GL_INTENSITY16:
1408 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1409 ? GL_INTENSITY : 0;
1410 case GL_RGB8:
1411 return GL_RGB;
1412 case GL_RGB:
1413 case GL_R3_G3_B2:
1414 case GL_RGB4:
1415 case GL_RGB5:
1416 case GL_RGB10:
1417 case GL_RGB12:
1418 case GL_RGB16:
1419 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
1420 case GL_SRGB8_EXT:
1421 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
1422 case GL_RGBA4:
1423 case GL_RGB5_A1:
1424 case GL_RGBA8:
1425 return GL_RGBA;
1426 case GL_RGBA:
1427 case GL_RGBA2:
1428 case GL_RGBA12:
1429 case GL_RGBA16:
1430 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
1431 case GL_RGB10_A2:
1432 case GL_SRGB8_ALPHA8_EXT:
1433 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
1434 case GL_STENCIL_INDEX:
1435 case GL_STENCIL_INDEX1_EXT:
1436 case GL_STENCIL_INDEX4_EXT:
1437 case GL_STENCIL_INDEX16_EXT:
1438 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
1439 * OpenGL ES, but Mesa does not currently support them.
1440 */
1441 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
1442 case GL_STENCIL_INDEX8_EXT:
1443 return GL_STENCIL_INDEX;
1444 case GL_DEPTH_COMPONENT:
1445 case GL_DEPTH_COMPONENT32:
1446 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
1447 case GL_DEPTH_COMPONENT16:
1448 case GL_DEPTH_COMPONENT24:
1449 return GL_DEPTH_COMPONENT;
1450 case GL_DEPTH_STENCIL_EXT:
1451 return _mesa_is_desktop_gl(ctx)
1452 && ctx->Extensions.EXT_packed_depth_stencil
1453 ? GL_DEPTH_STENCIL_EXT : 0;
1454 case GL_DEPTH24_STENCIL8_EXT:
1455 return ctx->Extensions.EXT_packed_depth_stencil
1456 ? GL_DEPTH_STENCIL_EXT : 0;
1457 case GL_DEPTH_COMPONENT32F:
1458 return ctx->Version >= 30
1459 || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
1460 ? GL_DEPTH_COMPONENT : 0;
1461 case GL_DEPTH32F_STENCIL8:
1462 return ctx->Version >= 30
1463 || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
1464 ? GL_DEPTH_STENCIL : 0;
1465 case GL_RED:
1466 case GL_R16:
1467 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1468 ? GL_RED : 0;
1469 case GL_R8:
1470 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1471 ? GL_RED : 0;
1472 case GL_RG:
1473 case GL_RG16:
1474 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1475 ? GL_RG : 0;
1476 case GL_RG8:
1477 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1478 ? GL_RG : 0;
1479 /* signed normalized texture formats */
1480 case GL_RED_SNORM:
1481 case GL_R8_SNORM:
1482 case GL_R16_SNORM:
1483 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1484 ? GL_RED : 0;
1485 case GL_RG_SNORM:
1486 case GL_RG8_SNORM:
1487 case GL_RG16_SNORM:
1488 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1489 ? GL_RG : 0;
1490 case GL_RGB_SNORM:
1491 case GL_RGB8_SNORM:
1492 case GL_RGB16_SNORM:
1493 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1494 ? GL_RGB : 0;
1495 case GL_RGBA_SNORM:
1496 case GL_RGBA8_SNORM:
1497 case GL_RGBA16_SNORM:
1498 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1499 ? GL_RGBA : 0;
1500 case GL_ALPHA_SNORM:
1501 case GL_ALPHA8_SNORM:
1502 case GL_ALPHA16_SNORM:
1503 return ctx->API == API_OPENGL_COMPAT &&
1504 ctx->Extensions.EXT_texture_snorm &&
1505 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1506 case GL_R16F:
1507 case GL_R32F:
1508 return ((_mesa_is_desktop_gl(ctx) &&
1509 ctx->Extensions.ARB_texture_rg &&
1510 ctx->Extensions.ARB_texture_float) ||
1511 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1512 ? GL_RED : 0;
1513 case GL_RG16F:
1514 case GL_RG32F:
1515 return ((_mesa_is_desktop_gl(ctx) &&
1516 ctx->Extensions.ARB_texture_rg &&
1517 ctx->Extensions.ARB_texture_float) ||
1518 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1519 ? GL_RG : 0;
1520 case GL_RGB16F:
1521 case GL_RGB32F:
1522 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
1523 ? GL_RGB : 0;
1524 case GL_RGBA16F:
1525 case GL_RGBA32F:
1526 return ((_mesa_is_desktop_gl(ctx) &&
1527 ctx->Extensions.ARB_texture_float) ||
1528 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1529 ? GL_RGBA : 0;
1530 case GL_ALPHA16F_ARB:
1531 case GL_ALPHA32F_ARB:
1532 return ctx->API == API_OPENGL_COMPAT &&
1533 ctx->Extensions.ARB_texture_float &&
1534 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1535 case GL_LUMINANCE16F_ARB:
1536 case GL_LUMINANCE32F_ARB:
1537 return ctx->API == API_OPENGL_COMPAT &&
1538 ctx->Extensions.ARB_texture_float &&
1539 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1540 case GL_LUMINANCE_ALPHA16F_ARB:
1541 case GL_LUMINANCE_ALPHA32F_ARB:
1542 return ctx->API == API_OPENGL_COMPAT &&
1543 ctx->Extensions.ARB_texture_float &&
1544 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1545 case GL_INTENSITY16F_ARB:
1546 case GL_INTENSITY32F_ARB:
1547 return ctx->API == API_OPENGL_COMPAT &&
1548 ctx->Extensions.ARB_texture_float &&
1549 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1550 case GL_RGB9_E5:
1551 return (_mesa_is_desktop_gl(ctx)
1552 && ctx->Extensions.EXT_texture_shared_exponent)
1553 ? GL_RGB : 0;
1554 case GL_R11F_G11F_B10F:
1555 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
1556 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1557 ? GL_RGB : 0;
1558
1559 case GL_RGBA8UI_EXT:
1560 case GL_RGBA16UI_EXT:
1561 case GL_RGBA32UI_EXT:
1562 case GL_RGBA8I_EXT:
1563 case GL_RGBA16I_EXT:
1564 case GL_RGBA32I_EXT:
1565 return ctx->Version >= 30
1566 || (_mesa_is_desktop_gl(ctx) &&
1567 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
1568
1569 case GL_RGB8UI_EXT:
1570 case GL_RGB16UI_EXT:
1571 case GL_RGB32UI_EXT:
1572 case GL_RGB8I_EXT:
1573 case GL_RGB16I_EXT:
1574 case GL_RGB32I_EXT:
1575 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
1576 ? GL_RGB : 0;
1577 case GL_R8UI:
1578 case GL_R8I:
1579 case GL_R16UI:
1580 case GL_R16I:
1581 case GL_R32UI:
1582 case GL_R32I:
1583 return ctx->Version >= 30
1584 || (_mesa_is_desktop_gl(ctx) &&
1585 ctx->Extensions.ARB_texture_rg &&
1586 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
1587
1588 case GL_RG8UI:
1589 case GL_RG8I:
1590 case GL_RG16UI:
1591 case GL_RG16I:
1592 case GL_RG32UI:
1593 case GL_RG32I:
1594 return ctx->Version >= 30
1595 || (_mesa_is_desktop_gl(ctx) &&
1596 ctx->Extensions.ARB_texture_rg &&
1597 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
1598
1599 case GL_INTENSITY8I_EXT:
1600 case GL_INTENSITY8UI_EXT:
1601 case GL_INTENSITY16I_EXT:
1602 case GL_INTENSITY16UI_EXT:
1603 case GL_INTENSITY32I_EXT:
1604 case GL_INTENSITY32UI_EXT:
1605 return ctx->API == API_OPENGL_COMPAT &&
1606 ctx->Extensions.EXT_texture_integer &&
1607 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1608
1609 case GL_LUMINANCE8I_EXT:
1610 case GL_LUMINANCE8UI_EXT:
1611 case GL_LUMINANCE16I_EXT:
1612 case GL_LUMINANCE16UI_EXT:
1613 case GL_LUMINANCE32I_EXT:
1614 case GL_LUMINANCE32UI_EXT:
1615 return ctx->API == API_OPENGL_COMPAT &&
1616 ctx->Extensions.EXT_texture_integer &&
1617 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1618
1619 case GL_LUMINANCE_ALPHA8I_EXT:
1620 case GL_LUMINANCE_ALPHA8UI_EXT:
1621 case GL_LUMINANCE_ALPHA16I_EXT:
1622 case GL_LUMINANCE_ALPHA16UI_EXT:
1623 case GL_LUMINANCE_ALPHA32I_EXT:
1624 case GL_LUMINANCE_ALPHA32UI_EXT:
1625 return ctx->API == API_OPENGL_COMPAT &&
1626 ctx->Extensions.EXT_texture_integer &&
1627 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1628
1629 case GL_ALPHA8I_EXT:
1630 case GL_ALPHA8UI_EXT:
1631 case GL_ALPHA16I_EXT:
1632 case GL_ALPHA16UI_EXT:
1633 case GL_ALPHA32I_EXT:
1634 case GL_ALPHA32UI_EXT:
1635 return ctx->API == API_OPENGL_COMPAT &&
1636 ctx->Extensions.EXT_texture_integer &&
1637 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1638
1639 case GL_RGB10_A2UI:
1640 return (_mesa_is_desktop_gl(ctx) &&
1641 ctx->Extensions.ARB_texture_rgb10_a2ui)
1642 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
1643
1644 case GL_RGB565:
1645 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
1646 ? GL_RGB : 0;
1647 default:
1648 return 0;
1649 }
1650 }
1651
1652
1653 /**
1654 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
1655 */
1656 static void
1657 invalidate_rb(GLuint key, void *data, void *userData)
1658 {
1659 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
1660 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
1661
1662 /* If this is a user-created FBO */
1663 if (_mesa_is_user_fbo(fb)) {
1664 GLuint i;
1665 for (i = 0; i < BUFFER_COUNT; i++) {
1666 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1667 if (att->Type == GL_RENDERBUFFER &&
1668 att->Renderbuffer == rb) {
1669 /* Mark fb status as indeterminate to force re-validation */
1670 fb->_Status = 0;
1671 return;
1672 }
1673 }
1674 }
1675 }
1676
1677
1678 /** sentinal value, see below */
1679 #define NO_SAMPLES 1000
1680
1681
1682 /**
1683 * Helper function used by _mesa_RenderbufferStorage() and
1684 * _mesa_RenderbufferStorageMultisample().
1685 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
1686 */
1687 static void
1688 renderbuffer_storage(GLenum target, GLenum internalFormat,
1689 GLsizei width, GLsizei height, GLsizei samples)
1690 {
1691 const char *func = samples == NO_SAMPLES ?
1692 "glRenderbufferStorage" : "glRenderbufferStorageMultisample";
1693 struct gl_renderbuffer *rb;
1694 GLenum baseFormat;
1695 GLenum sample_count_error;
1696 GET_CURRENT_CONTEXT(ctx);
1697
1698 if (MESA_VERBOSE & VERBOSE_API) {
1699 if (samples == NO_SAMPLES)
1700 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
1701 func,
1702 _mesa_lookup_enum_by_nr(target),
1703 _mesa_lookup_enum_by_nr(internalFormat),
1704 width, height);
1705 else
1706 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
1707 func,
1708 _mesa_lookup_enum_by_nr(target),
1709 _mesa_lookup_enum_by_nr(internalFormat),
1710 width, height, samples);
1711 }
1712
1713 if (target != GL_RENDERBUFFER_EXT) {
1714 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
1715 return;
1716 }
1717
1718 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
1719 if (baseFormat == 0) {
1720 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
1721 func, _mesa_lookup_enum_by_nr(internalFormat));
1722 return;
1723 }
1724
1725 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1726 _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
1727 return;
1728 }
1729
1730 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1731 _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
1732 return;
1733 }
1734
1735 if (samples == NO_SAMPLES) {
1736 /* NumSamples == 0 indicates non-multisampling */
1737 samples = 0;
1738 }
1739 else {
1740 /* check the sample count;
1741 * note: driver may choose to use more samples than what's requested
1742 */
1743 sample_count_error = _mesa_check_sample_count(ctx, target,
1744 internalFormat, samples);
1745 if (sample_count_error != GL_NO_ERROR) {
1746 _mesa_error(ctx, sample_count_error, "%s(samples)", func);
1747 return;
1748 }
1749 }
1750
1751 rb = ctx->CurrentRenderbuffer;
1752 if (!rb) {
1753 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1754 return;
1755 }
1756
1757 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1758
1759 if (rb->InternalFormat == internalFormat &&
1760 rb->Width == (GLuint) width &&
1761 rb->Height == (GLuint) height &&
1762 rb->NumSamples == samples) {
1763 /* no change in allocation needed */
1764 return;
1765 }
1766
1767 /* These MUST get set by the AllocStorage func */
1768 rb->Format = MESA_FORMAT_NONE;
1769 rb->NumSamples = samples;
1770
1771 /* Now allocate the storage */
1772 ASSERT(rb->AllocStorage);
1773 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
1774 /* No error - check/set fields now */
1775 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
1776 assert(rb->Width == (GLuint) width);
1777 assert(rb->Height == (GLuint) height);
1778 rb->InternalFormat = internalFormat;
1779 rb->_BaseFormat = baseFormat;
1780 assert(rb->_BaseFormat != 0);
1781 }
1782 else {
1783 /* Probably ran out of memory - clear the fields */
1784 rb->Width = 0;
1785 rb->Height = 0;
1786 rb->Format = MESA_FORMAT_NONE;
1787 rb->InternalFormat = GL_NONE;
1788 rb->_BaseFormat = GL_NONE;
1789 rb->NumSamples = 0;
1790 }
1791
1792 /* Invalidate the framebuffers the renderbuffer is attached in. */
1793 if (rb->AttachedAnytime) {
1794 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
1795 }
1796 }
1797
1798
1799 void GLAPIENTRY
1800 _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
1801 {
1802 struct gl_renderbuffer *rb;
1803 GET_CURRENT_CONTEXT(ctx);
1804
1805 if (!ctx->Extensions.OES_EGL_image) {
1806 _mesa_error(ctx, GL_INVALID_OPERATION,
1807 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
1808 return;
1809 }
1810
1811 if (target != GL_RENDERBUFFER) {
1812 _mesa_error(ctx, GL_INVALID_ENUM,
1813 "EGLImageTargetRenderbufferStorageOES");
1814 return;
1815 }
1816
1817 rb = ctx->CurrentRenderbuffer;
1818 if (!rb) {
1819 _mesa_error(ctx, GL_INVALID_OPERATION,
1820 "EGLImageTargetRenderbufferStorageOES");
1821 return;
1822 }
1823
1824 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1825
1826 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
1827 }
1828
1829
1830 /**
1831 * Helper function for _mesa_GetRenderbufferParameteriv() and
1832 * _mesa_GetFramebufferAttachmentParameteriv()
1833 * We have to be careful to respect the base format. For example, if a
1834 * renderbuffer/texture was created with internalFormat=GL_RGB but the
1835 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
1836 * we need to return zero.
1837 */
1838 static GLint
1839 get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
1840 {
1841 if (_mesa_base_format_has_channel(baseFormat, pname))
1842 return _mesa_get_format_bits(format, pname);
1843 else
1844 return 0;
1845 }
1846
1847
1848
1849 void GLAPIENTRY
1850 _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
1851 GLsizei width, GLsizei height)
1852 {
1853 /* GL_ARB_fbo says calling this function is equivalent to calling
1854 * glRenderbufferStorageMultisample() with samples=0. We pass in
1855 * a token value here just for error reporting purposes.
1856 */
1857 renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
1858 }
1859
1860
1861 void GLAPIENTRY
1862 _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
1863 GLenum internalFormat,
1864 GLsizei width, GLsizei height)
1865 {
1866 renderbuffer_storage(target, internalFormat, width, height, samples);
1867 }
1868
1869
1870 /**
1871 * OpenGL ES version of glRenderBufferStorage.
1872 */
1873 void GLAPIENTRY
1874 _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1875 GLsizei width, GLsizei height)
1876 {
1877 switch (internalFormat) {
1878 case GL_RGB565:
1879 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
1880 /* choose a closest format */
1881 internalFormat = GL_RGB5;
1882 break;
1883 default:
1884 break;
1885 }
1886
1887 renderbuffer_storage(target, internalFormat, width, height, 0);
1888 }
1889
1890
1891 void GLAPIENTRY
1892 _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
1893 {
1894 struct gl_renderbuffer *rb;
1895 GET_CURRENT_CONTEXT(ctx);
1896
1897 if (target != GL_RENDERBUFFER_EXT) {
1898 _mesa_error(ctx, GL_INVALID_ENUM,
1899 "glGetRenderbufferParameterivEXT(target)");
1900 return;
1901 }
1902
1903 rb = ctx->CurrentRenderbuffer;
1904 if (!rb) {
1905 _mesa_error(ctx, GL_INVALID_OPERATION,
1906 "glGetRenderbufferParameterivEXT");
1907 return;
1908 }
1909
1910 /* No need to flush here since we're just quering state which is
1911 * not effected by rendering.
1912 */
1913
1914 switch (pname) {
1915 case GL_RENDERBUFFER_WIDTH_EXT:
1916 *params = rb->Width;
1917 return;
1918 case GL_RENDERBUFFER_HEIGHT_EXT:
1919 *params = rb->Height;
1920 return;
1921 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
1922 *params = rb->InternalFormat;
1923 return;
1924 case GL_RENDERBUFFER_RED_SIZE_EXT:
1925 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
1926 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
1927 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
1928 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
1929 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
1930 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
1931 break;
1932 case GL_RENDERBUFFER_SAMPLES:
1933 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
1934 || _mesa_is_gles3(ctx)) {
1935 *params = rb->NumSamples;
1936 break;
1937 }
1938 /* fallthrough */
1939 default:
1940 _mesa_error(ctx, GL_INVALID_ENUM,
1941 "glGetRenderbufferParameterivEXT(target)");
1942 return;
1943 }
1944 }
1945
1946
1947 GLboolean GLAPIENTRY
1948 _mesa_IsFramebuffer(GLuint framebuffer)
1949 {
1950 GET_CURRENT_CONTEXT(ctx);
1951 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1952 if (framebuffer) {
1953 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
1954 if (rb != NULL && rb != &DummyFramebuffer)
1955 return GL_TRUE;
1956 }
1957 return GL_FALSE;
1958 }
1959
1960
1961 /**
1962 * Check if any of the attachments of the given framebuffer are textures
1963 * (render to texture). Call ctx->Driver.RenderTexture() for such
1964 * attachments.
1965 */
1966 static void
1967 check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1968 {
1969 GLuint i;
1970 ASSERT(ctx->Driver.RenderTexture);
1971
1972 if (_mesa_is_winsys_fbo(fb))
1973 return; /* can't render to texture with winsys framebuffers */
1974
1975 for (i = 0; i < BUFFER_COUNT; i++) {
1976 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1977 if (att->Texture && att->Renderbuffer->TexImage
1978 && driver_RenderTexture_is_safe(att)) {
1979 ctx->Driver.RenderTexture(ctx, fb, att);
1980 }
1981 }
1982 }
1983
1984
1985 /**
1986 * Examine all the framebuffer's attachments to see if any are textures.
1987 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
1988 * notify the device driver that the texture image may have changed.
1989 */
1990 static void
1991 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1992 {
1993 if (_mesa_is_winsys_fbo(fb))
1994 return; /* can't render to texture with winsys framebuffers */
1995
1996 if (ctx->Driver.FinishRenderTexture) {
1997 GLuint i;
1998 for (i = 0; i < BUFFER_COUNT; i++) {
1999 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2000 struct gl_renderbuffer *rb = att->Renderbuffer;
2001 if (rb && rb->NeedsFinishRenderTexture) {
2002 ctx->Driver.FinishRenderTexture(ctx, rb);
2003 }
2004 }
2005 }
2006 }
2007
2008
2009 static void
2010 bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names)
2011 {
2012 struct gl_framebuffer *newDrawFb, *newReadFb;
2013 struct gl_framebuffer *oldDrawFb, *oldReadFb;
2014 GLboolean bindReadBuf, bindDrawBuf;
2015 GET_CURRENT_CONTEXT(ctx);
2016
2017 #ifdef DEBUG
2018 if (ctx->Extensions.ARB_framebuffer_object) {
2019 ASSERT(ctx->Extensions.EXT_framebuffer_blit);
2020 }
2021 #endif
2022
2023 switch (target) {
2024 case GL_DRAW_FRAMEBUFFER_EXT:
2025 if (!ctx->Extensions.EXT_framebuffer_blit) {
2026 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2027 return;
2028 }
2029 bindDrawBuf = GL_TRUE;
2030 bindReadBuf = GL_FALSE;
2031 break;
2032 case GL_READ_FRAMEBUFFER_EXT:
2033 if (!ctx->Extensions.EXT_framebuffer_blit) {
2034 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2035 return;
2036 }
2037 bindDrawBuf = GL_FALSE;
2038 bindReadBuf = GL_TRUE;
2039 break;
2040 case GL_FRAMEBUFFER_EXT:
2041 bindDrawBuf = GL_TRUE;
2042 bindReadBuf = GL_TRUE;
2043 break;
2044 default:
2045 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2046 return;
2047 }
2048
2049 if (framebuffer) {
2050 /* Binding a user-created framebuffer object */
2051 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
2052 if (newDrawFb == &DummyFramebuffer) {
2053 /* ID was reserved, but no real framebuffer object made yet */
2054 newDrawFb = NULL;
2055 }
2056 else if (!newDrawFb && !allow_user_names) {
2057 /* All FBO IDs must be Gen'd */
2058 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
2059 return;
2060 }
2061
2062 if (!newDrawFb) {
2063 /* create new framebuffer object */
2064 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
2065 if (!newDrawFb) {
2066 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
2067 return;
2068 }
2069 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
2070 }
2071 newReadFb = newDrawFb;
2072 }
2073 else {
2074 /* Binding the window system framebuffer (which was originally set
2075 * with MakeCurrent).
2076 */
2077 newDrawFb = ctx->WinSysDrawBuffer;
2078 newReadFb = ctx->WinSysReadBuffer;
2079 }
2080
2081 ASSERT(newDrawFb);
2082 ASSERT(newDrawFb != &DummyFramebuffer);
2083
2084 /* save pointers to current/old framebuffers */
2085 oldDrawFb = ctx->DrawBuffer;
2086 oldReadFb = ctx->ReadBuffer;
2087
2088 /* check if really changing bindings */
2089 if (oldDrawFb == newDrawFb)
2090 bindDrawBuf = GL_FALSE;
2091 if (oldReadFb == newReadFb)
2092 bindReadBuf = GL_FALSE;
2093
2094 /*
2095 * OK, now bind the new Draw/Read framebuffers, if they're changing.
2096 *
2097 * We also check if we're beginning and/or ending render-to-texture.
2098 * When a framebuffer with texture attachments is unbound, call
2099 * ctx->Driver.FinishRenderTexture().
2100 * When a framebuffer with texture attachments is bound, call
2101 * ctx->Driver.RenderTexture().
2102 *
2103 * Note that if the ReadBuffer has texture attachments we don't consider
2104 * that a render-to-texture case.
2105 */
2106 if (bindReadBuf) {
2107 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2108
2109 /* check if old readbuffer was render-to-texture */
2110 check_end_texture_render(ctx, oldReadFb);
2111
2112 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
2113 }
2114
2115 if (bindDrawBuf) {
2116 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2117
2118 /* check if old framebuffer had any texture attachments */
2119 if (oldDrawFb)
2120 check_end_texture_render(ctx, oldDrawFb);
2121
2122 /* check if newly bound framebuffer has any texture attachments */
2123 check_begin_texture_render(ctx, newDrawFb);
2124
2125 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
2126 }
2127
2128 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
2129 ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
2130 }
2131 }
2132
2133 void GLAPIENTRY
2134 _mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
2135 {
2136 GET_CURRENT_CONTEXT(ctx);
2137
2138 /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
2139 * point, but they allow the use of user-generated names.
2140 */
2141 bind_framebuffer(target, framebuffer, _mesa_is_gles(ctx));
2142 }
2143
2144 void GLAPIENTRY
2145 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
2146 {
2147 /* This function should not be in the dispatch table for core profile /
2148 * OpenGL 3.1, so execution should never get here in those cases -- no
2149 * need for an explicit test.
2150 */
2151 bind_framebuffer(target, framebuffer, true);
2152 }
2153
2154 void GLAPIENTRY
2155 _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
2156 {
2157 GLint i;
2158 GET_CURRENT_CONTEXT(ctx);
2159
2160 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2161
2162 for (i = 0; i < n; i++) {
2163 if (framebuffers[i] > 0) {
2164 struct gl_framebuffer *fb;
2165 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
2166 if (fb) {
2167 ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
2168
2169 /* check if deleting currently bound framebuffer object */
2170 if (ctx->Extensions.EXT_framebuffer_blit) {
2171 /* separate draw/read binding points */
2172 if (fb == ctx->DrawBuffer) {
2173 /* bind default */
2174 ASSERT(fb->RefCount >= 2);
2175 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
2176 }
2177 if (fb == ctx->ReadBuffer) {
2178 /* bind default */
2179 ASSERT(fb->RefCount >= 2);
2180 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
2181 }
2182 }
2183 else {
2184 /* only one binding point for read/draw buffers */
2185 if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
2186 /* bind default */
2187 ASSERT(fb->RefCount >= 2);
2188 _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
2189 }
2190 }
2191
2192 /* remove from hash table immediately, to free the ID */
2193 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
2194
2195 if (fb != &DummyFramebuffer) {
2196 /* But the object will not be freed until it's no longer
2197 * bound in any context.
2198 */
2199 _mesa_reference_framebuffer(&fb, NULL);
2200 }
2201 }
2202 }
2203 }
2204 }
2205
2206
2207 void GLAPIENTRY
2208 _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
2209 {
2210 GET_CURRENT_CONTEXT(ctx);
2211 GLuint first;
2212 GLint i;
2213
2214 if (n < 0) {
2215 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
2216 return;
2217 }
2218
2219 if (!framebuffers)
2220 return;
2221
2222 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
2223
2224 for (i = 0; i < n; i++) {
2225 GLuint name = first + i;
2226 framebuffers[i] = name;
2227 /* insert dummy placeholder into hash table */
2228 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
2229 _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
2230 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
2231 }
2232 }
2233
2234
2235
2236 GLenum GLAPIENTRY
2237 _mesa_CheckFramebufferStatus(GLenum target)
2238 {
2239 struct gl_framebuffer *buffer;
2240 GET_CURRENT_CONTEXT(ctx);
2241
2242 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
2243
2244 if (MESA_VERBOSE & VERBOSE_API)
2245 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
2246 _mesa_lookup_enum_by_nr(target));
2247
2248 buffer = get_framebuffer_target(ctx, target);
2249 if (!buffer) {
2250 _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
2251 return 0;
2252 }
2253
2254 if (_mesa_is_winsys_fbo(buffer)) {
2255 /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
2256 if (buffer != &IncompleteFramebuffer) {
2257 return GL_FRAMEBUFFER_COMPLETE_EXT;
2258 } else {
2259 return GL_FRAMEBUFFER_UNDEFINED;
2260 }
2261 }
2262
2263 /* No need to flush here */
2264
2265 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
2266 _mesa_test_framebuffer_completeness(ctx, buffer);
2267 }
2268
2269 return buffer->_Status;
2270 }
2271
2272
2273 /**
2274 * Replicate the src attachment point. Used by framebuffer_texture() when
2275 * the same texture is attached at GL_DEPTH_ATTACHMENT and
2276 * GL_STENCIL_ATTACHMENT.
2277 */
2278 static void
2279 reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
2280 gl_buffer_index dst,
2281 gl_buffer_index src)
2282 {
2283 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
2284 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
2285
2286 assert(src_att->Texture != NULL);
2287 assert(src_att->Renderbuffer != NULL);
2288
2289 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
2290 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
2291 dst_att->Type = src_att->Type;
2292 dst_att->Complete = src_att->Complete;
2293 dst_att->TextureLevel = src_att->TextureLevel;
2294 dst_att->Zoffset = src_att->Zoffset;
2295 }
2296
2297
2298 /**
2299 * Common code called by glFramebufferTexture1D/2D/3DEXT() and
2300 * glFramebufferTextureLayerEXT().
2301 * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll
2302 * get textarget=0 in that case.
2303 */
2304 static void
2305 framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
2306 GLenum attachment, GLenum textarget, GLuint texture,
2307 GLint level, GLint zoffset, GLboolean layered)
2308 {
2309 struct gl_renderbuffer_attachment *att;
2310 struct gl_texture_object *texObj = NULL;
2311 struct gl_framebuffer *fb;
2312 GLenum maxLevelsTarget;
2313
2314 fb = get_framebuffer_target(ctx, target);
2315 if (!fb) {
2316 _mesa_error(ctx, GL_INVALID_ENUM,
2317 "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
2318 return;
2319 }
2320
2321 /* check framebuffer binding */
2322 if (_mesa_is_winsys_fbo(fb)) {
2323 _mesa_error(ctx, GL_INVALID_OPERATION,
2324 "glFramebufferTexture%sEXT", caller);
2325 return;
2326 }
2327
2328 /* The textarget, level, and zoffset parameters are only validated if
2329 * texture is non-zero.
2330 */
2331 if (texture) {
2332 GLboolean err = GL_TRUE;
2333
2334 texObj = _mesa_lookup_texture(ctx, texture);
2335 if (texObj != NULL) {
2336 if (textarget == 0) {
2337 /* If textarget == 0 it means we're being called by
2338 * glFramebufferTextureLayer() and textarget is not used.
2339 * The only legal texture types for that function are 3D and
2340 * 1D/2D arrays textures.
2341 */
2342 err = (texObj->Target != GL_TEXTURE_3D) &&
2343 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
2344 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) &&
2345 (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY) &&
2346 (texObj->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
2347 }
2348 else {
2349 /* Make sure textarget is consistent with the texture's type */
2350 err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
2351 ? !_mesa_is_cube_face(textarget)
2352 : (texObj->Target != textarget);
2353 }
2354 }
2355 else {
2356 /* can't render to a non-existant texture */
2357 _mesa_error(ctx, GL_INVALID_OPERATION,
2358 "glFramebufferTexture%sEXT(non existant texture)",
2359 caller);
2360 return;
2361 }
2362
2363 if (err) {
2364 _mesa_error(ctx, GL_INVALID_OPERATION,
2365 "glFramebufferTexture%sEXT(texture target mismatch)",
2366 caller);
2367 return;
2368 }
2369
2370 if (texObj->Target == GL_TEXTURE_3D) {
2371 const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
2372 if (zoffset < 0 || zoffset >= maxSize) {
2373 _mesa_error(ctx, GL_INVALID_VALUE,
2374 "glFramebufferTexture%sEXT(zoffset)", caller);
2375 return;
2376 }
2377 }
2378 else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
2379 (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) ||
2380 (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
2381 (texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
2382 if (zoffset < 0 ||
2383 zoffset >= (GLint) ctx->Const.MaxArrayTextureLayers) {
2384 _mesa_error(ctx, GL_INVALID_VALUE,
2385 "glFramebufferTexture%sEXT(layer)", caller);
2386 return;
2387 }
2388 }
2389
2390 maxLevelsTarget = textarget ? textarget : texObj->Target;
2391 if ((level < 0) ||
2392 (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
2393 _mesa_error(ctx, GL_INVALID_VALUE,
2394 "glFramebufferTexture%sEXT(level)", caller);
2395 return;
2396 }
2397 }
2398
2399 att = _mesa_get_attachment(ctx, fb, attachment);
2400 if (att == NULL) {
2401 _mesa_error(ctx, GL_INVALID_ENUM,
2402 "glFramebufferTexture%sEXT(attachment)", caller);
2403 return;
2404 }
2405
2406 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2407
2408 _glthread_LOCK_MUTEX(fb->Mutex);
2409 if (texObj) {
2410 if (attachment == GL_DEPTH_ATTACHMENT &&
2411 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
2412 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
2413 _mesa_tex_target_to_face(textarget) ==
2414 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
2415 zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
2416 /* The texture object is already attached to the stencil attachment
2417 * point. Don't create a new renderbuffer; just reuse the stencil
2418 * attachment's. This is required to prevent a GL error in
2419 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
2420 */
2421 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
2422 BUFFER_STENCIL);
2423 } else if (attachment == GL_STENCIL_ATTACHMENT &&
2424 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
2425 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
2426 _mesa_tex_target_to_face(textarget) ==
2427 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
2428 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
2429 /* As above, but with depth and stencil transposed. */
2430 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
2431 BUFFER_DEPTH);
2432 } else {
2433 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
2434 level, zoffset, layered);
2435 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2436 /* Above we created a new renderbuffer and attached it to the
2437 * depth attachment point. Now attach it to the stencil attachment
2438 * point too.
2439 */
2440 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2441 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
2442 BUFFER_DEPTH);
2443 }
2444 }
2445
2446 /* Set the render-to-texture flag. We'll check this flag in
2447 * glTexImage() and friends to determine if we need to revalidate
2448 * any FBOs that might be rendering into this texture.
2449 * This flag never gets cleared since it's non-trivial to determine
2450 * when all FBOs might be done rendering to this texture. That's OK
2451 * though since it's uncommon to render to a texture then repeatedly
2452 * call glTexImage() to change images in the texture.
2453 */
2454 texObj->_RenderToTexture = GL_TRUE;
2455 }
2456 else {
2457 _mesa_remove_attachment(ctx, att);
2458 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2459 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2460 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
2461 }
2462 }
2463
2464 invalidate_framebuffer(fb);
2465
2466 _glthread_UNLOCK_MUTEX(fb->Mutex);
2467 }
2468
2469
2470
2471 void GLAPIENTRY
2472 _mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
2473 GLenum textarget, GLuint texture, GLint level)
2474 {
2475 GET_CURRENT_CONTEXT(ctx);
2476
2477 if (texture != 0) {
2478 GLboolean error;
2479
2480 switch (textarget) {
2481 case GL_TEXTURE_1D:
2482 error = GL_FALSE;
2483 break;
2484 case GL_TEXTURE_1D_ARRAY:
2485 error = !ctx->Extensions.EXT_texture_array;
2486 break;
2487 default:
2488 error = GL_TRUE;
2489 }
2490
2491 if (error) {
2492 _mesa_error(ctx, GL_INVALID_OPERATION,
2493 "glFramebufferTexture1DEXT(textarget=%s)",
2494 _mesa_lookup_enum_by_nr(textarget));
2495 return;
2496 }
2497 }
2498
2499 framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
2500 level, 0, GL_FALSE);
2501 }
2502
2503
2504 void GLAPIENTRY
2505 _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
2506 GLenum textarget, GLuint texture, GLint level)
2507 {
2508 GET_CURRENT_CONTEXT(ctx);
2509
2510 if (texture != 0) {
2511 GLboolean error;
2512
2513 switch (textarget) {
2514 case GL_TEXTURE_2D:
2515 error = GL_FALSE;
2516 break;
2517 case GL_TEXTURE_RECTANGLE:
2518 error = _mesa_is_gles(ctx)
2519 || !ctx->Extensions.NV_texture_rectangle;
2520 break;
2521 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2522 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2523 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2524 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2525 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2526 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2527 error = !ctx->Extensions.ARB_texture_cube_map;
2528 break;
2529 case GL_TEXTURE_2D_ARRAY:
2530 error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2531 || !ctx->Extensions.EXT_texture_array;
2532 break;
2533 case GL_TEXTURE_2D_MULTISAMPLE:
2534 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2535 error = _mesa_is_gles(ctx)
2536 || !ctx->Extensions.ARB_texture_multisample;
2537 break;
2538 default:
2539 error = GL_TRUE;
2540 }
2541
2542 if (error) {
2543 _mesa_error(ctx, GL_INVALID_OPERATION,
2544 "glFramebufferTexture2DEXT(textarget=%s)",
2545 _mesa_lookup_enum_by_nr(textarget));
2546 return;
2547 }
2548 }
2549
2550 framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
2551 level, 0, GL_FALSE);
2552 }
2553
2554
2555 void GLAPIENTRY
2556 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
2557 GLenum textarget, GLuint texture,
2558 GLint level, GLint zoffset)
2559 {
2560 GET_CURRENT_CONTEXT(ctx);
2561
2562 if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
2563 _mesa_error(ctx, GL_INVALID_OPERATION,
2564 "glFramebufferTexture3DEXT(textarget)");
2565 return;
2566 }
2567
2568 framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
2569 level, zoffset, GL_FALSE);
2570 }
2571
2572
2573 void GLAPIENTRY
2574 _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
2575 GLuint texture, GLint level, GLint layer)
2576 {
2577 GET_CURRENT_CONTEXT(ctx);
2578
2579 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2580 level, layer, GL_FALSE);
2581 }
2582
2583
2584 void GLAPIENTRY
2585 _mesa_FramebufferTexture(GLenum target, GLenum attachment,
2586 GLuint texture, GLint level)
2587 {
2588 GET_CURRENT_CONTEXT(ctx);
2589
2590 if (_mesa_has_geometry_shaders(ctx)) {
2591 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2592 level, 0, GL_TRUE);
2593 } else {
2594 _mesa_error(ctx, GL_INVALID_OPERATION,
2595 "unsupported function (glFramebufferTexture) called");
2596 }
2597 }
2598
2599
2600 void GLAPIENTRY
2601 _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
2602 GLenum renderbufferTarget,
2603 GLuint renderbuffer)
2604 {
2605 struct gl_renderbuffer_attachment *att;
2606 struct gl_framebuffer *fb;
2607 struct gl_renderbuffer *rb;
2608 GET_CURRENT_CONTEXT(ctx);
2609
2610 fb = get_framebuffer_target(ctx, target);
2611 if (!fb) {
2612 _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
2613 return;
2614 }
2615
2616 if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
2617 _mesa_error(ctx, GL_INVALID_ENUM,
2618 "glFramebufferRenderbufferEXT(renderbufferTarget)");
2619 return;
2620 }
2621
2622 if (_mesa_is_winsys_fbo(fb)) {
2623 /* Can't attach new renderbuffers to a window system framebuffer */
2624 _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
2625 return;
2626 }
2627
2628 att = _mesa_get_attachment(ctx, fb, attachment);
2629 if (att == NULL) {
2630 _mesa_error(ctx, GL_INVALID_ENUM,
2631 "glFramebufferRenderbufferEXT(invalid attachment %s)",
2632 _mesa_lookup_enum_by_nr(attachment));
2633 return;
2634 }
2635
2636 if (renderbuffer) {
2637 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2638 if (!rb) {
2639 _mesa_error(ctx, GL_INVALID_OPERATION,
2640 "glFramebufferRenderbufferEXT(non-existant"
2641 " renderbuffer %u)", renderbuffer);
2642 return;
2643 }
2644 else if (rb == &DummyRenderbuffer) {
2645 /* This is what NVIDIA does */
2646 _mesa_error(ctx, GL_INVALID_VALUE,
2647 "glFramebufferRenderbufferEXT(renderbuffer %u)",
2648 renderbuffer);
2649 return;
2650 }
2651 }
2652 else {
2653 /* remove renderbuffer attachment */
2654 rb = NULL;
2655 }
2656
2657 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2658 rb && rb->Format != MESA_FORMAT_NONE) {
2659 /* make sure the renderbuffer is a depth/stencil format */
2660 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
2661 if (baseFormat != GL_DEPTH_STENCIL) {
2662 _mesa_error(ctx, GL_INVALID_OPERATION,
2663 "glFramebufferRenderbufferEXT(renderbuffer"
2664 " is not DEPTH_STENCIL format)");
2665 return;
2666 }
2667 }
2668
2669
2670 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2671
2672 assert(ctx->Driver.FramebufferRenderbuffer);
2673 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
2674
2675 /* Some subsequent GL commands may depend on the framebuffer's visual
2676 * after the binding is updated. Update visual info now.
2677 */
2678 _mesa_update_framebuffer_visual(ctx, fb);
2679 }
2680
2681
2682 void GLAPIENTRY
2683 _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
2684 GLenum pname, GLint *params)
2685 {
2686 const struct gl_renderbuffer_attachment *att;
2687 struct gl_framebuffer *buffer;
2688 GLenum err;
2689 GET_CURRENT_CONTEXT(ctx);
2690
2691 /* The error differs in GL and GLES. */
2692 err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
2693
2694 buffer = get_framebuffer_target(ctx, target);
2695 if (!buffer) {
2696 _mesa_error(ctx, GL_INVALID_ENUM,
2697 "glGetFramebufferAttachmentParameterivEXT(target)");
2698 return;
2699 }
2700
2701 if (_mesa_is_winsys_fbo(buffer)) {
2702 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
2703 * says:
2704 *
2705 * "If the framebuffer currently bound to target is zero, then
2706 * INVALID_OPERATION is generated."
2707 *
2708 * The EXT_framebuffer_object spec has the same wording, and the
2709 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
2710 * spec.
2711 */
2712 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2713 && !_mesa_is_gles3(ctx)) {
2714 _mesa_error(ctx, GL_INVALID_OPERATION,
2715 "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
2716 return;
2717 }
2718
2719 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
2720 attachment != GL_DEPTH && attachment != GL_STENCIL) {
2721 _mesa_error(ctx, GL_INVALID_OPERATION,
2722 "glGetFramebufferAttachmentParameteriv(attachment)");
2723 return;
2724 }
2725 /* the default / window-system FBO */
2726 att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
2727 }
2728 else {
2729 /* user-created framebuffer FBO */
2730 att = _mesa_get_attachment(ctx, buffer, attachment);
2731 }
2732
2733 if (att == NULL) {
2734 _mesa_error(ctx, GL_INVALID_ENUM,
2735 "glGetFramebufferAttachmentParameterivEXT(attachment)");
2736 return;
2737 }
2738
2739 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2740 /* the depth and stencil attachments must point to the same buffer */
2741 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
2742 depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
2743 stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
2744 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
2745 _mesa_error(ctx, GL_INVALID_OPERATION,
2746 "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
2747 " attachments differ)");
2748 return;
2749 }
2750 }
2751
2752 /* No need to flush here */
2753
2754 switch (pname) {
2755 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
2756 *params = _mesa_is_winsys_fbo(buffer)
2757 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
2758 return;
2759 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
2760 if (att->Type == GL_RENDERBUFFER_EXT) {
2761 *params = att->Renderbuffer->Name;
2762 }
2763 else if (att->Type == GL_TEXTURE) {
2764 *params = att->Texture->Name;
2765 }
2766 else {
2767 assert(att->Type == GL_NONE);
2768 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
2769 *params = 0;
2770 } else {
2771 goto invalid_pname_enum;
2772 }
2773 }
2774 return;
2775 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
2776 if (att->Type == GL_TEXTURE) {
2777 *params = att->TextureLevel;
2778 }
2779 else if (att->Type == GL_NONE) {
2780 _mesa_error(ctx, err,
2781 "glGetFramebufferAttachmentParameterivEXT(pname)");
2782 }
2783 else {
2784 goto invalid_pname_enum;
2785 }
2786 return;
2787 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
2788 if (att->Type == GL_TEXTURE) {
2789 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
2790 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
2791 }
2792 else {
2793 *params = 0;
2794 }
2795 }
2796 else if (att->Type == GL_NONE) {
2797 _mesa_error(ctx, err,
2798 "glGetFramebufferAttachmentParameterivEXT(pname)");
2799 }
2800 else {
2801 goto invalid_pname_enum;
2802 }
2803 return;
2804 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
2805 if (ctx->API == API_OPENGLES) {
2806 goto invalid_pname_enum;
2807 } else if (att->Type == GL_NONE) {
2808 _mesa_error(ctx, err,
2809 "glGetFramebufferAttachmentParameterivEXT(pname)");
2810 } else if (att->Type == GL_TEXTURE) {
2811 if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
2812 *params = att->Zoffset;
2813 }
2814 else {
2815 *params = 0;
2816 }
2817 }
2818 else {
2819 goto invalid_pname_enum;
2820 }
2821 return;
2822 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2823 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2824 && !_mesa_is_gles3(ctx)) {
2825 goto invalid_pname_enum;
2826 }
2827 else if (att->Type == GL_NONE) {
2828 _mesa_error(ctx, err,
2829 "glGetFramebufferAttachmentParameterivEXT(pname)");
2830 }
2831 else {
2832 if (ctx->Extensions.EXT_framebuffer_sRGB) {
2833 *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
2834 }
2835 else {
2836 /* According to ARB_framebuffer_sRGB, we should return LINEAR
2837 * if the sRGB conversion is unsupported. */
2838 *params = GL_LINEAR;
2839 }
2840 }
2841 return;
2842 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
2843 if ((ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_framebuffer_object)
2844 && ctx->API != API_OPENGL_CORE
2845 && !_mesa_is_gles3(ctx)) {
2846 goto invalid_pname_enum;
2847 }
2848 else if (att->Type == GL_NONE) {
2849 _mesa_error(ctx, err,
2850 "glGetFramebufferAttachmentParameterivEXT(pname)");
2851 }
2852 else {
2853 gl_format format = att->Renderbuffer->Format;
2854
2855 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
2856 * 3.0.1 spec says:
2857 *
2858 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
2859 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
2860 * generate an INVALID_OPERATION error.
2861 */
2862 if (_mesa_is_gles3(ctx) && attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2863 _mesa_error(ctx, GL_INVALID_OPERATION,
2864 "glGetFramebufferAttachmentParameteriv(cannot query "
2865 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
2866 "GL_DEPTH_STENCIL_ATTACHMENT");
2867 return;
2868 }
2869
2870 if (format == MESA_FORMAT_S8) {
2871 /* special cases */
2872 *params = GL_INDEX;
2873 }
2874 else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) {
2875 /* depends on the attachment parameter */
2876 if (attachment == GL_STENCIL_ATTACHMENT) {
2877 *params = GL_INDEX;
2878 }
2879 else {
2880 *params = GL_FLOAT;
2881 }
2882 }
2883 else {
2884 *params = _mesa_get_format_datatype(format);
2885 }
2886 }
2887 return;
2888 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2889 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2890 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2891 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2892 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2893 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2894 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2895 && !_mesa_is_gles3(ctx)) {
2896 goto invalid_pname_enum;
2897 }
2898 else if (att->Type == GL_NONE) {
2899 _mesa_error(ctx, err,
2900 "glGetFramebufferAttachmentParameterivEXT(pname)");
2901 }
2902 else if (att->Texture) {
2903 const struct gl_texture_image *texImage =
2904 _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
2905 att->TextureLevel);
2906 if (texImage) {
2907 *params = get_component_bits(pname, texImage->_BaseFormat,
2908 texImage->TexFormat);
2909 }
2910 else {
2911 *params = 0;
2912 }
2913 }
2914 else if (att->Renderbuffer) {
2915 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
2916 att->Renderbuffer->Format);
2917 }
2918 else {
2919 _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
2920 " invalid FBO attachment structure");
2921 }
2922 return;
2923 default:
2924 goto invalid_pname_enum;
2925 }
2926
2927 return;
2928
2929 invalid_pname_enum:
2930 _mesa_error(ctx, GL_INVALID_ENUM,
2931 "glGetFramebufferAttachmentParameteriv(pname)");
2932 return;
2933 }
2934
2935
2936 void GLAPIENTRY
2937 _mesa_GenerateMipmap(GLenum target)
2938 {
2939 struct gl_texture_image *srcImage;
2940 struct gl_texture_object *texObj;
2941 GLboolean error;
2942
2943 GET_CURRENT_CONTEXT(ctx);
2944
2945 FLUSH_VERTICES(ctx, 0);
2946
2947 switch (target) {
2948 case GL_TEXTURE_1D:
2949 error = _mesa_is_gles(ctx);
2950 break;
2951 case GL_TEXTURE_2D:
2952 error = GL_FALSE;
2953 break;
2954 case GL_TEXTURE_3D:
2955 error = ctx->API == API_OPENGLES;
2956 break;
2957 case GL_TEXTURE_CUBE_MAP:
2958 error = !ctx->Extensions.ARB_texture_cube_map;
2959 break;
2960 case GL_TEXTURE_1D_ARRAY:
2961 error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array;
2962 break;
2963 case GL_TEXTURE_2D_ARRAY:
2964 error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2965 || !ctx->Extensions.EXT_texture_array;
2966 break;
2967 default:
2968 error = GL_TRUE;
2969 }
2970
2971 if (error) {
2972 _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)",
2973 _mesa_lookup_enum_by_nr(target));
2974 return;
2975 }
2976
2977 texObj = _mesa_get_current_tex_object(ctx, target);
2978
2979 if (texObj->BaseLevel >= texObj->MaxLevel) {
2980 /* nothing to do */
2981 return;
2982 }
2983
2984 if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
2985 !_mesa_cube_complete(texObj)) {
2986 _mesa_error(ctx, GL_INVALID_OPERATION,
2987 "glGenerateMipmap(incomplete cube map)");
2988 return;
2989 }
2990
2991 _mesa_lock_texture(ctx, texObj);
2992
2993 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
2994 if (!srcImage) {
2995 _mesa_unlock_texture(ctx, texObj);
2996 _mesa_error(ctx, GL_INVALID_OPERATION,
2997 "glGenerateMipmap(zero size base image)");
2998 return;
2999 }
3000
3001 if (_mesa_is_enum_format_integer(srcImage->InternalFormat) ||
3002 _mesa_is_depthstencil_format(srcImage->InternalFormat) ||
3003 _mesa_is_stencil_format(srcImage->InternalFormat)) {
3004 _mesa_unlock_texture(ctx, texObj);
3005 _mesa_error(ctx, GL_INVALID_OPERATION,
3006 "glGenerateMipmap(invalid internal format)");
3007 return;
3008 }
3009
3010 if (target == GL_TEXTURE_CUBE_MAP) {
3011 GLuint face;
3012 for (face = 0; face < 6; face++)
3013 ctx->Driver.GenerateMipmap(ctx,
3014 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
3015 texObj);
3016 }
3017 else {
3018 ctx->Driver.GenerateMipmap(ctx, target, texObj);
3019 }
3020 _mesa_unlock_texture(ctx, texObj);
3021 }
3022
3023
3024 static const struct gl_renderbuffer_attachment *
3025 find_attachment(const struct gl_framebuffer *fb,
3026 const struct gl_renderbuffer *rb)
3027 {
3028 GLuint i;
3029 for (i = 0; i < Elements(fb->Attachment); i++) {
3030 if (fb->Attachment[i].Renderbuffer == rb)
3031 return &fb->Attachment[i];
3032 }
3033 return NULL;
3034 }
3035
3036
3037 /**
3038 * Helper function for checking if the datatypes of color buffers are
3039 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
3040 *
3041 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
3042 * and any of the following conditions hold:
3043 * - The read buffer contains fixed-point or floating-point values and any
3044 * draw buffer contains neither fixed-point nor floating-point values.
3045 * - The read buffer contains unsigned integer values and any draw buffer
3046 * does not contain unsigned integer values.
3047 * - The read buffer contains signed integer values and any draw buffer
3048 * does not contain signed integer values."
3049 */
3050 static GLboolean
3051 compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat)
3052 {
3053 GLenum srcType = _mesa_get_format_datatype(srcFormat);
3054 GLenum dstType = _mesa_get_format_datatype(dstFormat);
3055
3056 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
3057 assert(srcType == GL_UNSIGNED_NORMALIZED ||
3058 srcType == GL_SIGNED_NORMALIZED ||
3059 srcType == GL_FLOAT);
3060 /* Boil any of those types down to GL_FLOAT */
3061 srcType = GL_FLOAT;
3062 }
3063
3064 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
3065 assert(dstType == GL_UNSIGNED_NORMALIZED ||
3066 dstType == GL_SIGNED_NORMALIZED ||
3067 dstType == GL_FLOAT);
3068 /* Boil any of those types down to GL_FLOAT */
3069 dstType = GL_FLOAT;
3070 }
3071
3072 return srcType == dstType;
3073 }
3074
3075
3076 static GLboolean
3077 compatible_resolve_formats(const struct gl_renderbuffer *readRb,
3078 const struct gl_renderbuffer *drawRb)
3079 {
3080 GLenum readFormat, drawFormat;
3081
3082 /* The simple case where we know the backing Mesa formats are the same.
3083 */
3084 if (_mesa_get_srgb_format_linear(readRb->Format) ==
3085 _mesa_get_srgb_format_linear(drawRb->Format)) {
3086 return GL_TRUE;
3087 }
3088
3089 /* The Mesa formats are different, so we must check whether the internal
3090 * formats are compatible.
3091 *
3092 * Under some circumstances, the user may request e.g. two GL_RGBA8
3093 * textures and get two entirely different Mesa formats like RGBA8888 and
3094 * ARGB8888. Drivers behaving like that should be able to cope with
3095 * non-matching formats by themselves, because it's not the user's fault.
3096 *
3097 * Blits between linear and sRGB formats are also allowed.
3098 */
3099 readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
3100 drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
3101 readFormat = _mesa_get_linear_internalformat(readFormat);
3102 drawFormat = _mesa_get_linear_internalformat(drawFormat);
3103
3104 if (readFormat == drawFormat) {
3105 return GL_TRUE;
3106 }
3107
3108 return GL_FALSE;
3109 }
3110
3111 static GLboolean
3112 is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
3113 {
3114 switch (filter) {
3115 case GL_NEAREST:
3116 case GL_LINEAR:
3117 return true;
3118 case GL_SCALED_RESOLVE_FASTEST_EXT:
3119 case GL_SCALED_RESOLVE_NICEST_EXT:
3120 return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
3121 default:
3122 return false;
3123 }
3124 }
3125
3126 /**
3127 * Blit rectangular region, optionally from one framebuffer to another.
3128 *
3129 * Note, if the src buffer is multisampled and the dest is not, this is
3130 * when the samples must be resolved to a single color.
3131 */
3132 void GLAPIENTRY
3133 _mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3134 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3135 GLbitfield mask, GLenum filter)
3136 {
3137 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
3138 GL_DEPTH_BUFFER_BIT |
3139 GL_STENCIL_BUFFER_BIT);
3140 const struct gl_framebuffer *readFb, *drawFb;
3141 GET_CURRENT_CONTEXT(ctx);
3142
3143 FLUSH_VERTICES(ctx, 0);
3144
3145 if (MESA_VERBOSE & VERBOSE_API)
3146 _mesa_debug(ctx,
3147 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
3148 srcX0, srcY0, srcX1, srcY1,
3149 dstX0, dstY0, dstX1, dstY1,
3150 mask, _mesa_lookup_enum_by_nr(filter));
3151
3152 if (ctx->NewState) {
3153 _mesa_update_state(ctx);
3154 }
3155
3156 readFb = ctx->ReadBuffer;
3157 drawFb = ctx->DrawBuffer;
3158
3159 if (!readFb || !drawFb) {
3160 /* This will normally never happen but someday we may want to
3161 * support MakeCurrent() with no drawables.
3162 */
3163 return;
3164 }
3165
3166 /* check for complete framebuffers */
3167 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
3168 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
3169 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
3170 "glBlitFramebufferEXT(incomplete draw/read buffers)");
3171 return;
3172 }
3173
3174 if (!is_valid_blit_filter(ctx, filter)) {
3175 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
3176 _mesa_lookup_enum_by_nr(filter));
3177 return;
3178 }
3179
3180 if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
3181 filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
3182 (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
3183 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)",
3184 _mesa_lookup_enum_by_nr(filter));
3185 return;
3186 }
3187
3188 if (mask & ~legalMaskBits) {
3189 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
3190 return;
3191 }
3192
3193 /* depth/stencil must be blitted with nearest filtering */
3194 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
3195 && filter != GL_NEAREST) {
3196 _mesa_error(ctx, GL_INVALID_OPERATION,
3197 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
3198 return;
3199 }
3200
3201 /* get color read/draw renderbuffers */
3202 if (mask & GL_COLOR_BUFFER_BIT) {
3203 const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
3204 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
3205 const struct gl_renderbuffer *colorDrawRb = NULL;
3206 GLuint i;
3207
3208 /* From the EXT_framebuffer_object spec:
3209 *
3210 * "If a buffer is specified in <mask> and does not exist in both
3211 * the read and draw framebuffers, the corresponding bit is silently
3212 * ignored."
3213 */
3214 if (!colorReadRb || numColorDrawBuffers == 0) {
3215 mask &= ~GL_COLOR_BUFFER_BIT;
3216 }
3217 else {
3218 for (i = 0; i < numColorDrawBuffers; i++) {
3219 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
3220 if (!colorDrawRb)
3221 continue;
3222
3223 /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
3224 * ES 3.0.1 spec says:
3225 *
3226 * "If the source and destination buffers are identical, an
3227 * INVALID_OPERATION error is generated. Different mipmap
3228 * levels of a texture, different layers of a three-
3229 * dimensional texture or two-dimensional array texture, and
3230 * different faces of a cube map texture do not constitute
3231 * identical buffers."
3232 */
3233 if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
3234 _mesa_error(ctx, GL_INVALID_OPERATION,
3235 "glBlitFramebuffer(source and destination color "
3236 "buffer cannot be the same)");
3237 return;
3238 }
3239
3240 if (!compatible_color_datatypes(colorReadRb->Format,
3241 colorDrawRb->Format)) {
3242 _mesa_error(ctx, GL_INVALID_OPERATION,
3243 "glBlitFramebufferEXT(color buffer datatypes mismatch)");
3244 return;
3245 }
3246 /* extra checks for multisample copies... */
3247 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
3248 /* color formats must match */
3249 if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
3250 _mesa_error(ctx, GL_INVALID_OPERATION,
3251 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
3252 return;
3253 }
3254 }
3255 }
3256 if (filter != GL_NEAREST) {
3257 /* From EXT_framebuffer_multisample_blit_scaled specification:
3258 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
3259 * if filter is not NEAREST and read buffer contains integer data."
3260 */
3261 GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
3262 if (type == GL_INT || type == GL_UNSIGNED_INT) {
3263 _mesa_error(ctx, GL_INVALID_OPERATION,
3264 "glBlitFramebufferEXT(integer color type)");
3265 return;
3266 }
3267 }
3268 }
3269 }
3270
3271 if (mask & GL_STENCIL_BUFFER_BIT) {
3272 struct gl_renderbuffer *readRb =
3273 readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
3274 struct gl_renderbuffer *drawRb =
3275 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
3276
3277 /* From the EXT_framebuffer_object spec:
3278 *
3279 * "If a buffer is specified in <mask> and does not exist in both
3280 * the read and draw framebuffers, the corresponding bit is silently
3281 * ignored."
3282 */
3283 if ((readRb == NULL) || (drawRb == NULL)) {
3284 mask &= ~GL_STENCIL_BUFFER_BIT;
3285 }
3286 else {
3287 int read_z_bits, draw_z_bits;
3288
3289 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
3290 _mesa_error(ctx, GL_INVALID_OPERATION,
3291 "glBlitFramebuffer(source and destination stencil "
3292 "buffer cannot be the same)");
3293 return;
3294 }
3295
3296 if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
3297 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
3298 /* There is no need to check the stencil datatype here, because
3299 * there is only one: GL_UNSIGNED_INT.
3300 */
3301 _mesa_error(ctx, GL_INVALID_OPERATION,
3302 "glBlitFramebuffer(stencil attachment format mismatch)");
3303 return;
3304 }
3305
3306 read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
3307 draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
3308
3309 /* If both buffers also have depth data, the depth formats must match
3310 * as well. If one doesn't have depth, it's not blitted, so we should
3311 * ignore the depth format check.
3312 */
3313 if (read_z_bits > 0 && draw_z_bits > 0 &&
3314 (read_z_bits != draw_z_bits ||
3315 _mesa_get_format_datatype(readRb->Format) !=
3316 _mesa_get_format_datatype(drawRb->Format))) {
3317
3318 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3319 "(stencil attachment depth format mismatch)");
3320 return;
3321 }
3322 }
3323 }
3324
3325 if (mask & GL_DEPTH_BUFFER_BIT) {
3326 struct gl_renderbuffer *readRb =
3327 readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
3328 struct gl_renderbuffer *drawRb =
3329 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
3330
3331 /* From the EXT_framebuffer_object spec:
3332 *
3333 * "If a buffer is specified in <mask> and does not exist in both
3334 * the read and draw framebuffers, the corresponding bit is silently
3335 * ignored."
3336 */
3337 if ((readRb == NULL) || (drawRb == NULL)) {
3338 mask &= ~GL_DEPTH_BUFFER_BIT;
3339 }
3340 else {
3341 int read_s_bit, draw_s_bit;
3342
3343 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
3344 _mesa_error(ctx, GL_INVALID_OPERATION,
3345 "glBlitFramebuffer(source and destination depth "
3346 "buffer cannot be the same)");
3347 return;
3348 }
3349
3350 if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
3351 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
3352 (_mesa_get_format_datatype(readRb->Format) !=
3353 _mesa_get_format_datatype(drawRb->Format))) {
3354 _mesa_error(ctx, GL_INVALID_OPERATION,
3355 "glBlitFramebuffer(depth attachment format mismatch)");
3356 return;
3357 }
3358
3359 read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
3360 draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
3361
3362 /* If both buffers also have stencil data, the stencil formats must
3363 * match as well. If one doesn't have stencil, it's not blitted, so
3364 * we should ignore the stencil format check.
3365 */
3366 if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
3367 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3368 "(depth attachment stencil bits mismatch)");
3369 return;
3370 }
3371 }
3372 }
3373
3374
3375 if (_mesa_is_gles3(ctx)) {
3376 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
3377 * 3.0.1 spec says:
3378 *
3379 * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
3380 * an INVALID_OPERATION error is generated."
3381 */
3382 if (drawFb->Visual.samples > 0) {
3383 _mesa_error(ctx, GL_INVALID_OPERATION,
3384 "glBlitFramebuffer(destination samples must be 0)");
3385 return;
3386 }
3387
3388 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
3389 * 3.0.1 spec says:
3390 *
3391 * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
3392 * no copy is performed and an INVALID_OPERATION error is generated
3393 * if the formats of the read and draw framebuffers are not
3394 * identical or if the source and destination rectangles are not
3395 * defined with the same (X0, Y0) and (X1, Y1) bounds."
3396 *
3397 * The format check was made above because desktop OpenGL has the same
3398 * requirement.
3399 */
3400 if (readFb->Visual.samples > 0
3401 && (srcX0 != dstX0 || srcY0 != dstY0
3402 || srcX1 != dstX1 || srcY1 != dstY1)) {
3403 _mesa_error(ctx, GL_INVALID_OPERATION,
3404 "glBlitFramebuffer(bad src/dst multisample region)");
3405 return;
3406 }
3407 } else {
3408 if (readFb->Visual.samples > 0 &&
3409 drawFb->Visual.samples > 0 &&
3410 readFb->Visual.samples != drawFb->Visual.samples) {
3411 _mesa_error(ctx, GL_INVALID_OPERATION,
3412 "glBlitFramebufferEXT(mismatched samples)");
3413 return;
3414 }
3415
3416 /* extra checks for multisample copies... */
3417 if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
3418 (filter == GL_NEAREST || filter == GL_LINEAR)) {
3419 /* src and dest region sizes must be the same */
3420 if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
3421 abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
3422 _mesa_error(ctx, GL_INVALID_OPERATION,
3423 "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
3424 return;
3425 }
3426 }
3427 }
3428
3429 if (!ctx->Extensions.EXT_framebuffer_blit) {
3430 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
3431 return;
3432 }
3433
3434 /* Debug code */
3435 if (DEBUG_BLIT) {
3436 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
3437 const struct gl_renderbuffer *colorDrawRb = NULL;
3438 GLuint i = 0;
3439
3440 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
3441 " 0x%x, 0x%x)\n",
3442 srcX0, srcY0, srcX1, srcY1,
3443 dstX0, dstY0, dstX1, dstY1,
3444 mask, filter);
3445 if (colorReadRb) {
3446 const struct gl_renderbuffer_attachment *att;
3447
3448 att = find_attachment(readFb, colorReadRb);
3449 printf(" Src FBO %u RB %u (%dx%d) ",
3450 readFb->Name, colorReadRb->Name,
3451 colorReadRb->Width, colorReadRb->Height);
3452 if (att && att->Texture) {
3453 printf("Tex %u tgt 0x%x level %u face %u",
3454 att->Texture->Name,
3455 att->Texture->Target,
3456 att->TextureLevel,
3457 att->CubeMapFace);
3458 }
3459 printf("\n");
3460
3461 /* Print all active color render buffers */
3462 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
3463 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
3464 if (!colorDrawRb)
3465 continue;
3466
3467 att = find_attachment(drawFb, colorDrawRb);
3468 printf(" Dst FBO %u RB %u (%dx%d) ",
3469 drawFb->Name, colorDrawRb->Name,
3470 colorDrawRb->Width, colorDrawRb->Height);
3471 if (att && att->Texture) {
3472 printf("Tex %u tgt 0x%x level %u face %u",
3473 att->Texture->Name,
3474 att->Texture->Target,
3475 att->TextureLevel,
3476 att->CubeMapFace);
3477 }
3478 printf("\n");
3479 }
3480 }
3481 }
3482
3483 if (!mask ||
3484 (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
3485 (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
3486 return;
3487 }
3488
3489 ASSERT(ctx->Driver.BlitFramebuffer);
3490 ctx->Driver.BlitFramebuffer(ctx,
3491 srcX0, srcY0, srcX1, srcY1,
3492 dstX0, dstY0, dstX1, dstY1,
3493 mask, filter);
3494 }
3495
3496
3497 static void
3498 invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
3499 const GLenum *attachments, GLint x, GLint y,
3500 GLsizei width, GLsizei height, const char *name)
3501 {
3502 int i;
3503 struct gl_framebuffer *fb;
3504 GET_CURRENT_CONTEXT(ctx);
3505
3506 fb = get_framebuffer_target(ctx, target);
3507 if (!fb) {
3508 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
3509 return;
3510 }
3511
3512 if (numAttachments < 0) {
3513 _mesa_error(ctx, GL_INVALID_VALUE,
3514 "%s(numAttachments < 0)", name);
3515 return;
3516 }
3517
3518 /* The GL_ARB_invalidate_subdata spec says:
3519 *
3520 * "If an attachment is specified that does not exist in the
3521 * framebuffer bound to <target>, it is ignored."
3522 *
3523 * It also says:
3524 *
3525 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
3526 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
3527 * INVALID_OPERATION is generated."
3528 *
3529 * No mention is made of GL_AUXi being out of range. Therefore, we allow
3530 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
3531 * set of retrictions).
3532 */
3533 for (i = 0; i < numAttachments; i++) {
3534 if (_mesa_is_winsys_fbo(fb)) {
3535 switch (attachments[i]) {
3536 case GL_ACCUM:
3537 case GL_AUX0:
3538 case GL_AUX1:
3539 case GL_AUX2:
3540 case GL_AUX3:
3541 /* Accumulation buffers and auxilary buffers were removed in
3542 * OpenGL 3.1, and they never existed in OpenGL ES.
3543 */
3544 if (ctx->API != API_OPENGL_COMPAT)
3545 goto invalid_enum;
3546 break;
3547 case GL_COLOR:
3548 case GL_DEPTH:
3549 case GL_STENCIL:
3550 break;
3551 case GL_BACK_LEFT:
3552 case GL_BACK_RIGHT:
3553 case GL_FRONT_LEFT:
3554 case GL_FRONT_RIGHT:
3555 if (!_mesa_is_desktop_gl(ctx))
3556 goto invalid_enum;
3557 break;
3558 default:
3559 goto invalid_enum;
3560 }
3561 } else {
3562 switch (attachments[i]) {
3563 case GL_DEPTH_ATTACHMENT:
3564 case GL_STENCIL_ATTACHMENT:
3565 break;
3566 case GL_COLOR_ATTACHMENT0:
3567 case GL_COLOR_ATTACHMENT1:
3568 case GL_COLOR_ATTACHMENT2:
3569 case GL_COLOR_ATTACHMENT3:
3570 case GL_COLOR_ATTACHMENT4:
3571 case GL_COLOR_ATTACHMENT5:
3572 case GL_COLOR_ATTACHMENT6:
3573 case GL_COLOR_ATTACHMENT7:
3574 case GL_COLOR_ATTACHMENT8:
3575 case GL_COLOR_ATTACHMENT9:
3576 case GL_COLOR_ATTACHMENT10:
3577 case GL_COLOR_ATTACHMENT11:
3578 case GL_COLOR_ATTACHMENT12:
3579 case GL_COLOR_ATTACHMENT13:
3580 case GL_COLOR_ATTACHMENT14:
3581 case GL_COLOR_ATTACHMENT15: {
3582 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
3583 if (k >= ctx->Const.MaxColorAttachments) {
3584 _mesa_error(ctx, GL_INVALID_OPERATION,
3585 "%s(attachment >= max. color attachments)", name);
3586 return;
3587 }
3588 }
3589 default:
3590 goto invalid_enum;
3591 }
3592 }
3593 }
3594
3595 /* We don't actually do anything for this yet. Just return after
3596 * validating the parameters and generating the required errors.
3597 */
3598 return;
3599
3600 invalid_enum:
3601 _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
3602 return;
3603 }
3604
3605 void GLAPIENTRY
3606 _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
3607 const GLenum *attachments, GLint x, GLint y,
3608 GLsizei width, GLsizei height)
3609 {
3610 invalidate_framebuffer_storage(target, numAttachments, attachments,
3611 x, y, width, height,
3612 "glInvalidateSubFramebuffer");
3613 }
3614
3615 void GLAPIENTRY
3616 _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
3617 const GLenum *attachments)
3618 {
3619 /* The GL_ARB_invalidate_subdata spec says:
3620 *
3621 * "The command
3622 *
3623 * void InvalidateFramebuffer(enum target,
3624 * sizei numAttachments,
3625 * const enum *attachments);
3626 *
3627 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
3628 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
3629 * <MAX_VIEWPORT_DIMS[1]> respectively."
3630 */
3631 invalidate_framebuffer_storage(target, numAttachments, attachments,
3632 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
3633 "glInvalidateFramebuffer");
3634 }
3635
3636 void GLAPIENTRY
3637 _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
3638 const GLenum *attachments)
3639 {
3640 struct gl_framebuffer *fb;
3641 GLint i;
3642
3643 GET_CURRENT_CONTEXT(ctx);
3644
3645 fb = get_framebuffer_target(ctx, target);
3646 if (!fb) {
3647 _mesa_error(ctx, GL_INVALID_ENUM,
3648 "glDiscardFramebufferEXT(target %s)",
3649 _mesa_lookup_enum_by_nr(target));
3650 return;
3651 }
3652
3653 if (numAttachments < 0) {
3654 _mesa_error(ctx, GL_INVALID_VALUE,
3655 "glDiscardFramebufferEXT(numAttachments < 0)");
3656 return;
3657 }
3658
3659 for (i = 0; i < numAttachments; i++) {
3660 switch (attachments[i]) {
3661 case GL_COLOR:
3662 case GL_DEPTH:
3663 case GL_STENCIL:
3664 if (_mesa_is_user_fbo(fb))
3665 goto invalid_enum;
3666 break;
3667 case GL_COLOR_ATTACHMENT0:
3668 case GL_DEPTH_ATTACHMENT:
3669 case GL_STENCIL_ATTACHMENT:
3670 if (_mesa_is_winsys_fbo(fb))
3671 goto invalid_enum;
3672 break;
3673 default:
3674 goto invalid_enum;
3675 }
3676 }
3677
3678 if (ctx->Driver.DiscardFramebuffer)
3679 ctx->Driver.DiscardFramebuffer(ctx, target, numAttachments, attachments);
3680
3681 return;
3682
3683 invalid_enum:
3684 _mesa_error(ctx, GL_INVALID_ENUM,
3685 "glDiscardFramebufferEXT(attachment %s)",
3686 _mesa_lookup_enum_by_nr(attachments[i]));
3687 }