mesa: use _mesa_is_user_fbo() and _mesa_is_winsys_fbo() functions
[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->Extensions.EXT_texture_integer ? GL_RGBA : 0;
1229
1230 case GL_RGB8UI_EXT:
1231 case GL_RGB16UI_EXT:
1232 case GL_RGB32UI_EXT:
1233 case GL_RGB8I_EXT:
1234 case GL_RGB16I_EXT:
1235 case GL_RGB32I_EXT:
1236 return ctx->Extensions.EXT_texture_integer ? GL_RGB : 0;
1237
1238 case GL_R8UI:
1239 case GL_R8I:
1240 case GL_R16UI:
1241 case GL_R16I:
1242 case GL_R32UI:
1243 case GL_R32I:
1244 return ctx->Extensions.ARB_texture_rg &&
1245 ctx->Extensions.EXT_texture_integer ? GL_RED : 0;
1246
1247 case GL_RG8UI:
1248 case GL_RG8I:
1249 case GL_RG16UI:
1250 case GL_RG16I:
1251 case GL_RG32UI:
1252 case GL_RG32I:
1253 return ctx->Extensions.ARB_texture_rg &&
1254 ctx->Extensions.EXT_texture_integer ? GL_RG : 0;
1255
1256 case GL_INTENSITY8I_EXT:
1257 case GL_INTENSITY8UI_EXT:
1258 case GL_INTENSITY16I_EXT:
1259 case GL_INTENSITY16UI_EXT:
1260 case GL_INTENSITY32I_EXT:
1261 case GL_INTENSITY32UI_EXT:
1262 return ctx->Extensions.EXT_texture_integer &&
1263 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1264
1265 case GL_LUMINANCE8I_EXT:
1266 case GL_LUMINANCE8UI_EXT:
1267 case GL_LUMINANCE16I_EXT:
1268 case GL_LUMINANCE16UI_EXT:
1269 case GL_LUMINANCE32I_EXT:
1270 case GL_LUMINANCE32UI_EXT:
1271 return ctx->Extensions.EXT_texture_integer &&
1272 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1273
1274 case GL_LUMINANCE_ALPHA8I_EXT:
1275 case GL_LUMINANCE_ALPHA8UI_EXT:
1276 case GL_LUMINANCE_ALPHA16I_EXT:
1277 case GL_LUMINANCE_ALPHA16UI_EXT:
1278 case GL_LUMINANCE_ALPHA32I_EXT:
1279 case GL_LUMINANCE_ALPHA32UI_EXT:
1280 return ctx->Extensions.EXT_texture_integer &&
1281 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1282
1283 case GL_RGB10_A2UI:
1284 return ctx->Extensions.ARB_texture_rgb10_a2ui ? GL_RGBA : 0;
1285 default:
1286 return 0;
1287 }
1288 }
1289
1290
1291 /**
1292 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
1293 */
1294 static void
1295 invalidate_rb(GLuint key, void *data, void *userData)
1296 {
1297 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
1298 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
1299
1300 /* If this is a user-created FBO */
1301 if (_mesa_is_user_fbo(fb)) {
1302 GLuint i;
1303 for (i = 0; i < BUFFER_COUNT; i++) {
1304 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1305 if (att->Type == GL_RENDERBUFFER &&
1306 att->Renderbuffer == rb) {
1307 /* Mark fb status as indeterminate to force re-validation */
1308 fb->_Status = 0;
1309 return;
1310 }
1311 }
1312 }
1313 }
1314
1315
1316 /** sentinal value, see below */
1317 #define NO_SAMPLES 1000
1318
1319
1320 /**
1321 * Helper function used by _mesa_RenderbufferStorageEXT() and
1322 * _mesa_RenderbufferStorageMultisample().
1323 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT().
1324 */
1325 static void
1326 renderbuffer_storage(GLenum target, GLenum internalFormat,
1327 GLsizei width, GLsizei height, GLsizei samples)
1328 {
1329 const char *func = samples == NO_SAMPLES ?
1330 "glRenderbufferStorage" : "RenderbufferStorageMultisample";
1331 struct gl_renderbuffer *rb;
1332 GLenum baseFormat;
1333 GET_CURRENT_CONTEXT(ctx);
1334
1335 ASSERT_OUTSIDE_BEGIN_END(ctx);
1336
1337 if (target != GL_RENDERBUFFER_EXT) {
1338 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
1339 return;
1340 }
1341
1342 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
1343 if (baseFormat == 0) {
1344 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
1345 return;
1346 }
1347
1348 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1349 _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
1350 return;
1351 }
1352
1353 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1354 _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
1355 return;
1356 }
1357
1358 if (samples == NO_SAMPLES) {
1359 /* NumSamples == 0 indicates non-multisampling */
1360 samples = 0;
1361 }
1362 else if (samples > (GLsizei) ctx->Const.MaxSamples) {
1363 /* note: driver may choose to use more samples than what's requested */
1364 _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
1365 return;
1366 }
1367
1368 rb = ctx->CurrentRenderbuffer;
1369 if (!rb) {
1370 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1371 return;
1372 }
1373
1374 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1375
1376 if (rb->InternalFormat == internalFormat &&
1377 rb->Width == (GLuint) width &&
1378 rb->Height == (GLuint) height) {
1379 /* no change in allocation needed */
1380 return;
1381 }
1382
1383 /* These MUST get set by the AllocStorage func */
1384 rb->Format = MESA_FORMAT_NONE;
1385 rb->NumSamples = samples;
1386
1387 /* Now allocate the storage */
1388 ASSERT(rb->AllocStorage);
1389 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
1390 /* No error - check/set fields now */
1391 assert(rb->Format != MESA_FORMAT_NONE);
1392 assert(rb->Width == (GLuint) width);
1393 assert(rb->Height == (GLuint) height);
1394 rb->InternalFormat = internalFormat;
1395 rb->_BaseFormat = baseFormat;
1396 assert(rb->_BaseFormat != 0);
1397 }
1398 else {
1399 /* Probably ran out of memory - clear the fields */
1400 rb->Width = 0;
1401 rb->Height = 0;
1402 rb->Format = MESA_FORMAT_NONE;
1403 rb->InternalFormat = GL_NONE;
1404 rb->_BaseFormat = GL_NONE;
1405 rb->NumSamples = 0;
1406 }
1407
1408 /* Invalidate the framebuffers the renderbuffer is attached in. */
1409 if (rb->AttachedAnytime) {
1410 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
1411 }
1412 }
1413
1414
1415 #if FEATURE_OES_EGL_image
1416 void GLAPIENTRY
1417 _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
1418 {
1419 struct gl_renderbuffer *rb;
1420 GET_CURRENT_CONTEXT(ctx);
1421 ASSERT_OUTSIDE_BEGIN_END(ctx);
1422
1423 if (!ctx->Extensions.OES_EGL_image) {
1424 _mesa_error(ctx, GL_INVALID_OPERATION,
1425 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
1426 return;
1427 }
1428
1429 if (target != GL_RENDERBUFFER) {
1430 _mesa_error(ctx, GL_INVALID_ENUM,
1431 "EGLImageTargetRenderbufferStorageOES");
1432 return;
1433 }
1434
1435 rb = ctx->CurrentRenderbuffer;
1436 if (!rb) {
1437 _mesa_error(ctx, GL_INVALID_OPERATION,
1438 "EGLImageTargetRenderbufferStorageOES");
1439 return;
1440 }
1441
1442 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1443
1444 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
1445 }
1446 #endif
1447
1448
1449 /**
1450 * Helper function for _mesa_GetRenderbufferParameterivEXT() and
1451 * _mesa_GetFramebufferAttachmentParameterivEXT()
1452 * We have to be careful to respect the base format. For example, if a
1453 * renderbuffer/texture was created with internalFormat=GL_RGB but the
1454 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
1455 * we need to return zero.
1456 */
1457 static GLint
1458 get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
1459 {
1460 if (_mesa_base_format_has_channel(baseFormat, pname))
1461 return _mesa_get_format_bits(format, pname);
1462 else
1463 return 0;
1464 }
1465
1466
1467
1468 void GLAPIENTRY
1469 _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1470 GLsizei width, GLsizei height)
1471 {
1472 /* GL_ARB_fbo says calling this function is equivalent to calling
1473 * glRenderbufferStorageMultisample() with samples=0. We pass in
1474 * a token value here just for error reporting purposes.
1475 */
1476 renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
1477 }
1478
1479
1480 void GLAPIENTRY
1481 _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
1482 GLenum internalFormat,
1483 GLsizei width, GLsizei height)
1484 {
1485 renderbuffer_storage(target, internalFormat, width, height, samples);
1486 }
1487
1488
1489 /**
1490 * OpenGL ES version of glRenderBufferStorage.
1491 */
1492 void GLAPIENTRY
1493 _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1494 GLsizei width, GLsizei height)
1495 {
1496 switch (internalFormat) {
1497 case GL_RGB565:
1498 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
1499 /* choose a closest format */
1500 internalFormat = GL_RGB5;
1501 break;
1502 default:
1503 break;
1504 }
1505
1506 renderbuffer_storage(target, internalFormat, width, height, 0);
1507 }
1508
1509
1510 void GLAPIENTRY
1511 _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
1512 {
1513 struct gl_renderbuffer *rb;
1514 GET_CURRENT_CONTEXT(ctx);
1515
1516 ASSERT_OUTSIDE_BEGIN_END(ctx);
1517
1518 if (target != GL_RENDERBUFFER_EXT) {
1519 _mesa_error(ctx, GL_INVALID_ENUM,
1520 "glGetRenderbufferParameterivEXT(target)");
1521 return;
1522 }
1523
1524 rb = ctx->CurrentRenderbuffer;
1525 if (!rb) {
1526 _mesa_error(ctx, GL_INVALID_OPERATION,
1527 "glGetRenderbufferParameterivEXT");
1528 return;
1529 }
1530
1531 /* No need to flush here since we're just quering state which is
1532 * not effected by rendering.
1533 */
1534
1535 switch (pname) {
1536 case GL_RENDERBUFFER_WIDTH_EXT:
1537 *params = rb->Width;
1538 return;
1539 case GL_RENDERBUFFER_HEIGHT_EXT:
1540 *params = rb->Height;
1541 return;
1542 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
1543 *params = rb->InternalFormat;
1544 return;
1545 case GL_RENDERBUFFER_RED_SIZE_EXT:
1546 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
1547 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
1548 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
1549 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
1550 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
1551 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
1552 break;
1553 case GL_RENDERBUFFER_SAMPLES:
1554 if (ctx->Extensions.ARB_framebuffer_object) {
1555 *params = rb->NumSamples;
1556 break;
1557 }
1558 /* fallthrough */
1559 default:
1560 _mesa_error(ctx, GL_INVALID_ENUM,
1561 "glGetRenderbufferParameterivEXT(target)");
1562 return;
1563 }
1564 }
1565
1566
1567 GLboolean GLAPIENTRY
1568 _mesa_IsFramebufferEXT(GLuint framebuffer)
1569 {
1570 GET_CURRENT_CONTEXT(ctx);
1571 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1572 if (framebuffer) {
1573 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
1574 if (rb != NULL && rb != &DummyFramebuffer)
1575 return GL_TRUE;
1576 }
1577 return GL_FALSE;
1578 }
1579
1580
1581 /**
1582 * Check if any of the attachments of the given framebuffer are textures
1583 * (render to texture). Call ctx->Driver.RenderTexture() for such
1584 * attachments.
1585 */
1586 static void
1587 check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1588 {
1589 GLuint i;
1590 ASSERT(ctx->Driver.RenderTexture);
1591
1592 if (_mesa_is_winsys_fbo(fb))
1593 return; /* can't render to texture with winsys framebuffers */
1594
1595 for (i = 0; i < BUFFER_COUNT; i++) {
1596 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1597 if (att->Texture && _mesa_get_attachment_teximage(att)) {
1598 ctx->Driver.RenderTexture(ctx, fb, att);
1599 }
1600 }
1601 }
1602
1603
1604 /**
1605 * Examine all the framebuffer's attachments to see if any are textures.
1606 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
1607 * notify the device driver that the texture image may have changed.
1608 */
1609 static void
1610 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1611 {
1612 if (_mesa_is_winsys_fbo(fb))
1613 return; /* can't render to texture with winsys framebuffers */
1614
1615 if (ctx->Driver.FinishRenderTexture) {
1616 GLuint i;
1617 for (i = 0; i < BUFFER_COUNT; i++) {
1618 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1619 if (att->Texture && att->Renderbuffer) {
1620 ctx->Driver.FinishRenderTexture(ctx, att);
1621 }
1622 }
1623 }
1624 }
1625
1626
1627 void GLAPIENTRY
1628 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
1629 {
1630 struct gl_framebuffer *newDrawFb, *newReadFb;
1631 struct gl_framebuffer *oldDrawFb, *oldReadFb;
1632 GLboolean bindReadBuf, bindDrawBuf;
1633 GET_CURRENT_CONTEXT(ctx);
1634
1635 #ifdef DEBUG
1636 if (ctx->Extensions.ARB_framebuffer_object) {
1637 ASSERT(ctx->Extensions.EXT_framebuffer_object);
1638 ASSERT(ctx->Extensions.EXT_framebuffer_blit);
1639 }
1640 #endif
1641
1642 ASSERT_OUTSIDE_BEGIN_END(ctx);
1643
1644 if (!ctx->Extensions.EXT_framebuffer_object) {
1645 _mesa_error(ctx, GL_INVALID_OPERATION,
1646 "glBindFramebufferEXT(unsupported)");
1647 return;
1648 }
1649
1650 switch (target) {
1651 #if FEATURE_EXT_framebuffer_blit
1652 case GL_DRAW_FRAMEBUFFER_EXT:
1653 if (!ctx->Extensions.EXT_framebuffer_blit) {
1654 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1655 return;
1656 }
1657 bindDrawBuf = GL_TRUE;
1658 bindReadBuf = GL_FALSE;
1659 break;
1660 case GL_READ_FRAMEBUFFER_EXT:
1661 if (!ctx->Extensions.EXT_framebuffer_blit) {
1662 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1663 return;
1664 }
1665 bindDrawBuf = GL_FALSE;
1666 bindReadBuf = GL_TRUE;
1667 break;
1668 #endif
1669 case GL_FRAMEBUFFER_EXT:
1670 bindDrawBuf = GL_TRUE;
1671 bindReadBuf = GL_TRUE;
1672 break;
1673 default:
1674 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1675 return;
1676 }
1677
1678 if (framebuffer) {
1679 /* Binding a user-created framebuffer object */
1680 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
1681 if (newDrawFb == &DummyFramebuffer) {
1682 /* ID was reserved, but no real framebuffer object made yet */
1683 newDrawFb = NULL;
1684 }
1685 else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) {
1686 /* All FBO IDs must be Gen'd */
1687 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
1688 return;
1689 }
1690
1691 if (!newDrawFb) {
1692 /* create new framebuffer object */
1693 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
1694 if (!newDrawFb) {
1695 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
1696 return;
1697 }
1698 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
1699 }
1700 newReadFb = newDrawFb;
1701 }
1702 else {
1703 /* Binding the window system framebuffer (which was originally set
1704 * with MakeCurrent).
1705 */
1706 newDrawFb = ctx->WinSysDrawBuffer;
1707 newReadFb = ctx->WinSysReadBuffer;
1708 }
1709
1710 ASSERT(newDrawFb);
1711 ASSERT(newDrawFb != &DummyFramebuffer);
1712
1713 /* save pointers to current/old framebuffers */
1714 oldDrawFb = ctx->DrawBuffer;
1715 oldReadFb = ctx->ReadBuffer;
1716
1717 /* check if really changing bindings */
1718 if (oldDrawFb == newDrawFb)
1719 bindDrawBuf = GL_FALSE;
1720 if (oldReadFb == newReadFb)
1721 bindReadBuf = GL_FALSE;
1722
1723 /*
1724 * OK, now bind the new Draw/Read framebuffers, if they're changing.
1725 *
1726 * We also check if we're beginning and/or ending render-to-texture.
1727 * When a framebuffer with texture attachments is unbound, call
1728 * ctx->Driver.FinishRenderTexture().
1729 * When a framebuffer with texture attachments is bound, call
1730 * ctx->Driver.RenderTexture().
1731 *
1732 * Note that if the ReadBuffer has texture attachments we don't consider
1733 * that a render-to-texture case.
1734 */
1735 if (bindReadBuf) {
1736 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1737
1738 /* check if old readbuffer was render-to-texture */
1739 check_end_texture_render(ctx, oldReadFb);
1740
1741 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
1742 }
1743
1744 if (bindDrawBuf) {
1745 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1746
1747 /* check if old read/draw buffers were render-to-texture */
1748 if (!bindReadBuf)
1749 check_end_texture_render(ctx, oldReadFb);
1750
1751 if (oldDrawFb != oldReadFb)
1752 check_end_texture_render(ctx, oldDrawFb);
1753
1754 /* check if newly bound framebuffer has any texture attachments */
1755 check_begin_texture_render(ctx, newDrawFb);
1756
1757 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
1758 }
1759
1760 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
1761 ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
1762 }
1763 }
1764
1765
1766 void GLAPIENTRY
1767 _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
1768 {
1769 GLint i;
1770 GET_CURRENT_CONTEXT(ctx);
1771
1772 ASSERT_OUTSIDE_BEGIN_END(ctx);
1773 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1774
1775 for (i = 0; i < n; i++) {
1776 if (framebuffers[i] > 0) {
1777 struct gl_framebuffer *fb;
1778 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
1779 if (fb) {
1780 ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
1781
1782 /* check if deleting currently bound framebuffer object */
1783 if (ctx->Extensions.EXT_framebuffer_blit) {
1784 /* separate draw/read binding points */
1785 if (fb == ctx->DrawBuffer) {
1786 /* bind default */
1787 ASSERT(fb->RefCount >= 2);
1788 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
1789 }
1790 if (fb == ctx->ReadBuffer) {
1791 /* bind default */
1792 ASSERT(fb->RefCount >= 2);
1793 _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
1794 }
1795 }
1796 else {
1797 /* only one binding point for read/draw buffers */
1798 if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
1799 /* bind default */
1800 ASSERT(fb->RefCount >= 2);
1801 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1802 }
1803 }
1804
1805 /* remove from hash table immediately, to free the ID */
1806 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
1807
1808 if (fb != &DummyFramebuffer) {
1809 /* But the object will not be freed until it's no longer
1810 * bound in any context.
1811 */
1812 _mesa_reference_framebuffer(&fb, NULL);
1813 }
1814 }
1815 }
1816 }
1817 }
1818
1819
1820 void GLAPIENTRY
1821 _mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
1822 {
1823 GET_CURRENT_CONTEXT(ctx);
1824 GLuint first;
1825 GLint i;
1826
1827 ASSERT_OUTSIDE_BEGIN_END(ctx);
1828
1829 if (n < 0) {
1830 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
1831 return;
1832 }
1833
1834 if (!framebuffers)
1835 return;
1836
1837 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
1838
1839 for (i = 0; i < n; i++) {
1840 GLuint name = first + i;
1841 framebuffers[i] = name;
1842 /* insert dummy placeholder into hash table */
1843 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1844 _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
1845 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1846 }
1847 }
1848
1849
1850
1851 GLenum GLAPIENTRY
1852 _mesa_CheckFramebufferStatusEXT(GLenum target)
1853 {
1854 struct gl_framebuffer *buffer;
1855 GET_CURRENT_CONTEXT(ctx);
1856
1857 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
1858
1859 buffer = get_framebuffer_target(ctx, target);
1860 if (!buffer) {
1861 _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
1862 return 0;
1863 }
1864
1865 if (_mesa_is_winsys_fbo(buffer)) {
1866 /* The window system / default framebuffer is always complete */
1867 return GL_FRAMEBUFFER_COMPLETE_EXT;
1868 }
1869
1870 /* No need to flush here */
1871
1872 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
1873 _mesa_test_framebuffer_completeness(ctx, buffer);
1874 }
1875
1876 return buffer->_Status;
1877 }
1878
1879
1880 /**
1881 * Replicate the src attachment point. Used by framebuffer_texture() when
1882 * the same texture is attached at GL_DEPTH_ATTACHMENT and
1883 * GL_STENCIL_ATTACHMENT.
1884 */
1885 static void
1886 reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
1887 gl_buffer_index dst,
1888 gl_buffer_index src)
1889 {
1890 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
1891 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
1892
1893 assert(src_att->Texture != NULL);
1894 assert(src_att->Renderbuffer != NULL);
1895
1896 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
1897 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
1898 dst_att->Type = src_att->Type;
1899 dst_att->Complete = src_att->Complete;
1900 dst_att->TextureLevel = src_att->TextureLevel;
1901 dst_att->Zoffset = src_att->Zoffset;
1902 }
1903
1904
1905 /**
1906 * Common code called by glFramebufferTexture1D/2D/3DEXT().
1907 */
1908 static void
1909 framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
1910 GLenum attachment, GLenum textarget, GLuint texture,
1911 GLint level, GLint zoffset)
1912 {
1913 struct gl_renderbuffer_attachment *att;
1914 struct gl_texture_object *texObj = NULL;
1915 struct gl_framebuffer *fb;
1916
1917 ASSERT_OUTSIDE_BEGIN_END(ctx);
1918
1919 fb = get_framebuffer_target(ctx, target);
1920 if (!fb) {
1921 _mesa_error(ctx, GL_INVALID_ENUM,
1922 "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
1923 return;
1924 }
1925
1926 /* check framebuffer binding */
1927 if (_mesa_is_winsys_fbo(fb)) {
1928 _mesa_error(ctx, GL_INVALID_OPERATION,
1929 "glFramebufferTexture%sEXT", caller);
1930 return;
1931 }
1932
1933 /* The textarget, level, and zoffset parameters are only validated if
1934 * texture is non-zero.
1935 */
1936 if (texture) {
1937 GLboolean err = GL_TRUE;
1938
1939 texObj = _mesa_lookup_texture(ctx, texture);
1940 if (texObj != NULL) {
1941 if (textarget == 0) {
1942 /* XXX what's the purpose of this? */
1943 err = (texObj->Target != GL_TEXTURE_3D) &&
1944 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
1945 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT);
1946 }
1947 else {
1948 err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
1949 ? !_mesa_is_cube_face(textarget)
1950 : (texObj->Target != textarget);
1951 }
1952 }
1953 else {
1954 /* can't render to a non-existant texture */
1955 _mesa_error(ctx, GL_INVALID_OPERATION,
1956 "glFramebufferTexture%sEXT(non existant texture)",
1957 caller);
1958 return;
1959 }
1960
1961 if (err) {
1962 _mesa_error(ctx, GL_INVALID_OPERATION,
1963 "glFramebufferTexture%sEXT(texture target mismatch)",
1964 caller);
1965 return;
1966 }
1967
1968 if (texObj->Target == GL_TEXTURE_3D) {
1969 const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1970 if (zoffset < 0 || zoffset >= maxSize) {
1971 _mesa_error(ctx, GL_INVALID_VALUE,
1972 "glFramebufferTexture%sEXT(zoffset)", caller);
1973 return;
1974 }
1975 }
1976 else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
1977 (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
1978 if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) {
1979 _mesa_error(ctx, GL_INVALID_VALUE,
1980 "glFramebufferTexture%sEXT(layer)", caller);
1981 return;
1982 }
1983 }
1984
1985 if ((level < 0) ||
1986 (level >= _mesa_max_texture_levels(ctx, texObj->Target))) {
1987 _mesa_error(ctx, GL_INVALID_VALUE,
1988 "glFramebufferTexture%sEXT(level)", caller);
1989 return;
1990 }
1991 }
1992
1993 att = _mesa_get_attachment(ctx, fb, attachment);
1994 if (att == NULL) {
1995 _mesa_error(ctx, GL_INVALID_ENUM,
1996 "glFramebufferTexture%sEXT(attachment)", caller);
1997 return;
1998 }
1999
2000 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2001
2002 _glthread_LOCK_MUTEX(fb->Mutex);
2003 if (texObj) {
2004 if (attachment == GL_DEPTH_ATTACHMENT &&
2005 texObj == fb->Attachment[BUFFER_STENCIL].Texture) {
2006 /* The texture object is already attached to the stencil attachment
2007 * point. Don't create a new renderbuffer; just reuse the stencil
2008 * attachment's. This is required to prevent a GL error in
2009 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
2010 */
2011 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
2012 BUFFER_STENCIL);
2013 } else if (attachment == GL_STENCIL_ATTACHMENT &&
2014 texObj == fb->Attachment[BUFFER_DEPTH].Texture) {
2015 /* As above, but with depth and stencil juxtasposed. */
2016 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
2017 BUFFER_DEPTH);
2018 } else {
2019 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
2020 level, zoffset);
2021 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2022 /* Above we created a new renderbuffer and attached it to the
2023 * depth attachment point. Now attach it to the stencil attachment
2024 * point too.
2025 */
2026 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2027 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
2028 BUFFER_DEPTH);
2029 }
2030 }
2031
2032 /* Set the render-to-texture flag. We'll check this flag in
2033 * glTexImage() and friends to determine if we need to revalidate
2034 * any FBOs that might be rendering into this texture.
2035 * This flag never gets cleared since it's non-trivial to determine
2036 * when all FBOs might be done rendering to this texture. That's OK
2037 * though since it's uncommon to render to a texture then repeatedly
2038 * call glTexImage() to change images in the texture.
2039 */
2040 texObj->_RenderToTexture = GL_TRUE;
2041 }
2042 else {
2043 _mesa_remove_attachment(ctx, att);
2044 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2045 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2046 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
2047 }
2048 }
2049
2050 invalidate_framebuffer(fb);
2051
2052 _glthread_UNLOCK_MUTEX(fb->Mutex);
2053 }
2054
2055
2056
2057 void GLAPIENTRY
2058 _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
2059 GLenum textarget, GLuint texture, GLint level)
2060 {
2061 GET_CURRENT_CONTEXT(ctx);
2062
2063 if (texture != 0) {
2064 GLboolean error;
2065
2066 switch (textarget) {
2067 case GL_TEXTURE_1D:
2068 error = GL_FALSE;
2069 break;
2070 case GL_TEXTURE_1D_ARRAY:
2071 error = !ctx->Extensions.EXT_texture_array;
2072 break;
2073 default:
2074 error = GL_TRUE;
2075 }
2076
2077 if (error) {
2078 _mesa_error(ctx, GL_INVALID_OPERATION,
2079 "glFramebufferTexture1DEXT(textarget=%s)",
2080 _mesa_lookup_enum_by_nr(textarget));
2081 return;
2082 }
2083 }
2084
2085 framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
2086 level, 0);
2087 }
2088
2089
2090 void GLAPIENTRY
2091 _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
2092 GLenum textarget, GLuint texture, GLint level)
2093 {
2094 GET_CURRENT_CONTEXT(ctx);
2095
2096 if (texture != 0) {
2097 GLboolean error;
2098
2099 switch (textarget) {
2100 case GL_TEXTURE_2D:
2101 error = GL_FALSE;
2102 break;
2103 case GL_TEXTURE_RECTANGLE:
2104 error = !ctx->Extensions.NV_texture_rectangle;
2105 break;
2106 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2107 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2108 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2109 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2110 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2111 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2112 error = !ctx->Extensions.ARB_texture_cube_map;
2113 break;
2114 case GL_TEXTURE_2D_ARRAY:
2115 error = !ctx->Extensions.EXT_texture_array;
2116 break;
2117 default:
2118 error = GL_TRUE;
2119 }
2120
2121 if (error) {
2122 _mesa_error(ctx, GL_INVALID_OPERATION,
2123 "glFramebufferTexture2DEXT(textarget=%s)",
2124 _mesa_lookup_enum_by_nr(textarget));
2125 return;
2126 }
2127 }
2128
2129 framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
2130 level, 0);
2131 }
2132
2133
2134 void GLAPIENTRY
2135 _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
2136 GLenum textarget, GLuint texture,
2137 GLint level, GLint zoffset)
2138 {
2139 GET_CURRENT_CONTEXT(ctx);
2140
2141 if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
2142 _mesa_error(ctx, GL_INVALID_OPERATION,
2143 "glFramebufferTexture3DEXT(textarget)");
2144 return;
2145 }
2146
2147 framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
2148 level, zoffset);
2149 }
2150
2151
2152 void GLAPIENTRY
2153 _mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
2154 GLuint texture, GLint level, GLint layer)
2155 {
2156 GET_CURRENT_CONTEXT(ctx);
2157
2158 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2159 level, layer);
2160 }
2161
2162
2163 void GLAPIENTRY
2164 _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
2165 GLenum renderbufferTarget,
2166 GLuint renderbuffer)
2167 {
2168 struct gl_renderbuffer_attachment *att;
2169 struct gl_framebuffer *fb;
2170 struct gl_renderbuffer *rb;
2171 GET_CURRENT_CONTEXT(ctx);
2172
2173 ASSERT_OUTSIDE_BEGIN_END(ctx);
2174
2175 fb = get_framebuffer_target(ctx, target);
2176 if (!fb) {
2177 _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
2178 return;
2179 }
2180
2181 if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
2182 _mesa_error(ctx, GL_INVALID_ENUM,
2183 "glFramebufferRenderbufferEXT(renderbufferTarget)");
2184 return;
2185 }
2186
2187 if (_mesa_is_winsys_fbo(fb)) {
2188 /* Can't attach new renderbuffers to a window system framebuffer */
2189 _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
2190 return;
2191 }
2192
2193 att = _mesa_get_attachment(ctx, fb, attachment);
2194 if (att == NULL) {
2195 _mesa_error(ctx, GL_INVALID_ENUM,
2196 "glFramebufferRenderbufferEXT(invalid attachment %s)",
2197 _mesa_lookup_enum_by_nr(attachment));
2198 return;
2199 }
2200
2201 if (renderbuffer) {
2202 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2203 if (!rb) {
2204 _mesa_error(ctx, GL_INVALID_OPERATION,
2205 "glFramebufferRenderbufferEXT(non-existant"
2206 " renderbuffer %u)", renderbuffer);
2207 return;
2208 }
2209 else if (rb == &DummyRenderbuffer) {
2210 /* This is what NVIDIA does */
2211 _mesa_error(ctx, GL_INVALID_VALUE,
2212 "glFramebufferRenderbufferEXT(renderbuffer %u)",
2213 renderbuffer);
2214 return;
2215 }
2216 }
2217 else {
2218 /* remove renderbuffer attachment */
2219 rb = NULL;
2220 }
2221
2222 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2223 rb && rb->Format != MESA_FORMAT_NONE) {
2224 /* make sure the renderbuffer is a depth/stencil format */
2225 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
2226 if (baseFormat != GL_DEPTH_STENCIL) {
2227 _mesa_error(ctx, GL_INVALID_OPERATION,
2228 "glFramebufferRenderbufferEXT(renderbuffer"
2229 " is not DEPTH_STENCIL format)");
2230 return;
2231 }
2232 }
2233
2234
2235 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2236
2237 assert(ctx->Driver.FramebufferRenderbuffer);
2238 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
2239
2240 /* Some subsequent GL commands may depend on the framebuffer's visual
2241 * after the binding is updated. Update visual info now.
2242 */
2243 _mesa_update_framebuffer_visual(ctx, fb);
2244 }
2245
2246
2247 void GLAPIENTRY
2248 _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
2249 GLenum pname, GLint *params)
2250 {
2251 const struct gl_renderbuffer_attachment *att;
2252 struct gl_framebuffer *buffer;
2253 GLenum err;
2254 GET_CURRENT_CONTEXT(ctx);
2255
2256 ASSERT_OUTSIDE_BEGIN_END(ctx);
2257
2258 /* The error differs in GL andd GLES. */
2259 err = ctx->API == API_OPENGL ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
2260
2261 buffer = get_framebuffer_target(ctx, target);
2262 if (!buffer) {
2263 _mesa_error(ctx, GL_INVALID_ENUM,
2264 "glGetFramebufferAttachmentParameterivEXT(target)");
2265 return;
2266 }
2267
2268 if (_mesa_is_winsys_fbo(buffer)) {
2269 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
2270 * says:
2271 *
2272 * "If the framebuffer currently bound to target is zero, then
2273 * INVALID_OPERATION is generated."
2274 *
2275 * The EXT_framebuffer_object spec has the same wording, and the
2276 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
2277 * spec.
2278 */
2279 if (ctx->API != API_OPENGL || !ctx->Extensions.ARB_framebuffer_object) {
2280 _mesa_error(ctx, GL_INVALID_OPERATION,
2281 "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
2282 return;
2283 }
2284 /* the default / window-system FBO */
2285 att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
2286 }
2287 else {
2288 /* user-created framebuffer FBO */
2289 att = _mesa_get_attachment(ctx, buffer, attachment);
2290 }
2291
2292 if (att == NULL) {
2293 _mesa_error(ctx, GL_INVALID_ENUM,
2294 "glGetFramebufferAttachmentParameterivEXT(attachment)");
2295 return;
2296 }
2297
2298 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2299 /* the depth and stencil attachments must point to the same buffer */
2300 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
2301 depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
2302 stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
2303 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
2304 _mesa_error(ctx, GL_INVALID_OPERATION,
2305 "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
2306 " attachments differ)");
2307 return;
2308 }
2309 }
2310
2311 /* No need to flush here */
2312
2313 switch (pname) {
2314 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
2315 *params = _mesa_is_winsys_fbo(buffer)
2316 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
2317 return;
2318 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
2319 if (att->Type == GL_RENDERBUFFER_EXT) {
2320 *params = att->Renderbuffer->Name;
2321 }
2322 else if (att->Type == GL_TEXTURE) {
2323 *params = att->Texture->Name;
2324 }
2325 else {
2326 assert(att->Type == GL_NONE);
2327 if (ctx->API == API_OPENGL) {
2328 *params = 0;
2329 } else {
2330 _mesa_error(ctx, GL_INVALID_ENUM,
2331 "glGetFramebufferAttachmentParameterivEXT(pname)");
2332 }
2333 }
2334 return;
2335 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
2336 if (att->Type == GL_TEXTURE) {
2337 *params = att->TextureLevel;
2338 }
2339 else if (att->Type == GL_NONE) {
2340 _mesa_error(ctx, err,
2341 "glGetFramebufferAttachmentParameterivEXT(pname)");
2342 }
2343 else {
2344 _mesa_error(ctx, GL_INVALID_ENUM,
2345 "glGetFramebufferAttachmentParameterivEXT(pname)");
2346 }
2347 return;
2348 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
2349 if (att->Type == GL_TEXTURE) {
2350 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
2351 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
2352 }
2353 else {
2354 *params = 0;
2355 }
2356 }
2357 else if (att->Type == GL_NONE) {
2358 _mesa_error(ctx, err,
2359 "glGetFramebufferAttachmentParameterivEXT(pname)");
2360 }
2361 else {
2362 _mesa_error(ctx, GL_INVALID_ENUM,
2363 "glGetFramebufferAttachmentParameterivEXT(pname)");
2364 }
2365 return;
2366 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
2367 if (att->Type == GL_TEXTURE) {
2368 if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
2369 *params = att->Zoffset;
2370 }
2371 else {
2372 *params = 0;
2373 }
2374 }
2375 else if (att->Type == GL_NONE) {
2376 _mesa_error(ctx, err,
2377 "glGetFramebufferAttachmentParameterivEXT(pname)");
2378 }
2379 else {
2380 _mesa_error(ctx, GL_INVALID_ENUM,
2381 "glGetFramebufferAttachmentParameterivEXT(pname)");
2382 }
2383 return;
2384 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2385 if (!ctx->Extensions.ARB_framebuffer_object) {
2386 _mesa_error(ctx, GL_INVALID_ENUM,
2387 "glGetFramebufferAttachmentParameterivEXT(pname)");
2388 }
2389 else if (att->Type == GL_NONE) {
2390 _mesa_error(ctx, err,
2391 "glGetFramebufferAttachmentParameterivEXT(pname)");
2392 }
2393 else {
2394 if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) {
2395 *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
2396 }
2397 else {
2398 /* According to ARB_framebuffer_sRGB, we should return LINEAR
2399 * if the sRGB conversion is unsupported. */
2400 *params = GL_LINEAR;
2401 }
2402 }
2403 return;
2404 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
2405 if (!ctx->Extensions.ARB_framebuffer_object) {
2406 _mesa_error(ctx, GL_INVALID_ENUM,
2407 "glGetFramebufferAttachmentParameterivEXT(pname)");
2408 return;
2409 }
2410 else if (att->Type == GL_NONE) {
2411 _mesa_error(ctx, err,
2412 "glGetFramebufferAttachmentParameterivEXT(pname)");
2413 }
2414 else {
2415 gl_format format = att->Renderbuffer->Format;
2416 if (format == MESA_FORMAT_S8) {
2417 /* special cases */
2418 *params = GL_INDEX;
2419 }
2420 else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) {
2421 /* depends on the attachment parameter */
2422 if (attachment == GL_STENCIL_ATTACHMENT) {
2423 *params = GL_INDEX;
2424 }
2425 else {
2426 *params = GL_FLOAT;
2427 }
2428 }
2429 else {
2430 *params = _mesa_get_format_datatype(format);
2431 }
2432 }
2433 return;
2434 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2435 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2436 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2437 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2438 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2439 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2440 if (!ctx->Extensions.ARB_framebuffer_object) {
2441 _mesa_error(ctx, GL_INVALID_ENUM,
2442 "glGetFramebufferAttachmentParameterivEXT(pname)");
2443 }
2444 else if (att->Type == GL_NONE) {
2445 _mesa_error(ctx, err,
2446 "glGetFramebufferAttachmentParameterivEXT(pname)");
2447 }
2448 else if (att->Texture) {
2449 const struct gl_texture_image *texImage =
2450 _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
2451 att->TextureLevel);
2452 if (texImage) {
2453 *params = get_component_bits(pname, texImage->_BaseFormat,
2454 texImage->TexFormat);
2455 }
2456 else {
2457 *params = 0;
2458 }
2459 }
2460 else if (att->Renderbuffer) {
2461 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
2462 att->Renderbuffer->Format);
2463 }
2464 else {
2465 _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
2466 " invalid FBO attachment structure");
2467 }
2468 return;
2469 default:
2470 _mesa_error(ctx, GL_INVALID_ENUM,
2471 "glGetFramebufferAttachmentParameterivEXT(pname)");
2472 return;
2473 }
2474 }
2475
2476
2477 void GLAPIENTRY
2478 _mesa_GenerateMipmapEXT(GLenum target)
2479 {
2480 struct gl_texture_image *srcImage;
2481 struct gl_texture_object *texObj;
2482 GLboolean error;
2483
2484 GET_CURRENT_CONTEXT(ctx);
2485
2486 ASSERT_OUTSIDE_BEGIN_END(ctx);
2487 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2488
2489 switch (target) {
2490 case GL_TEXTURE_1D:
2491 case GL_TEXTURE_2D:
2492 case GL_TEXTURE_3D:
2493 error = GL_FALSE;
2494 break;
2495 case GL_TEXTURE_CUBE_MAP:
2496 error = !ctx->Extensions.ARB_texture_cube_map;
2497 break;
2498 case GL_TEXTURE_1D_ARRAY:
2499 case GL_TEXTURE_2D_ARRAY:
2500 error = !ctx->Extensions.EXT_texture_array;
2501 break;
2502 default:
2503 error = GL_TRUE;
2504 }
2505
2506 if (error) {
2507 _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)",
2508 _mesa_lookup_enum_by_nr(target));
2509 return;
2510 }
2511
2512 texObj = _mesa_get_current_tex_object(ctx, target);
2513
2514 if (texObj->BaseLevel >= texObj->MaxLevel) {
2515 /* nothing to do */
2516 return;
2517 }
2518
2519 if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
2520 !_mesa_cube_complete(texObj)) {
2521 _mesa_error(ctx, GL_INVALID_OPERATION,
2522 "glGenerateMipmap(incomplete cube map)");
2523 return;
2524 }
2525
2526 _mesa_lock_texture(ctx, texObj);
2527
2528 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
2529 if (!srcImage) {
2530 _mesa_unlock_texture(ctx, texObj);
2531 return;
2532 }
2533
2534 if (target == GL_TEXTURE_CUBE_MAP) {
2535 GLuint face;
2536 for (face = 0; face < 6; face++)
2537 ctx->Driver.GenerateMipmap(ctx,
2538 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
2539 texObj);
2540 }
2541 else {
2542 ctx->Driver.GenerateMipmap(ctx, target, texObj);
2543 }
2544 _mesa_unlock_texture(ctx, texObj);
2545 }
2546
2547
2548 #if FEATURE_EXT_framebuffer_blit
2549
2550 static const struct gl_renderbuffer_attachment *
2551 find_attachment(const struct gl_framebuffer *fb,
2552 const struct gl_renderbuffer *rb)
2553 {
2554 GLuint i;
2555 for (i = 0; i < Elements(fb->Attachment); i++) {
2556 if (fb->Attachment[i].Renderbuffer == rb)
2557 return &fb->Attachment[i];
2558 }
2559 return NULL;
2560 }
2561
2562
2563 /**
2564 * Helper function for checking if the datatypes of color buffers are
2565 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
2566 *
2567 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
2568 * and any of the following conditions hold:
2569 * - The read buffer contains fixed-point or floating-point values and any
2570 * draw buffer contains neither fixed-point nor floating-point values.
2571 * - The read buffer contains unsigned integer values and any draw buffer
2572 * does not contain unsigned integer values.
2573 * - The read buffer contains signed integer values and any draw buffer
2574 * does not contain signed integer values."
2575 */
2576 static GLboolean
2577 compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat)
2578 {
2579 GLenum srcType = _mesa_get_format_datatype(srcFormat);
2580 GLenum dstType = _mesa_get_format_datatype(dstFormat);
2581
2582 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
2583 assert(srcType == GL_UNSIGNED_NORMALIZED ||
2584 srcType == GL_SIGNED_NORMALIZED ||
2585 srcType == GL_FLOAT);
2586 /* Boil any of those types down to GL_FLOAT */
2587 srcType = GL_FLOAT;
2588 }
2589
2590 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
2591 assert(dstType == GL_UNSIGNED_NORMALIZED ||
2592 dstType == GL_SIGNED_NORMALIZED ||
2593 dstType == GL_FLOAT);
2594 /* Boil any of those types down to GL_FLOAT */
2595 dstType = GL_FLOAT;
2596 }
2597
2598 return srcType == dstType;
2599 }
2600
2601
2602 /**
2603 * Blit rectangular region, optionally from one framebuffer to another.
2604 *
2605 * Note, if the src buffer is multisampled and the dest is not, this is
2606 * when the samples must be resolved to a single color.
2607 */
2608 void GLAPIENTRY
2609 _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
2610 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
2611 GLbitfield mask, GLenum filter)
2612 {
2613 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
2614 GL_DEPTH_BUFFER_BIT |
2615 GL_STENCIL_BUFFER_BIT);
2616 const struct gl_framebuffer *readFb, *drawFb;
2617 const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
2618 GET_CURRENT_CONTEXT(ctx);
2619
2620 ASSERT_OUTSIDE_BEGIN_END(ctx);
2621 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2622
2623 if (MESA_VERBOSE & VERBOSE_API)
2624 _mesa_debug(ctx,
2625 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
2626 srcX0, srcY0, srcX1, srcY1,
2627 dstX0, dstY0, dstX1, dstY1,
2628 mask, _mesa_lookup_enum_by_nr(filter));
2629
2630 if (ctx->NewState) {
2631 _mesa_update_state(ctx);
2632 }
2633
2634 readFb = ctx->ReadBuffer;
2635 drawFb = ctx->DrawBuffer;
2636
2637 if (!readFb || !drawFb) {
2638 /* This will normally never happen but someday we may want to
2639 * support MakeCurrent() with no drawables.
2640 */
2641 return;
2642 }
2643
2644 /* check for complete framebuffers */
2645 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
2646 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2647 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
2648 "glBlitFramebufferEXT(incomplete draw/read buffers)");
2649 return;
2650 }
2651
2652 if (filter != GL_NEAREST && filter != GL_LINEAR) {
2653 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
2654 return;
2655 }
2656
2657 if (mask & ~legalMaskBits) {
2658 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
2659 return;
2660 }
2661
2662 /* depth/stencil must be blitted with nearest filtering */
2663 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
2664 && filter != GL_NEAREST) {
2665 _mesa_error(ctx, GL_INVALID_OPERATION,
2666 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
2667 return;
2668 }
2669
2670 /* get color read/draw renderbuffers */
2671 if (mask & GL_COLOR_BUFFER_BIT) {
2672 colorReadRb = readFb->_ColorReadBuffer;
2673 colorDrawRb = drawFb->_ColorDrawBuffers[0];
2674
2675 /* From the EXT_framebuffer_object spec:
2676 *
2677 * "If a buffer is specified in <mask> and does not exist in both
2678 * the read and draw framebuffers, the corresponding bit is silently
2679 * ignored."
2680 */
2681 if ((colorReadRb == NULL) || (colorDrawRb == NULL)) {
2682 colorReadRb = colorDrawRb = NULL;
2683 mask &= ~GL_COLOR_BUFFER_BIT;
2684 }
2685 else if (!compatible_color_datatypes(colorReadRb->Format,
2686 colorDrawRb->Format)) {
2687 _mesa_error(ctx, GL_INVALID_OPERATION,
2688 "glBlitFramebufferEXT(color buffer datatypes mismatch)");
2689 return;
2690 }
2691 }
2692 else {
2693 colorReadRb = colorDrawRb = NULL;
2694 }
2695
2696 if (mask & GL_STENCIL_BUFFER_BIT) {
2697 struct gl_renderbuffer *readRb =
2698 readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
2699 struct gl_renderbuffer *drawRb =
2700 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
2701
2702 /* From the EXT_framebuffer_object spec:
2703 *
2704 * "If a buffer is specified in <mask> and does not exist in both
2705 * the read and draw framebuffers, the corresponding bit is silently
2706 * ignored."
2707 */
2708 if ((readRb == NULL) || (drawRb == NULL)) {
2709 mask &= ~GL_STENCIL_BUFFER_BIT;
2710 }
2711 else if (readRb->Format != drawRb->Format) {
2712 _mesa_error(ctx, GL_INVALID_OPERATION,
2713 "glBlitFramebufferEXT(stencil buffer format mismatch)");
2714 return;
2715 }
2716 }
2717
2718 if (mask & GL_DEPTH_BUFFER_BIT) {
2719 struct gl_renderbuffer *readRb =
2720 readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
2721 struct gl_renderbuffer *drawRb =
2722 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
2723
2724 /* From the EXT_framebuffer_object spec:
2725 *
2726 * "If a buffer is specified in <mask> and does not exist in both
2727 * the read and draw framebuffers, the corresponding bit is silently
2728 * ignored."
2729 */
2730 if ((readRb == NULL) || (drawRb == NULL)) {
2731 mask &= ~GL_DEPTH_BUFFER_BIT;
2732 }
2733 else if (readRb->Format != drawRb->Format) {
2734 _mesa_error(ctx, GL_INVALID_OPERATION,
2735 "glBlitFramebufferEXT(depth buffer format mismatch)");
2736 return;
2737 }
2738 }
2739
2740 if (readFb->Visual.samples > 0 &&
2741 drawFb->Visual.samples > 0 &&
2742 readFb->Visual.samples != drawFb->Visual.samples) {
2743 _mesa_error(ctx, GL_INVALID_OPERATION,
2744 "glBlitFramebufferEXT(mismatched samples)");
2745 return;
2746 }
2747
2748 /* extra checks for multisample copies... */
2749 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
2750 /* src and dest region sizes must be the same */
2751 if (srcX1 - srcX0 != dstX1 - dstX0 ||
2752 srcY1 - srcY0 != dstY1 - dstY0) {
2753 _mesa_error(ctx, GL_INVALID_OPERATION,
2754 "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
2755 return;
2756 }
2757
2758 /* color formats must match */
2759 if (colorReadRb &&
2760 colorDrawRb &&
2761 colorReadRb->Format != colorDrawRb->Format) {
2762 _mesa_error(ctx, GL_INVALID_OPERATION,
2763 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
2764 return;
2765 }
2766 }
2767
2768 if (filter == GL_LINEAR && (mask & GL_COLOR_BUFFER_BIT)) {
2769 /* 3.1 spec, page 199:
2770 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
2771 * if filter is LINEAR and read buffer contains integer data."
2772 */
2773 GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
2774 if (type == GL_INT || type == GL_UNSIGNED_INT) {
2775 _mesa_error(ctx, GL_INVALID_OPERATION,
2776 "glBlitFramebufferEXT(integer color type)");
2777 return;
2778 }
2779 }
2780
2781 if (!ctx->Extensions.EXT_framebuffer_blit) {
2782 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
2783 return;
2784 }
2785
2786 /* Debug code */
2787 if (DEBUG_BLIT) {
2788 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
2789 " 0x%x, 0x%x)\n",
2790 srcX0, srcY0, srcX1, srcY1,
2791 dstX0, dstY0, dstX1, dstY1,
2792 mask, filter);
2793 if (colorReadRb) {
2794 const struct gl_renderbuffer_attachment *att;
2795
2796 att = find_attachment(readFb, colorReadRb);
2797 printf(" Src FBO %u RB %u (%dx%d) ",
2798 readFb->Name, colorReadRb->Name,
2799 colorReadRb->Width, colorReadRb->Height);
2800 if (att && att->Texture) {
2801 printf("Tex %u tgt 0x%x level %u face %u",
2802 att->Texture->Name,
2803 att->Texture->Target,
2804 att->TextureLevel,
2805 att->CubeMapFace);
2806 }
2807 printf("\n");
2808
2809 att = find_attachment(drawFb, colorDrawRb);
2810 printf(" Dst FBO %u RB %u (%dx%d) ",
2811 drawFb->Name, colorDrawRb->Name,
2812 colorDrawRb->Width, colorDrawRb->Height);
2813 if (att && att->Texture) {
2814 printf("Tex %u tgt 0x%x level %u face %u",
2815 att->Texture->Name,
2816 att->Texture->Target,
2817 att->TextureLevel,
2818 att->CubeMapFace);
2819 }
2820 printf("\n");
2821 }
2822 }
2823
2824 if (!mask) {
2825 return;
2826 }
2827
2828 ASSERT(ctx->Driver.BlitFramebuffer);
2829 ctx->Driver.BlitFramebuffer(ctx,
2830 srcX0, srcY0, srcX1, srcY1,
2831 dstX0, dstY0, dstX1, dstY1,
2832 mask, filter);
2833 }
2834 #endif /* FEATURE_EXT_framebuffer_blit */
2835
2836
2837 #if FEATURE_ARB_geometry_shader4
2838 void GLAPIENTRY
2839 _mesa_FramebufferTextureARB(GLenum target, GLenum attachment,
2840 GLuint texture, GLint level)
2841 {
2842 GET_CURRENT_CONTEXT(ctx);
2843 _mesa_error(ctx, GL_INVALID_OPERATION,
2844 "glFramebufferTextureARB "
2845 "not implemented!");
2846 }
2847
2848
2849 void GLAPIENTRY
2850 _mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment,
2851 GLuint texture, GLint level, GLenum face)
2852 {
2853 GET_CURRENT_CONTEXT(ctx);
2854 _mesa_error(ctx, GL_INVALID_OPERATION,
2855 "glFramebufferTextureFaceARB "
2856 "not implemented!");
2857 }
2858 #endif /* FEATURE_ARB_geometry_shader4 */