OSDN Git Service

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