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