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