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