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