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