fbobject.c revision 7f991d26ad189bc3c08c04dc248a5b2df5ce9f68
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 "glformats.h"
42#include "hash.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 */
71static struct gl_framebuffer DummyFramebuffer;
72static struct gl_renderbuffer DummyRenderbuffer;
73
74/* We bind this framebuffer when applications pass a NULL
75 * drawable/surface in make current. */
76static struct gl_framebuffer IncompleteFramebuffer;
77
78
79static void
80delete_dummy_renderbuffer(struct gl_renderbuffer *rb)
81{
82   /* no op */
83}
84
85static void
86delete_dummy_framebuffer(struct gl_framebuffer *fb)
87{
88   /* no op */
89}
90
91
92void
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
103struct gl_framebuffer *
104_mesa_get_incomplete_framebuffer(void)
105{
106   return &IncompleteFramebuffer;
107}
108
109/**
110 * Helper routine for getting a gl_renderbuffer.
111 */
112struct 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 */
129struct 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 */
148static void
149invalidate_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 */
162static struct gl_framebuffer *
163get_framebuffer_target(struct gl_context *ctx, GLenum target)
164{
165   switch (target) {
166   case GL_DRAW_FRAMEBUFFER:
167      return ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx)
168	 ? ctx->DrawBuffer : NULL;
169   case GL_READ_FRAMEBUFFER:
170      return ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx)
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 */
188struct 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 (!_mesa_is_desktop_gl(ctx))
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 */
241static 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 */
301void
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 */
328void
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 */
369void
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 */
387void
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 */
424void
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 */
459static void
460att_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 */
471static void
472fbo_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 */
483GLboolean
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 */
507static GLboolean
508is_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 */
526static void
527test_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 */
675void
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   /* we're changing framebuffer fields here */
689   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
690
691   numImages = 0;
692   fb->Width = 0;
693   fb->Height = 0;
694
695   /* Start at -2 to more easily loop over all attachment points.
696    *  -2: depth buffer
697    *  -1: stencil buffer
698    * >=0: color buffer
699    */
700   for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
701      struct gl_renderbuffer_attachment *att;
702      GLenum f;
703      gl_format attFormat;
704
705      /*
706       * XXX for ARB_fbo, only check color buffers that are named by
707       * GL_READ_BUFFER and GL_DRAW_BUFFERi.
708       */
709
710      /* check for attachment completeness
711       */
712      if (i == -2) {
713         att = &fb->Attachment[BUFFER_DEPTH];
714         test_attachment_completeness(ctx, GL_DEPTH, att);
715         if (!att->Complete) {
716            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
717            fbo_incomplete("depth attachment incomplete", -1);
718            return;
719         }
720      }
721      else if (i == -1) {
722         att = &fb->Attachment[BUFFER_STENCIL];
723         test_attachment_completeness(ctx, GL_STENCIL, att);
724         if (!att->Complete) {
725            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
726            fbo_incomplete("stencil attachment incomplete", -1);
727            return;
728         }
729      }
730      else {
731         att = &fb->Attachment[BUFFER_COLOR0 + i];
732         test_attachment_completeness(ctx, GL_COLOR, att);
733         if (!att->Complete) {
734            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
735            fbo_incomplete("color attachment incomplete", i);
736            return;
737         }
738      }
739
740      /* get width, height, format of the renderbuffer/texture
741       */
742      if (att->Type == GL_TEXTURE) {
743         const struct gl_texture_image *texImg =
744            _mesa_get_attachment_teximage(att);
745         minWidth = MIN2(minWidth, texImg->Width);
746         maxWidth = MAX2(maxWidth, texImg->Width);
747         minHeight = MIN2(minHeight, texImg->Height);
748         maxHeight = MAX2(maxHeight, texImg->Height);
749         f = texImg->_BaseFormat;
750         attFormat = texImg->TexFormat;
751         numImages++;
752         if (!_mesa_is_legal_color_format(ctx, f) &&
753             !is_legal_depth_format(ctx, f)) {
754            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
755            fbo_incomplete("texture attachment incomplete", -1);
756            return;
757         }
758      }
759      else if (att->Type == GL_RENDERBUFFER_EXT) {
760         minWidth = MIN2(minWidth, att->Renderbuffer->Width);
761         maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
762         minHeight = MIN2(minHeight, att->Renderbuffer->Height);
763         maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
764         f = att->Renderbuffer->InternalFormat;
765         attFormat = att->Renderbuffer->Format;
766         numImages++;
767      }
768      else {
769         assert(att->Type == GL_NONE);
770         continue;
771      }
772
773      if (att->Renderbuffer && numSamples < 0) {
774         /* first buffer */
775         numSamples = att->Renderbuffer->NumSamples;
776      }
777
778      /* check if integer color */
779      fb->_IntegerColor = _mesa_is_format_integer_color(attFormat);
780
781      /* Error-check width, height, format, samples
782       */
783      if (numImages == 1) {
784         /* save format, num samples */
785         if (i >= 0) {
786            intFormat = f;
787         }
788      }
789      else {
790         if (!ctx->Extensions.ARB_framebuffer_object) {
791            /* check that width, height, format are same */
792            if (minWidth != maxWidth || minHeight != maxHeight) {
793               fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
794               fbo_incomplete("width or height mismatch", -1);
795               return;
796            }
797            /* check that all color buffers are the same format */
798            if (intFormat != GL_NONE && f != intFormat) {
799               fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
800               fbo_incomplete("format mismatch", -1);
801               return;
802            }
803         }
804         if (att->Renderbuffer &&
805             att->Renderbuffer->NumSamples != numSamples) {
806            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
807            fbo_incomplete("inconsistant number of samples", i);
808            return;
809         }
810      }
811
812      /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
813       */
814      if (att->Type == GL_RENDERBUFFER &&
815          att->Renderbuffer->Format == MESA_FORMAT_NONE) {
816         fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
817         fbo_incomplete("unsupported renderbuffer format", i);
818         return;
819      }
820   }
821
822#if FEATURE_GL
823   if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
824      /* Check that all DrawBuffers are present */
825      for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
826	 if (fb->ColorDrawBuffer[j] != GL_NONE) {
827	    const struct gl_renderbuffer_attachment *att
828	       = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
829	    assert(att);
830	    if (att->Type == GL_NONE) {
831	       fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
832	       fbo_incomplete("missing drawbuffer", j);
833	       return;
834	    }
835	 }
836      }
837
838      /* Check that the ReadBuffer is present */
839      if (fb->ColorReadBuffer != GL_NONE) {
840	 const struct gl_renderbuffer_attachment *att
841	    = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
842	 assert(att);
843	 if (att->Type == GL_NONE) {
844	    fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
845            fbo_incomplete("missing readbuffer", -1);
846	    return;
847	 }
848      }
849   }
850#else
851   (void) j;
852#endif
853
854   if (numImages == 0) {
855      fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
856      fbo_incomplete("no attachments", -1);
857      return;
858   }
859
860   /* Provisionally set status = COMPLETE ... */
861   fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
862
863   /* ... but the driver may say the FB is incomplete.
864    * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
865    * if anything.
866    */
867   if (ctx->Driver.ValidateFramebuffer) {
868      ctx->Driver.ValidateFramebuffer(ctx, fb);
869      if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
870         fbo_incomplete("driver marked FBO as incomplete", -1);
871      }
872   }
873
874   if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
875      /*
876       * Note that if ARB_framebuffer_object is supported and the attached
877       * renderbuffers/textures are different sizes, the framebuffer
878       * width/height will be set to the smallest width/height.
879       */
880      fb->Width = minWidth;
881      fb->Height = minHeight;
882
883      /* finally, update the visual info for the framebuffer */
884      _mesa_update_framebuffer_visual(ctx, fb);
885   }
886}
887
888
889GLboolean GLAPIENTRY
890_mesa_IsRenderbufferEXT(GLuint renderbuffer)
891{
892   GET_CURRENT_CONTEXT(ctx);
893   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
894   if (renderbuffer) {
895      struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
896      if (rb != NULL && rb != &DummyRenderbuffer)
897         return GL_TRUE;
898   }
899   return GL_FALSE;
900}
901
902
903void GLAPIENTRY
904_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
905{
906   struct gl_renderbuffer *newRb;
907   GET_CURRENT_CONTEXT(ctx);
908
909   ASSERT_OUTSIDE_BEGIN_END(ctx);
910
911   if (target != GL_RENDERBUFFER_EXT) {
912      _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
913      return;
914   }
915
916   /* No need to flush here since the render buffer binding has no
917    * effect on rendering state.
918    */
919
920   if (renderbuffer) {
921      newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
922      if (newRb == &DummyRenderbuffer) {
923         /* ID was reserved, but no real renderbuffer object made yet */
924         newRb = NULL;
925      }
926      else if (!newRb && ctx->Extensions.ARB_framebuffer_object) {
927         /* All RB IDs must be Gen'd */
928         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
929         return;
930      }
931
932      if (!newRb) {
933	 /* create new renderbuffer object */
934	 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
935	 if (!newRb) {
936	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
937	    return;
938	 }
939         ASSERT(newRb->AllocStorage);
940         _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
941         newRb->RefCount = 1; /* referenced by hash table */
942      }
943   }
944   else {
945      newRb = NULL;
946   }
947
948   ASSERT(newRb != &DummyRenderbuffer);
949
950   _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
951}
952
953
954/**
955 * If the given renderbuffer is anywhere attached to the framebuffer, detach
956 * the renderbuffer.
957 * This is used when a renderbuffer object is deleted.
958 * The spec calls for unbinding.
959 */
960static void
961detach_renderbuffer(struct gl_context *ctx,
962                    struct gl_framebuffer *fb,
963                    struct gl_renderbuffer *rb)
964{
965   GLuint i;
966   for (i = 0; i < BUFFER_COUNT; i++) {
967      if (fb->Attachment[i].Renderbuffer == rb) {
968         _mesa_remove_attachment(ctx, &fb->Attachment[i]);
969      }
970   }
971   invalidate_framebuffer(fb);
972}
973
974
975void GLAPIENTRY
976_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
977{
978   GLint i;
979   GET_CURRENT_CONTEXT(ctx);
980
981   ASSERT_OUTSIDE_BEGIN_END(ctx);
982   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
983
984   for (i = 0; i < n; i++) {
985      if (renderbuffers[i] > 0) {
986	 struct gl_renderbuffer *rb;
987	 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
988	 if (rb) {
989            /* check if deleting currently bound renderbuffer object */
990            if (rb == ctx->CurrentRenderbuffer) {
991               /* bind default */
992               ASSERT(rb->RefCount >= 2);
993               _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
994            }
995
996            if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
997               detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
998            }
999            if (_mesa_is_user_fbo(ctx->ReadBuffer)
1000                && ctx->ReadBuffer != ctx->DrawBuffer) {
1001               detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
1002            }
1003
1004	    /* Remove from hash table immediately, to free the ID.
1005             * But the object will not be freed until it's no longer
1006             * referenced anywhere else.
1007             */
1008	    _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
1009
1010            if (rb != &DummyRenderbuffer) {
1011               /* no longer referenced by hash table */
1012               _mesa_reference_renderbuffer(&rb, NULL);
1013	    }
1014	 }
1015      }
1016   }
1017}
1018
1019
1020void GLAPIENTRY
1021_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
1022{
1023   GET_CURRENT_CONTEXT(ctx);
1024   GLuint first;
1025   GLint i;
1026
1027   ASSERT_OUTSIDE_BEGIN_END(ctx);
1028
1029   if (n < 0) {
1030      _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
1031      return;
1032   }
1033
1034   if (!renderbuffers)
1035      return;
1036
1037   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1038
1039   for (i = 0; i < n; i++) {
1040      GLuint name = first + i;
1041      renderbuffers[i] = name;
1042      /* insert dummy placeholder into hash table */
1043      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1044      _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
1045      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1046   }
1047}
1048
1049
1050/**
1051 * Given an internal format token for a render buffer, return the
1052 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
1053 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
1054 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
1055 *
1056 * This is similar to _mesa_base_tex_format() but the set of valid
1057 * internal formats is different.
1058 *
1059 * Note that even if a format is determined to be legal here, validation
1060 * of the FBO may fail if the format is not supported by the driver/GPU.
1061 *
1062 * \param internalFormat  as passed to glRenderbufferStorage()
1063 * \return the base internal format, or 0 if internalFormat is illegal
1064 */
1065GLenum
1066_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
1067{
1068   /*
1069    * Notes: some formats such as alpha, luminance, etc. were added
1070    * with GL_ARB_framebuffer_object.
1071    */
1072   switch (internalFormat) {
1073   case GL_ALPHA:
1074   case GL_ALPHA4:
1075   case GL_ALPHA8:
1076   case GL_ALPHA12:
1077   case GL_ALPHA16:
1078      return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1079   case GL_LUMINANCE:
1080   case GL_LUMINANCE4:
1081   case GL_LUMINANCE8:
1082   case GL_LUMINANCE12:
1083   case GL_LUMINANCE16:
1084      return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1085   case GL_LUMINANCE_ALPHA:
1086   case GL_LUMINANCE4_ALPHA4:
1087   case GL_LUMINANCE6_ALPHA2:
1088   case GL_LUMINANCE8_ALPHA8:
1089   case GL_LUMINANCE12_ALPHA4:
1090   case GL_LUMINANCE12_ALPHA12:
1091   case GL_LUMINANCE16_ALPHA16:
1092      return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1093   case GL_INTENSITY:
1094   case GL_INTENSITY4:
1095   case GL_INTENSITY8:
1096   case GL_INTENSITY12:
1097   case GL_INTENSITY16:
1098      return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1099   case GL_RGB:
1100   case GL_R3_G3_B2:
1101   case GL_RGB4:
1102   case GL_RGB5:
1103   case GL_RGB8:
1104   case GL_RGB10:
1105   case GL_RGB12:
1106   case GL_RGB16:
1107   case GL_SRGB8_EXT:
1108      return GL_RGB;
1109   case GL_RGBA:
1110   case GL_RGBA2:
1111   case GL_RGBA4:
1112   case GL_RGB5_A1:
1113   case GL_RGBA8:
1114   case GL_RGB10_A2:
1115   case GL_RGBA12:
1116   case GL_RGBA16:
1117   case GL_SRGB8_ALPHA8_EXT:
1118      return GL_RGBA;
1119   case GL_STENCIL_INDEX:
1120   case GL_STENCIL_INDEX1_EXT:
1121   case GL_STENCIL_INDEX4_EXT:
1122   case GL_STENCIL_INDEX8_EXT:
1123   case GL_STENCIL_INDEX16_EXT:
1124      return GL_STENCIL_INDEX;
1125   case GL_DEPTH_COMPONENT:
1126   case GL_DEPTH_COMPONENT16:
1127   case GL_DEPTH_COMPONENT24:
1128   case GL_DEPTH_COMPONENT32:
1129      return GL_DEPTH_COMPONENT;
1130   case GL_DEPTH_STENCIL_EXT:
1131   case GL_DEPTH24_STENCIL8_EXT:
1132      if (ctx->Extensions.EXT_packed_depth_stencil)
1133         return GL_DEPTH_STENCIL_EXT;
1134      else
1135         return 0;
1136   case GL_DEPTH_COMPONENT32F:
1137      if (ctx->Extensions.ARB_depth_buffer_float)
1138         return GL_DEPTH_COMPONENT;
1139      else
1140         return 0;
1141   case GL_DEPTH32F_STENCIL8:
1142      if (ctx->Extensions.ARB_depth_buffer_float)
1143         return GL_DEPTH_STENCIL;
1144      else
1145         return 0;
1146   case GL_RED:
1147   case GL_R8:
1148   case GL_R16:
1149      return ctx->Extensions.ARB_texture_rg ? GL_RED : 0;
1150   case GL_RG:
1151   case GL_RG8:
1152   case GL_RG16:
1153      return ctx->Extensions.ARB_texture_rg ? GL_RG : 0;
1154   /* signed normalized texture formats */
1155   case GL_RED_SNORM:
1156   case GL_R8_SNORM:
1157   case GL_R16_SNORM:
1158      return ctx->Extensions.EXT_texture_snorm ? GL_RED : 0;
1159   case GL_RG_SNORM:
1160   case GL_RG8_SNORM:
1161   case GL_RG16_SNORM:
1162      return ctx->Extensions.EXT_texture_snorm ? GL_RG : 0;
1163   case GL_RGB_SNORM:
1164   case GL_RGB8_SNORM:
1165   case GL_RGB16_SNORM:
1166      return ctx->Extensions.EXT_texture_snorm ? GL_RGB : 0;
1167   case GL_RGBA_SNORM:
1168   case GL_RGBA8_SNORM:
1169   case GL_RGBA16_SNORM:
1170      return ctx->Extensions.EXT_texture_snorm ? GL_RGBA : 0;
1171   case GL_ALPHA_SNORM:
1172   case GL_ALPHA8_SNORM:
1173   case GL_ALPHA16_SNORM:
1174      return ctx->Extensions.EXT_texture_snorm &&
1175             ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1176   case GL_LUMINANCE_SNORM:
1177   case GL_LUMINANCE8_SNORM:
1178   case GL_LUMINANCE16_SNORM:
1179      return ctx->Extensions.EXT_texture_snorm &&
1180             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1181   case GL_LUMINANCE_ALPHA_SNORM:
1182   case GL_LUMINANCE8_ALPHA8_SNORM:
1183   case GL_LUMINANCE16_ALPHA16_SNORM:
1184      return ctx->Extensions.EXT_texture_snorm &&
1185             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1186   case GL_INTENSITY_SNORM:
1187   case GL_INTENSITY8_SNORM:
1188   case GL_INTENSITY16_SNORM:
1189      return ctx->Extensions.EXT_texture_snorm &&
1190             ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1191   case GL_R16F:
1192   case GL_R32F:
1193      return ctx->Extensions.ARB_texture_rg &&
1194             ctx->Extensions.ARB_texture_float ? GL_RED : 0;
1195   case GL_RG16F:
1196   case GL_RG32F:
1197      return ctx->Extensions.ARB_texture_rg &&
1198             ctx->Extensions.ARB_texture_float ? GL_RG : 0;
1199   case GL_RGB16F:
1200   case GL_RGB32F:
1201      return ctx->Extensions.ARB_texture_float ? GL_RGB : 0;
1202   case GL_RGBA16F:
1203   case GL_RGBA32F:
1204      return ctx->Extensions.ARB_texture_float ? GL_RGBA : 0;
1205   case GL_ALPHA16F_ARB:
1206   case GL_ALPHA32F_ARB:
1207      return ctx->Extensions.ARB_texture_float &&
1208             ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1209   case GL_LUMINANCE16F_ARB:
1210   case GL_LUMINANCE32F_ARB:
1211      return ctx->Extensions.ARB_texture_float &&
1212             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1213   case GL_LUMINANCE_ALPHA16F_ARB:
1214   case GL_LUMINANCE_ALPHA32F_ARB:
1215      return ctx->Extensions.ARB_texture_float &&
1216             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1217   case GL_INTENSITY16F_ARB:
1218   case GL_INTENSITY32F_ARB:
1219      return ctx->Extensions.ARB_texture_float &&
1220             ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1221   case GL_RGB9_E5:
1222      return ctx->Extensions.EXT_texture_shared_exponent ? GL_RGB : 0;
1223   case GL_R11F_G11F_B10F:
1224      return ctx->Extensions.EXT_packed_float ? GL_RGB : 0;
1225
1226   case GL_RGBA8UI_EXT:
1227   case GL_RGBA16UI_EXT:
1228   case GL_RGBA32UI_EXT:
1229   case GL_RGBA8I_EXT:
1230   case GL_RGBA16I_EXT:
1231   case GL_RGBA32I_EXT:
1232      return ctx->Version >= 30 ||
1233             ctx->Extensions.EXT_texture_integer ? GL_RGBA : 0;
1234
1235   case GL_RGB8UI_EXT:
1236   case GL_RGB16UI_EXT:
1237   case GL_RGB32UI_EXT:
1238   case GL_RGB8I_EXT:
1239   case GL_RGB16I_EXT:
1240   case GL_RGB32I_EXT:
1241      return ctx->Version >= 30 ||
1242             ctx->Extensions.EXT_texture_integer ? GL_RGB : 0;
1243
1244   case GL_R8UI:
1245   case GL_R8I:
1246   case GL_R16UI:
1247   case GL_R16I:
1248   case GL_R32UI:
1249   case GL_R32I:
1250      return ctx->Version >= 30 ||
1251             (ctx->Extensions.ARB_texture_rg &&
1252              ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
1253
1254   case GL_RG8UI:
1255   case GL_RG8I:
1256   case GL_RG16UI:
1257   case GL_RG16I:
1258   case GL_RG32UI:
1259   case GL_RG32I:
1260      return ctx->Version >= 30 ||
1261             (ctx->Extensions.ARB_texture_rg &&
1262              ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
1263
1264   case GL_INTENSITY8I_EXT:
1265   case GL_INTENSITY8UI_EXT:
1266   case GL_INTENSITY16I_EXT:
1267   case GL_INTENSITY16UI_EXT:
1268   case GL_INTENSITY32I_EXT:
1269   case GL_INTENSITY32UI_EXT:
1270      return ctx->Extensions.EXT_texture_integer &&
1271             ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1272
1273   case GL_LUMINANCE8I_EXT:
1274   case GL_LUMINANCE8UI_EXT:
1275   case GL_LUMINANCE16I_EXT:
1276   case GL_LUMINANCE16UI_EXT:
1277   case GL_LUMINANCE32I_EXT:
1278   case GL_LUMINANCE32UI_EXT:
1279      return ctx->Extensions.EXT_texture_integer &&
1280             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1281
1282   case GL_LUMINANCE_ALPHA8I_EXT:
1283   case GL_LUMINANCE_ALPHA8UI_EXT:
1284   case GL_LUMINANCE_ALPHA16I_EXT:
1285   case GL_LUMINANCE_ALPHA16UI_EXT:
1286   case GL_LUMINANCE_ALPHA32I_EXT:
1287   case GL_LUMINANCE_ALPHA32UI_EXT:
1288      return ctx->Extensions.EXT_texture_integer &&
1289             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1290
1291   case GL_ALPHA8I_EXT:
1292   case GL_ALPHA8UI_EXT:
1293   case GL_ALPHA16I_EXT:
1294   case GL_ALPHA16UI_EXT:
1295   case GL_ALPHA32I_EXT:
1296   case GL_ALPHA32UI_EXT:
1297      return ctx->Extensions.EXT_texture_integer &&
1298             ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1299
1300   case GL_RGB10_A2UI:
1301      return ctx->Extensions.ARB_texture_rgb10_a2ui ? GL_RGBA : 0;
1302
1303   case GL_RGB565:
1304      return ctx->Extensions.ARB_ES2_compatibility ? GL_RGB : 0;
1305   default:
1306      return 0;
1307   }
1308}
1309
1310
1311/**
1312 * Invalidate a renderbuffer attachment.  Called from _mesa_HashWalk().
1313 */
1314static void
1315invalidate_rb(GLuint key, void *data, void *userData)
1316{
1317   struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
1318   struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
1319
1320   /* If this is a user-created FBO */
1321   if (_mesa_is_user_fbo(fb)) {
1322      GLuint i;
1323      for (i = 0; i < BUFFER_COUNT; i++) {
1324         struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1325         if (att->Type == GL_RENDERBUFFER &&
1326             att->Renderbuffer == rb) {
1327            /* Mark fb status as indeterminate to force re-validation */
1328            fb->_Status = 0;
1329            return;
1330         }
1331      }
1332   }
1333}
1334
1335
1336/** sentinal value, see below */
1337#define NO_SAMPLES 1000
1338
1339
1340/**
1341 * Helper function used by _mesa_RenderbufferStorageEXT() and
1342 * _mesa_RenderbufferStorageMultisample().
1343 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT().
1344 */
1345static void
1346renderbuffer_storage(GLenum target, GLenum internalFormat,
1347                     GLsizei width, GLsizei height, GLsizei samples)
1348{
1349   const char *func = samples == NO_SAMPLES ?
1350      "glRenderbufferStorage" : "RenderbufferStorageMultisample";
1351   struct gl_renderbuffer *rb;
1352   GLenum baseFormat;
1353   GET_CURRENT_CONTEXT(ctx);
1354
1355   ASSERT_OUTSIDE_BEGIN_END(ctx);
1356
1357   if (target != GL_RENDERBUFFER_EXT) {
1358      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
1359      return;
1360   }
1361
1362   baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
1363   if (baseFormat == 0) {
1364      _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func);
1365      return;
1366   }
1367
1368   if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1369      _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
1370      return;
1371   }
1372
1373   if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1374      _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
1375      return;
1376   }
1377
1378   if (samples == NO_SAMPLES) {
1379      /* NumSamples == 0 indicates non-multisampling */
1380      samples = 0;
1381   }
1382   else if (samples > (GLsizei) ctx->Const.MaxSamples) {
1383      /* note: driver may choose to use more samples than what's requested */
1384      _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
1385      return;
1386   }
1387
1388   rb = ctx->CurrentRenderbuffer;
1389   if (!rb) {
1390      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1391      return;
1392   }
1393
1394   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1395
1396   if (rb->InternalFormat == internalFormat &&
1397       rb->Width == (GLuint) width &&
1398       rb->Height == (GLuint) height &&
1399       rb->NumSamples == samples) {
1400      /* no change in allocation needed */
1401      return;
1402   }
1403
1404   /* These MUST get set by the AllocStorage func */
1405   rb->Format = MESA_FORMAT_NONE;
1406   rb->NumSamples = samples;
1407
1408   /* Now allocate the storage */
1409   ASSERT(rb->AllocStorage);
1410   if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
1411      /* No error - check/set fields now */
1412      /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
1413      assert(rb->Width == (GLuint) width);
1414      assert(rb->Height == (GLuint) height);
1415      rb->InternalFormat = internalFormat;
1416      rb->_BaseFormat = baseFormat;
1417      assert(rb->_BaseFormat != 0);
1418   }
1419   else {
1420      /* Probably ran out of memory - clear the fields */
1421      rb->Width = 0;
1422      rb->Height = 0;
1423      rb->Format = MESA_FORMAT_NONE;
1424      rb->InternalFormat = GL_NONE;
1425      rb->_BaseFormat = GL_NONE;
1426      rb->NumSamples = 0;
1427   }
1428
1429   /* Invalidate the framebuffers the renderbuffer is attached in. */
1430   if (rb->AttachedAnytime) {
1431      _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
1432   }
1433}
1434
1435
1436#if FEATURE_OES_EGL_image
1437void GLAPIENTRY
1438_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
1439{
1440   struct gl_renderbuffer *rb;
1441   GET_CURRENT_CONTEXT(ctx);
1442   ASSERT_OUTSIDE_BEGIN_END(ctx);
1443
1444   if (!ctx->Extensions.OES_EGL_image) {
1445      _mesa_error(ctx, GL_INVALID_OPERATION,
1446                  "glEGLImageTargetRenderbufferStorageOES(unsupported)");
1447      return;
1448   }
1449
1450   if (target != GL_RENDERBUFFER) {
1451      _mesa_error(ctx, GL_INVALID_ENUM,
1452                  "EGLImageTargetRenderbufferStorageOES");
1453      return;
1454   }
1455
1456   rb = ctx->CurrentRenderbuffer;
1457   if (!rb) {
1458      _mesa_error(ctx, GL_INVALID_OPERATION,
1459                  "EGLImageTargetRenderbufferStorageOES");
1460      return;
1461   }
1462
1463   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1464
1465   ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
1466}
1467#endif
1468
1469
1470/**
1471 * Helper function for _mesa_GetRenderbufferParameterivEXT() and
1472 * _mesa_GetFramebufferAttachmentParameterivEXT()
1473 * We have to be careful to respect the base format.  For example, if a
1474 * renderbuffer/texture was created with internalFormat=GL_RGB but the
1475 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
1476 * we need to return zero.
1477 */
1478static GLint
1479get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
1480{
1481   if (_mesa_base_format_has_channel(baseFormat, pname))
1482      return _mesa_get_format_bits(format, pname);
1483   else
1484      return 0;
1485}
1486
1487
1488
1489void GLAPIENTRY
1490_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1491                             GLsizei width, GLsizei height)
1492{
1493   /* GL_ARB_fbo says calling this function is equivalent to calling
1494    * glRenderbufferStorageMultisample() with samples=0.  We pass in
1495    * a token value here just for error reporting purposes.
1496    */
1497   renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
1498}
1499
1500
1501void GLAPIENTRY
1502_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
1503                                     GLenum internalFormat,
1504                                     GLsizei width, GLsizei height)
1505{
1506   renderbuffer_storage(target, internalFormat, width, height, samples);
1507}
1508
1509
1510/**
1511 * OpenGL ES version of glRenderBufferStorage.
1512 */
1513void GLAPIENTRY
1514_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1515			   GLsizei width, GLsizei height)
1516{
1517   switch (internalFormat) {
1518   case GL_RGB565:
1519      /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
1520      /* choose a closest format */
1521      internalFormat = GL_RGB5;
1522      break;
1523   default:
1524      break;
1525   }
1526
1527   renderbuffer_storage(target, internalFormat, width, height, 0);
1528}
1529
1530
1531void GLAPIENTRY
1532_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params)
1533{
1534   struct gl_renderbuffer *rb;
1535   GET_CURRENT_CONTEXT(ctx);
1536
1537   ASSERT_OUTSIDE_BEGIN_END(ctx);
1538
1539   if (target != GL_RENDERBUFFER_EXT) {
1540      _mesa_error(ctx, GL_INVALID_ENUM,
1541                  "glGetRenderbufferParameterivEXT(target)");
1542      return;
1543   }
1544
1545   rb = ctx->CurrentRenderbuffer;
1546   if (!rb) {
1547      _mesa_error(ctx, GL_INVALID_OPERATION,
1548                  "glGetRenderbufferParameterivEXT");
1549      return;
1550   }
1551
1552   /* No need to flush here since we're just quering state which is
1553    * not effected by rendering.
1554    */
1555
1556   switch (pname) {
1557   case GL_RENDERBUFFER_WIDTH_EXT:
1558      *params = rb->Width;
1559      return;
1560   case GL_RENDERBUFFER_HEIGHT_EXT:
1561      *params = rb->Height;
1562      return;
1563   case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
1564      *params = rb->InternalFormat;
1565      return;
1566   case GL_RENDERBUFFER_RED_SIZE_EXT:
1567   case GL_RENDERBUFFER_GREEN_SIZE_EXT:
1568   case GL_RENDERBUFFER_BLUE_SIZE_EXT:
1569   case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
1570   case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
1571   case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
1572      *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
1573      break;
1574   case GL_RENDERBUFFER_SAMPLES:
1575      if (ctx->Extensions.ARB_framebuffer_object) {
1576         *params = rb->NumSamples;
1577         break;
1578      }
1579      /* fallthrough */
1580   default:
1581      _mesa_error(ctx, GL_INVALID_ENUM,
1582                  "glGetRenderbufferParameterivEXT(target)");
1583      return;
1584   }
1585}
1586
1587
1588GLboolean GLAPIENTRY
1589_mesa_IsFramebufferEXT(GLuint framebuffer)
1590{
1591   GET_CURRENT_CONTEXT(ctx);
1592   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1593   if (framebuffer) {
1594      struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
1595      if (rb != NULL && rb != &DummyFramebuffer)
1596         return GL_TRUE;
1597   }
1598   return GL_FALSE;
1599}
1600
1601
1602/**
1603 * Check if any of the attachments of the given framebuffer are textures
1604 * (render to texture).  Call ctx->Driver.RenderTexture() for such
1605 * attachments.
1606 */
1607static void
1608check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1609{
1610   GLuint i;
1611   ASSERT(ctx->Driver.RenderTexture);
1612
1613   if (_mesa_is_winsys_fbo(fb))
1614      return; /* can't render to texture with winsys framebuffers */
1615
1616   for (i = 0; i < BUFFER_COUNT; i++) {
1617      struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1618      if (att->Texture && _mesa_get_attachment_teximage(att)) {
1619         ctx->Driver.RenderTexture(ctx, fb, att);
1620      }
1621   }
1622}
1623
1624
1625/**
1626 * Examine all the framebuffer's attachments to see if any are textures.
1627 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
1628 * notify the device driver that the texture image may have changed.
1629 */
1630static void
1631check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1632{
1633   if (_mesa_is_winsys_fbo(fb))
1634      return; /* can't render to texture with winsys framebuffers */
1635
1636   if (ctx->Driver.FinishRenderTexture) {
1637      GLuint i;
1638      for (i = 0; i < BUFFER_COUNT; i++) {
1639         struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1640         if (att->Texture && att->Renderbuffer) {
1641            ctx->Driver.FinishRenderTexture(ctx, att);
1642         }
1643      }
1644   }
1645}
1646
1647
1648void GLAPIENTRY
1649_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
1650{
1651   struct gl_framebuffer *newDrawFb, *newReadFb;
1652   struct gl_framebuffer *oldDrawFb, *oldReadFb;
1653   GLboolean bindReadBuf, bindDrawBuf;
1654   GET_CURRENT_CONTEXT(ctx);
1655
1656#ifdef DEBUG
1657   if (ctx->Extensions.ARB_framebuffer_object) {
1658      ASSERT(ctx->Extensions.EXT_framebuffer_object);
1659      ASSERT(ctx->Extensions.EXT_framebuffer_blit);
1660   }
1661#endif
1662
1663   ASSERT_OUTSIDE_BEGIN_END(ctx);
1664
1665   if (!ctx->Extensions.EXT_framebuffer_object) {
1666      _mesa_error(ctx, GL_INVALID_OPERATION,
1667                  "glBindFramebufferEXT(unsupported)");
1668      return;
1669   }
1670
1671   switch (target) {
1672#if FEATURE_EXT_framebuffer_blit
1673   case GL_DRAW_FRAMEBUFFER_EXT:
1674      if (!ctx->Extensions.EXT_framebuffer_blit) {
1675         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1676         return;
1677      }
1678      bindDrawBuf = GL_TRUE;
1679      bindReadBuf = GL_FALSE;
1680      break;
1681   case GL_READ_FRAMEBUFFER_EXT:
1682      if (!ctx->Extensions.EXT_framebuffer_blit) {
1683         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1684         return;
1685      }
1686      bindDrawBuf = GL_FALSE;
1687      bindReadBuf = GL_TRUE;
1688      break;
1689#endif
1690   case GL_FRAMEBUFFER_EXT:
1691      bindDrawBuf = GL_TRUE;
1692      bindReadBuf = GL_TRUE;
1693      break;
1694   default:
1695      _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1696      return;
1697   }
1698
1699   if (framebuffer) {
1700      /* Binding a user-created framebuffer object */
1701      newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
1702      if (newDrawFb == &DummyFramebuffer) {
1703         /* ID was reserved, but no real framebuffer object made yet */
1704         newDrawFb = NULL;
1705      }
1706      else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) {
1707         /* All FBO IDs must be Gen'd */
1708         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
1709         return;
1710      }
1711
1712      if (!newDrawFb) {
1713	 /* create new framebuffer object */
1714	 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
1715	 if (!newDrawFb) {
1716	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
1717	    return;
1718	 }
1719         _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
1720      }
1721      newReadFb = newDrawFb;
1722   }
1723   else {
1724      /* Binding the window system framebuffer (which was originally set
1725       * with MakeCurrent).
1726       */
1727      newDrawFb = ctx->WinSysDrawBuffer;
1728      newReadFb = ctx->WinSysReadBuffer;
1729   }
1730
1731   ASSERT(newDrawFb);
1732   ASSERT(newDrawFb != &DummyFramebuffer);
1733
1734   /* save pointers to current/old framebuffers */
1735   oldDrawFb = ctx->DrawBuffer;
1736   oldReadFb = ctx->ReadBuffer;
1737
1738   /* check if really changing bindings */
1739   if (oldDrawFb == newDrawFb)
1740      bindDrawBuf = GL_FALSE;
1741   if (oldReadFb == newReadFb)
1742      bindReadBuf = GL_FALSE;
1743
1744   /*
1745    * OK, now bind the new Draw/Read framebuffers, if they're changing.
1746    *
1747    * We also check if we're beginning and/or ending render-to-texture.
1748    * When a framebuffer with texture attachments is unbound, call
1749    * ctx->Driver.FinishRenderTexture().
1750    * When a framebuffer with texture attachments is bound, call
1751    * ctx->Driver.RenderTexture().
1752    *
1753    * Note that if the ReadBuffer has texture attachments we don't consider
1754    * that a render-to-texture case.
1755    */
1756   if (bindReadBuf) {
1757      FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1758
1759      /* check if old readbuffer was render-to-texture */
1760      check_end_texture_render(ctx, oldReadFb);
1761
1762      _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
1763   }
1764
1765   if (bindDrawBuf) {
1766      FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1767
1768      /* check if old framebuffer had any texture attachments */
1769      if (oldDrawFb)
1770         check_end_texture_render(ctx, oldDrawFb);
1771
1772      /* check if newly bound framebuffer has any texture attachments */
1773      check_begin_texture_render(ctx, newDrawFb);
1774
1775      _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
1776   }
1777
1778   if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
1779      ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
1780   }
1781}
1782
1783
1784void GLAPIENTRY
1785_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
1786{
1787   GLint i;
1788   GET_CURRENT_CONTEXT(ctx);
1789
1790   ASSERT_OUTSIDE_BEGIN_END(ctx);
1791   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1792
1793   for (i = 0; i < n; i++) {
1794      if (framebuffers[i] > 0) {
1795	 struct gl_framebuffer *fb;
1796	 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
1797	 if (fb) {
1798            ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
1799
1800            /* check if deleting currently bound framebuffer object */
1801            if (ctx->Extensions.EXT_framebuffer_blit) {
1802               /* separate draw/read binding points */
1803               if (fb == ctx->DrawBuffer) {
1804                  /* bind default */
1805                  ASSERT(fb->RefCount >= 2);
1806                  _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
1807               }
1808               if (fb == ctx->ReadBuffer) {
1809                  /* bind default */
1810                  ASSERT(fb->RefCount >= 2);
1811                  _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
1812               }
1813            }
1814            else {
1815               /* only one binding point for read/draw buffers */
1816               if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
1817                  /* bind default */
1818                  ASSERT(fb->RefCount >= 2);
1819                  _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1820               }
1821            }
1822
1823	    /* remove from hash table immediately, to free the ID */
1824	    _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
1825
1826            if (fb != &DummyFramebuffer) {
1827               /* But the object will not be freed until it's no longer
1828                * bound in any context.
1829                */
1830               _mesa_reference_framebuffer(&fb, NULL);
1831	    }
1832	 }
1833      }
1834   }
1835}
1836
1837
1838void GLAPIENTRY
1839_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
1840{
1841   GET_CURRENT_CONTEXT(ctx);
1842   GLuint first;
1843   GLint i;
1844
1845   ASSERT_OUTSIDE_BEGIN_END(ctx);
1846
1847   if (n < 0) {
1848      _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
1849      return;
1850   }
1851
1852   if (!framebuffers)
1853      return;
1854
1855   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
1856
1857   for (i = 0; i < n; i++) {
1858      GLuint name = first + i;
1859      framebuffers[i] = name;
1860      /* insert dummy placeholder into hash table */
1861      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1862      _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
1863      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1864   }
1865}
1866
1867
1868
1869GLenum GLAPIENTRY
1870_mesa_CheckFramebufferStatusEXT(GLenum target)
1871{
1872   struct gl_framebuffer *buffer;
1873   GET_CURRENT_CONTEXT(ctx);
1874
1875   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
1876
1877   buffer = get_framebuffer_target(ctx, target);
1878   if (!buffer) {
1879      _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
1880      return 0;
1881   }
1882
1883   if (_mesa_is_winsys_fbo(buffer)) {
1884      /* The window system / default framebuffer is always complete */
1885      return GL_FRAMEBUFFER_COMPLETE_EXT;
1886   }
1887
1888   /* No need to flush here */
1889
1890   if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
1891      _mesa_test_framebuffer_completeness(ctx, buffer);
1892   }
1893
1894   return buffer->_Status;
1895}
1896
1897
1898/**
1899 * Replicate the src attachment point. Used by framebuffer_texture() when
1900 * the same texture is attached at GL_DEPTH_ATTACHMENT and
1901 * GL_STENCIL_ATTACHMENT.
1902 */
1903static void
1904reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
1905                                     gl_buffer_index dst,
1906                                     gl_buffer_index src)
1907{
1908   struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
1909   struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
1910
1911   assert(src_att->Texture != NULL);
1912   assert(src_att->Renderbuffer != NULL);
1913
1914   _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
1915   _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
1916   dst_att->Type = src_att->Type;
1917   dst_att->Complete = src_att->Complete;
1918   dst_att->TextureLevel = src_att->TextureLevel;
1919   dst_att->Zoffset = src_att->Zoffset;
1920}
1921
1922
1923/**
1924 * Common code called by glFramebufferTexture1D/2D/3DEXT() and
1925 * glFramebufferTextureLayerEXT().
1926 * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll
1927 * get textarget=0 in that case.
1928 */
1929static void
1930framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
1931                    GLenum attachment, GLenum textarget, GLuint texture,
1932                    GLint level, GLint zoffset)
1933{
1934   struct gl_renderbuffer_attachment *att;
1935   struct gl_texture_object *texObj = NULL;
1936   struct gl_framebuffer *fb;
1937   GLenum maxLevelsTarget;
1938
1939   ASSERT_OUTSIDE_BEGIN_END(ctx);
1940
1941   fb = get_framebuffer_target(ctx, target);
1942   if (!fb) {
1943      _mesa_error(ctx, GL_INVALID_ENUM,
1944                  "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
1945      return;
1946   }
1947
1948   /* check framebuffer binding */
1949   if (_mesa_is_winsys_fbo(fb)) {
1950      _mesa_error(ctx, GL_INVALID_OPERATION,
1951                  "glFramebufferTexture%sEXT", caller);
1952      return;
1953   }
1954
1955   /* The textarget, level, and zoffset parameters are only validated if
1956    * texture is non-zero.
1957    */
1958   if (texture) {
1959      GLboolean err = GL_TRUE;
1960
1961      texObj = _mesa_lookup_texture(ctx, texture);
1962      if (texObj != NULL) {
1963         if (textarget == 0) {
1964            /* If textarget == 0 it means we're being called by
1965             * glFramebufferTextureLayer() and textarget is not used.
1966             * The only legal texture types for that function are 3D and
1967             * 1D/2D arrays textures.
1968             */
1969            err = (texObj->Target != GL_TEXTURE_3D) &&
1970                (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
1971                (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT);
1972         }
1973         else {
1974            /* Make sure textarget is consistent with the texture's type */
1975            err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
1976                ? !_mesa_is_cube_face(textarget)
1977                : (texObj->Target != textarget);
1978         }
1979      }
1980      else {
1981         /* can't render to a non-existant texture */
1982         _mesa_error(ctx, GL_INVALID_OPERATION,
1983                     "glFramebufferTexture%sEXT(non existant texture)",
1984                     caller);
1985         return;
1986      }
1987
1988      if (err) {
1989         _mesa_error(ctx, GL_INVALID_OPERATION,
1990                     "glFramebufferTexture%sEXT(texture target mismatch)",
1991                     caller);
1992         return;
1993      }
1994
1995      if (texObj->Target == GL_TEXTURE_3D) {
1996         const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1997         if (zoffset < 0 || zoffset >= maxSize) {
1998            _mesa_error(ctx, GL_INVALID_VALUE,
1999                        "glFramebufferTexture%sEXT(zoffset)", caller);
2000            return;
2001         }
2002      }
2003      else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
2004               (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) {
2005         if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) {
2006            _mesa_error(ctx, GL_INVALID_VALUE,
2007                        "glFramebufferTexture%sEXT(layer)", caller);
2008            return;
2009         }
2010      }
2011
2012      maxLevelsTarget = textarget ? textarget : texObj->Target;
2013      if ((level < 0) ||
2014          (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
2015         _mesa_error(ctx, GL_INVALID_VALUE,
2016                     "glFramebufferTexture%sEXT(level)", caller);
2017         return;
2018      }
2019   }
2020
2021   att = _mesa_get_attachment(ctx, fb, attachment);
2022   if (att == NULL) {
2023      _mesa_error(ctx, GL_INVALID_ENUM,
2024                  "glFramebufferTexture%sEXT(attachment)", caller);
2025      return;
2026   }
2027
2028   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2029
2030   _glthread_LOCK_MUTEX(fb->Mutex);
2031   if (texObj) {
2032      if (attachment == GL_DEPTH_ATTACHMENT &&
2033          texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
2034          level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
2035          _mesa_tex_target_to_face(textarget) ==
2036          fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
2037          zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
2038	 /* The texture object is already attached to the stencil attachment
2039	  * point. Don't create a new renderbuffer; just reuse the stencil
2040	  * attachment's. This is required to prevent a GL error in
2041	  * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
2042	  */
2043	 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
2044	                                      BUFFER_STENCIL);
2045      } else if (attachment == GL_STENCIL_ATTACHMENT &&
2046	         texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
2047                 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
2048                 _mesa_tex_target_to_face(textarget) ==
2049                 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
2050                 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
2051	 /* As above, but with depth and stencil transposed. */
2052	 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
2053	                                      BUFFER_DEPTH);
2054      } else {
2055	 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
2056				      level, zoffset);
2057	 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2058	    /* Above we created a new renderbuffer and attached it to the
2059	     * depth attachment point. Now attach it to the stencil attachment
2060	     * point too.
2061	     */
2062	    assert(att == &fb->Attachment[BUFFER_DEPTH]);
2063	    reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
2064	                                         BUFFER_DEPTH);
2065	 }
2066      }
2067
2068      /* Set the render-to-texture flag.  We'll check this flag in
2069       * glTexImage() and friends to determine if we need to revalidate
2070       * any FBOs that might be rendering into this texture.
2071       * This flag never gets cleared since it's non-trivial to determine
2072       * when all FBOs might be done rendering to this texture.  That's OK
2073       * though since it's uncommon to render to a texture then repeatedly
2074       * call glTexImage() to change images in the texture.
2075       */
2076      texObj->_RenderToTexture = GL_TRUE;
2077   }
2078   else {
2079      _mesa_remove_attachment(ctx, att);
2080      if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2081	 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2082	 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
2083      }
2084   }
2085
2086   invalidate_framebuffer(fb);
2087
2088   _glthread_UNLOCK_MUTEX(fb->Mutex);
2089}
2090
2091
2092
2093void GLAPIENTRY
2094_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
2095                              GLenum textarget, GLuint texture, GLint level)
2096{
2097   GET_CURRENT_CONTEXT(ctx);
2098
2099   if (texture != 0) {
2100      GLboolean error;
2101
2102      switch (textarget) {
2103      case GL_TEXTURE_1D:
2104         error = GL_FALSE;
2105         break;
2106      case GL_TEXTURE_1D_ARRAY:
2107         error = !ctx->Extensions.EXT_texture_array;
2108         break;
2109      default:
2110         error = GL_TRUE;
2111      }
2112
2113      if (error) {
2114         _mesa_error(ctx, GL_INVALID_OPERATION,
2115                     "glFramebufferTexture1DEXT(textarget=%s)",
2116                     _mesa_lookup_enum_by_nr(textarget));
2117         return;
2118      }
2119   }
2120
2121   framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
2122                       level, 0);
2123}
2124
2125
2126void GLAPIENTRY
2127_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
2128                              GLenum textarget, GLuint texture, GLint level)
2129{
2130   GET_CURRENT_CONTEXT(ctx);
2131
2132   if (texture != 0) {
2133      GLboolean error;
2134
2135      switch (textarget) {
2136      case GL_TEXTURE_2D:
2137         error = GL_FALSE;
2138         break;
2139      case GL_TEXTURE_RECTANGLE:
2140         error = _mesa_is_gles(ctx)
2141            || !ctx->Extensions.NV_texture_rectangle;
2142         break;
2143      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2144      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2145      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2146      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2147      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2148      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2149         error = !ctx->Extensions.ARB_texture_cube_map;
2150         break;
2151      case GL_TEXTURE_2D_ARRAY:
2152         error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2153            || !ctx->Extensions.EXT_texture_array;
2154         break;
2155      default:
2156         error = GL_TRUE;
2157      }
2158
2159      if (error) {
2160         _mesa_error(ctx, GL_INVALID_OPERATION,
2161                     "glFramebufferTexture2DEXT(textarget=%s)",
2162                     _mesa_lookup_enum_by_nr(textarget));
2163         return;
2164      }
2165   }
2166
2167   framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
2168                       level, 0);
2169}
2170
2171
2172void GLAPIENTRY
2173_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment,
2174                              GLenum textarget, GLuint texture,
2175                              GLint level, GLint zoffset)
2176{
2177   GET_CURRENT_CONTEXT(ctx);
2178
2179   if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
2180      _mesa_error(ctx, GL_INVALID_OPERATION,
2181                  "glFramebufferTexture3DEXT(textarget)");
2182      return;
2183   }
2184
2185   framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
2186                       level, zoffset);
2187}
2188
2189
2190void GLAPIENTRY
2191_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment,
2192                                 GLuint texture, GLint level, GLint layer)
2193{
2194   GET_CURRENT_CONTEXT(ctx);
2195
2196   framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2197                       level, layer);
2198}
2199
2200
2201void GLAPIENTRY
2202_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
2203                                 GLenum renderbufferTarget,
2204                                 GLuint renderbuffer)
2205{
2206   struct gl_renderbuffer_attachment *att;
2207   struct gl_framebuffer *fb;
2208   struct gl_renderbuffer *rb;
2209   GET_CURRENT_CONTEXT(ctx);
2210
2211   ASSERT_OUTSIDE_BEGIN_END(ctx);
2212
2213   fb = get_framebuffer_target(ctx, target);
2214   if (!fb) {
2215      _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
2216      return;
2217   }
2218
2219   if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
2220      _mesa_error(ctx, GL_INVALID_ENUM,
2221                  "glFramebufferRenderbufferEXT(renderbufferTarget)");
2222      return;
2223   }
2224
2225   if (_mesa_is_winsys_fbo(fb)) {
2226      /* Can't attach new renderbuffers to a window system framebuffer */
2227      _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
2228      return;
2229   }
2230
2231   att = _mesa_get_attachment(ctx, fb, attachment);
2232   if (att == NULL) {
2233      _mesa_error(ctx, GL_INVALID_ENUM,
2234                  "glFramebufferRenderbufferEXT(invalid attachment %s)",
2235                  _mesa_lookup_enum_by_nr(attachment));
2236      return;
2237   }
2238
2239   if (renderbuffer) {
2240      rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2241      if (!rb) {
2242	 _mesa_error(ctx, GL_INVALID_OPERATION,
2243		     "glFramebufferRenderbufferEXT(non-existant"
2244                     " renderbuffer %u)", renderbuffer);
2245	 return;
2246      }
2247      else if (rb == &DummyRenderbuffer) {
2248         /* This is what NVIDIA does */
2249	 _mesa_error(ctx, GL_INVALID_VALUE,
2250		     "glFramebufferRenderbufferEXT(renderbuffer %u)",
2251                     renderbuffer);
2252	 return;
2253      }
2254   }
2255   else {
2256      /* remove renderbuffer attachment */
2257      rb = NULL;
2258   }
2259
2260   if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2261       rb && rb->Format != MESA_FORMAT_NONE) {
2262      /* make sure the renderbuffer is a depth/stencil format */
2263      const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
2264      if (baseFormat != GL_DEPTH_STENCIL) {
2265         _mesa_error(ctx, GL_INVALID_OPERATION,
2266                     "glFramebufferRenderbufferEXT(renderbuffer"
2267                     " is not DEPTH_STENCIL format)");
2268         return;
2269      }
2270   }
2271
2272
2273   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2274
2275   assert(ctx->Driver.FramebufferRenderbuffer);
2276   ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
2277
2278   /* Some subsequent GL commands may depend on the framebuffer's visual
2279    * after the binding is updated.  Update visual info now.
2280    */
2281   _mesa_update_framebuffer_visual(ctx, fb);
2282}
2283
2284
2285void GLAPIENTRY
2286_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
2287                                             GLenum pname, GLint *params)
2288{
2289   const struct gl_renderbuffer_attachment *att;
2290   struct gl_framebuffer *buffer;
2291   GLenum err;
2292   GET_CURRENT_CONTEXT(ctx);
2293
2294   ASSERT_OUTSIDE_BEGIN_END(ctx);
2295
2296   /* The error differs in GL and GLES. */
2297   err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
2298
2299   buffer = get_framebuffer_target(ctx, target);
2300   if (!buffer) {
2301      _mesa_error(ctx, GL_INVALID_ENUM,
2302                  "glGetFramebufferAttachmentParameterivEXT(target)");
2303      return;
2304   }
2305
2306   if (_mesa_is_winsys_fbo(buffer)) {
2307      /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
2308       * says:
2309       *
2310       *     "If the framebuffer currently bound to target is zero, then
2311       *     INVALID_OPERATION is generated."
2312       *
2313       * The EXT_framebuffer_object spec has the same wording, and the
2314       * OES_framebuffer_object spec refers to the EXT_framebuffer_object
2315       * spec.
2316       */
2317      if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object) {
2318	 _mesa_error(ctx, GL_INVALID_OPERATION,
2319		     "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
2320	 return;
2321      }
2322      /* the default / window-system FBO */
2323      att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
2324   }
2325   else {
2326      /* user-created framebuffer FBO */
2327      att = _mesa_get_attachment(ctx, buffer, attachment);
2328   }
2329
2330   if (att == NULL) {
2331      _mesa_error(ctx, GL_INVALID_ENUM,
2332                  "glGetFramebufferAttachmentParameterivEXT(attachment)");
2333      return;
2334   }
2335
2336   if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2337      /* the depth and stencil attachments must point to the same buffer */
2338      const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
2339      depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
2340      stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
2341      if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
2342         _mesa_error(ctx, GL_INVALID_OPERATION,
2343                     "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
2344                     " attachments differ)");
2345         return;
2346      }
2347   }
2348
2349   /* No need to flush here */
2350
2351   switch (pname) {
2352   case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
2353      *params = _mesa_is_winsys_fbo(buffer)
2354         ? GL_FRAMEBUFFER_DEFAULT : att->Type;
2355      return;
2356   case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
2357      if (att->Type == GL_RENDERBUFFER_EXT) {
2358	 *params = att->Renderbuffer->Name;
2359      }
2360      else if (att->Type == GL_TEXTURE) {
2361	 *params = att->Texture->Name;
2362      }
2363      else {
2364         assert(att->Type == GL_NONE);
2365         if (_mesa_is_desktop_gl(ctx)) {
2366            *params = 0;
2367         } else {
2368            _mesa_error(ctx, GL_INVALID_ENUM,
2369                        "glGetFramebufferAttachmentParameterivEXT(pname)");
2370         }
2371      }
2372      return;
2373   case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
2374      if (att->Type == GL_TEXTURE) {
2375	 *params = att->TextureLevel;
2376      }
2377      else if (att->Type == GL_NONE) {
2378         _mesa_error(ctx, err,
2379                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2380      }
2381      else {
2382	 _mesa_error(ctx, GL_INVALID_ENUM,
2383		     "glGetFramebufferAttachmentParameterivEXT(pname)");
2384      }
2385      return;
2386   case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
2387      if (att->Type == GL_TEXTURE) {
2388         if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
2389            *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
2390         }
2391         else {
2392            *params = 0;
2393         }
2394      }
2395      else if (att->Type == GL_NONE) {
2396         _mesa_error(ctx, err,
2397                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2398      }
2399      else {
2400	 _mesa_error(ctx, GL_INVALID_ENUM,
2401		     "glGetFramebufferAttachmentParameterivEXT(pname)");
2402      }
2403      return;
2404   case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
2405      if (att->Type == GL_TEXTURE) {
2406         if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
2407            *params = att->Zoffset;
2408         }
2409         else {
2410            *params = 0;
2411         }
2412      }
2413      else if (att->Type == GL_NONE) {
2414         _mesa_error(ctx, err,
2415                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2416      }
2417      else {
2418	 _mesa_error(ctx, GL_INVALID_ENUM,
2419		     "glGetFramebufferAttachmentParameterivEXT(pname)");
2420      }
2421      return;
2422   case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2423      if (!ctx->Extensions.ARB_framebuffer_object) {
2424         _mesa_error(ctx, GL_INVALID_ENUM,
2425                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2426      }
2427      else if (att->Type == GL_NONE) {
2428         _mesa_error(ctx, err,
2429                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2430      }
2431      else {
2432         if (ctx->Extensions.EXT_framebuffer_sRGB) {
2433            *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
2434         }
2435         else {
2436            /* According to ARB_framebuffer_sRGB, we should return LINEAR
2437             * if the sRGB conversion is unsupported. */
2438            *params = GL_LINEAR;
2439         }
2440      }
2441      return;
2442   case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
2443      if (!ctx->Extensions.ARB_framebuffer_object) {
2444         _mesa_error(ctx, GL_INVALID_ENUM,
2445                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2446         return;
2447      }
2448      else if (att->Type == GL_NONE) {
2449         _mesa_error(ctx, err,
2450                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2451      }
2452      else {
2453         gl_format format = att->Renderbuffer->Format;
2454         if (format == MESA_FORMAT_S8) {
2455            /* special cases */
2456            *params = GL_INDEX;
2457         }
2458         else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) {
2459            /* depends on the attachment parameter */
2460            if (attachment == GL_STENCIL_ATTACHMENT) {
2461               *params = GL_INDEX;
2462            }
2463            else {
2464               *params = GL_FLOAT;
2465            }
2466         }
2467         else {
2468            *params = _mesa_get_format_datatype(format);
2469         }
2470      }
2471      return;
2472   case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2473   case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2474   case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2475   case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2476   case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2477   case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2478      if (!ctx->Extensions.ARB_framebuffer_object) {
2479         _mesa_error(ctx, GL_INVALID_ENUM,
2480                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2481      }
2482      else if (att->Type == GL_NONE) {
2483         _mesa_error(ctx, err,
2484                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2485      }
2486      else if (att->Texture) {
2487         const struct gl_texture_image *texImage =
2488            _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
2489                                   att->TextureLevel);
2490         if (texImage) {
2491            *params = get_component_bits(pname, texImage->_BaseFormat,
2492                                         texImage->TexFormat);
2493         }
2494         else {
2495            *params = 0;
2496         }
2497      }
2498      else if (att->Renderbuffer) {
2499         *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
2500                                      att->Renderbuffer->Format);
2501      }
2502      else {
2503         _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
2504                       " invalid FBO attachment structure");
2505      }
2506      return;
2507   default:
2508      _mesa_error(ctx, GL_INVALID_ENUM,
2509                  "glGetFramebufferAttachmentParameterivEXT(pname)");
2510      return;
2511   }
2512}
2513
2514
2515void GLAPIENTRY
2516_mesa_GenerateMipmapEXT(GLenum target)
2517{
2518   struct gl_texture_image *srcImage;
2519   struct gl_texture_object *texObj;
2520   GLboolean error;
2521
2522   GET_CURRENT_CONTEXT(ctx);
2523
2524   ASSERT_OUTSIDE_BEGIN_END(ctx);
2525   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2526
2527   switch (target) {
2528   case GL_TEXTURE_1D:
2529   case GL_TEXTURE_2D:
2530   case GL_TEXTURE_3D:
2531      error = GL_FALSE;
2532      break;
2533   case GL_TEXTURE_CUBE_MAP:
2534      error = !ctx->Extensions.ARB_texture_cube_map;
2535      break;
2536   case GL_TEXTURE_1D_ARRAY:
2537   case GL_TEXTURE_2D_ARRAY:
2538      error = !ctx->Extensions.EXT_texture_array;
2539      break;
2540   default:
2541      error = GL_TRUE;
2542   }
2543
2544   if (error) {
2545      _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)",
2546                  _mesa_lookup_enum_by_nr(target));
2547      return;
2548   }
2549
2550   texObj = _mesa_get_current_tex_object(ctx, target);
2551
2552   if (texObj->BaseLevel >= texObj->MaxLevel) {
2553      /* nothing to do */
2554      return;
2555   }
2556
2557   if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
2558       !_mesa_cube_complete(texObj)) {
2559      _mesa_error(ctx, GL_INVALID_OPERATION,
2560                  "glGenerateMipmap(incomplete cube map)");
2561      return;
2562   }
2563
2564   _mesa_lock_texture(ctx, texObj);
2565
2566   srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
2567   if (!srcImage) {
2568      _mesa_unlock_texture(ctx, texObj);
2569      _mesa_error(ctx, GL_INVALID_OPERATION,
2570                  "glGenerateMipmap(zero size base image)");
2571      return;
2572   }
2573
2574   if (target == GL_TEXTURE_CUBE_MAP) {
2575      GLuint face;
2576      for (face = 0; face < 6; face++)
2577	 ctx->Driver.GenerateMipmap(ctx,
2578				    GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
2579				    texObj);
2580   }
2581   else {
2582      ctx->Driver.GenerateMipmap(ctx, target, texObj);
2583   }
2584   _mesa_unlock_texture(ctx, texObj);
2585}
2586
2587
2588#if FEATURE_EXT_framebuffer_blit
2589
2590static const struct gl_renderbuffer_attachment *
2591find_attachment(const struct gl_framebuffer *fb,
2592                const struct gl_renderbuffer *rb)
2593{
2594   GLuint i;
2595   for (i = 0; i < Elements(fb->Attachment); i++) {
2596      if (fb->Attachment[i].Renderbuffer == rb)
2597         return &fb->Attachment[i];
2598   }
2599   return NULL;
2600}
2601
2602
2603/**
2604 * Helper function for checking if the datatypes of color buffers are
2605 * compatible for glBlitFramebuffer.  From the 3.1 spec, page 198:
2606 *
2607 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
2608 *  and any of the following conditions hold:
2609 *   - The read buffer contains fixed-point or floating-point values and any
2610 *     draw buffer contains neither fixed-point nor floating-point values.
2611 *   - The read buffer contains unsigned integer values and any draw buffer
2612 *     does not contain unsigned integer values.
2613 *   - The read buffer contains signed integer values and any draw buffer
2614 *     does not contain signed integer values."
2615 */
2616static GLboolean
2617compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat)
2618{
2619   GLenum srcType = _mesa_get_format_datatype(srcFormat);
2620   GLenum dstType = _mesa_get_format_datatype(dstFormat);
2621
2622   if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
2623      assert(srcType == GL_UNSIGNED_NORMALIZED ||
2624             srcType == GL_SIGNED_NORMALIZED ||
2625             srcType == GL_FLOAT);
2626      /* Boil any of those types down to GL_FLOAT */
2627      srcType = GL_FLOAT;
2628   }
2629
2630   if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
2631      assert(dstType == GL_UNSIGNED_NORMALIZED ||
2632             dstType == GL_SIGNED_NORMALIZED ||
2633             dstType == GL_FLOAT);
2634      /* Boil any of those types down to GL_FLOAT */
2635      dstType = GL_FLOAT;
2636   }
2637
2638   return srcType == dstType;
2639}
2640
2641
2642/**
2643 * Return the equivalent non-generic internal format.
2644 * This is useful for comparing whether two internal formats are semantically
2645 * equivalent.
2646 */
2647static GLenum
2648get_nongeneric_internalformat(GLenum format)
2649{
2650   switch (format) {
2651      /* GL 1.1 formats. */
2652      case 4:
2653      case GL_RGBA:
2654         return GL_RGBA8;
2655
2656      case 3:
2657      case GL_RGB:
2658         return GL_RGB8;
2659
2660      case 2:
2661      case GL_LUMINANCE_ALPHA:
2662         return GL_LUMINANCE8_ALPHA8;
2663
2664      case 1:
2665      case GL_LUMINANCE:
2666         return GL_LUMINANCE8;
2667
2668      case GL_ALPHA:
2669         return GL_ALPHA8;
2670
2671      case GL_INTENSITY:
2672         return GL_INTENSITY8;
2673
2674      /* GL_ARB_texture_rg */
2675      case GL_RED:
2676         return GL_R8;
2677
2678      case GL_RG:
2679         return GL_RG8;
2680
2681      /* GL_EXT_texture_sRGB */
2682      case GL_SRGB:
2683         return GL_SRGB8;
2684
2685      case GL_SRGB_ALPHA:
2686         return GL_SRGB8_ALPHA8;
2687
2688      case GL_SLUMINANCE:
2689         return GL_SLUMINANCE8;
2690
2691      case GL_SLUMINANCE_ALPHA:
2692         return GL_SLUMINANCE8_ALPHA8;
2693
2694      /* GL_EXT_texture_snorm */
2695      case GL_RGBA_SNORM:
2696         return GL_RGBA8_SNORM;
2697
2698      case GL_RGB_SNORM:
2699         return GL_RGB8_SNORM;
2700
2701      case GL_RG_SNORM:
2702         return GL_RG8_SNORM;
2703
2704      case GL_RED_SNORM:
2705         return GL_R8_SNORM;
2706
2707      case GL_LUMINANCE_ALPHA_SNORM:
2708         return GL_LUMINANCE8_ALPHA8_SNORM;
2709
2710      case GL_LUMINANCE_SNORM:
2711         return GL_LUMINANCE8_SNORM;
2712
2713      case GL_ALPHA_SNORM:
2714         return GL_ALPHA8_SNORM;
2715
2716      case GL_INTENSITY_SNORM:
2717         return GL_INTENSITY8_SNORM;
2718
2719      default:
2720         return format;
2721   }
2722}
2723
2724
2725static GLboolean
2726compatible_resolve_formats(const struct gl_renderbuffer *colorReadRb,
2727                           const struct gl_renderbuffer *colorDrawRb)
2728{
2729   /* The simple case where we know the backing formats are the same.
2730    */
2731   if (colorReadRb->Format == colorDrawRb->Format) {
2732      return GL_TRUE;
2733   }
2734
2735   /* The Mesa formats are different, so we must check whether the internal
2736    * formats are compatible.
2737    *
2738    * Under some circumstances, the user may request e.g. two GL_RGBA8
2739    * textures and get two entirely different Mesa formats like RGBA8888 and
2740    * ARGB8888. Drivers behaving like that should be able to cope with
2741    * non-matching formats by themselves, because it's not the user's fault.
2742    */
2743   if (get_nongeneric_internalformat(colorReadRb->InternalFormat) ==
2744       get_nongeneric_internalformat(colorDrawRb->InternalFormat)) {
2745      return GL_TRUE;
2746   }
2747
2748   return GL_FALSE;
2749}
2750
2751
2752/**
2753 * Blit rectangular region, optionally from one framebuffer to another.
2754 *
2755 * Note, if the src buffer is multisampled and the dest is not, this is
2756 * when the samples must be resolved to a single color.
2757 */
2758void GLAPIENTRY
2759_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
2760                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
2761                         GLbitfield mask, GLenum filter)
2762{
2763   const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
2764                                     GL_DEPTH_BUFFER_BIT |
2765                                     GL_STENCIL_BUFFER_BIT);
2766   const struct gl_framebuffer *readFb, *drawFb;
2767   const struct gl_renderbuffer *colorReadRb, *colorDrawRb;
2768   GET_CURRENT_CONTEXT(ctx);
2769
2770   ASSERT_OUTSIDE_BEGIN_END(ctx);
2771   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2772
2773   if (MESA_VERBOSE & VERBOSE_API)
2774      _mesa_debug(ctx,
2775                  "glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d, 0x%x, %s)\n",
2776                  srcX0, srcY0, srcX1, srcY1,
2777                  dstX0, dstY0, dstX1, dstY1,
2778                  mask, _mesa_lookup_enum_by_nr(filter));
2779
2780   if (ctx->NewState) {
2781      _mesa_update_state(ctx);
2782   }
2783
2784   readFb = ctx->ReadBuffer;
2785   drawFb = ctx->DrawBuffer;
2786
2787   if (!readFb || !drawFb) {
2788      /* This will normally never happen but someday we may want to
2789       * support MakeCurrent() with no drawables.
2790       */
2791      return;
2792   }
2793
2794   /* check for complete framebuffers */
2795   if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
2796       readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2797      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
2798                  "glBlitFramebufferEXT(incomplete draw/read buffers)");
2799      return;
2800   }
2801
2802   if (filter != GL_NEAREST && filter != GL_LINEAR) {
2803      _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
2804      return;
2805   }
2806
2807   if (mask & ~legalMaskBits) {
2808      _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
2809      return;
2810   }
2811
2812   /* depth/stencil must be blitted with nearest filtering */
2813   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
2814        && filter != GL_NEAREST) {
2815      _mesa_error(ctx, GL_INVALID_OPERATION,
2816             "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
2817      return;
2818   }
2819
2820   /* get color read/draw renderbuffers */
2821   if (mask & GL_COLOR_BUFFER_BIT) {
2822      colorReadRb = readFb->_ColorReadBuffer;
2823      colorDrawRb = drawFb->_ColorDrawBuffers[0];
2824
2825      /* From the EXT_framebuffer_object spec:
2826       *
2827       *     "If a buffer is specified in <mask> and does not exist in both
2828       *     the read and draw framebuffers, the corresponding bit is silently
2829       *     ignored."
2830       */
2831      if ((colorReadRb == NULL) || (colorDrawRb == NULL)) {
2832	 colorReadRb = colorDrawRb = NULL;
2833	 mask &= ~GL_COLOR_BUFFER_BIT;
2834      }
2835      else if (!compatible_color_datatypes(colorReadRb->Format,
2836                                           colorDrawRb->Format)) {
2837         _mesa_error(ctx, GL_INVALID_OPERATION,
2838                     "glBlitFramebufferEXT(color buffer datatypes mismatch)");
2839         return;
2840      }
2841   }
2842   else {
2843      colorReadRb = colorDrawRb = NULL;
2844   }
2845
2846   if (mask & GL_STENCIL_BUFFER_BIT) {
2847      struct gl_renderbuffer *readRb =
2848         readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
2849      struct gl_renderbuffer *drawRb =
2850         drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
2851
2852      /* From the EXT_framebuffer_object spec:
2853       *
2854       *     "If a buffer is specified in <mask> and does not exist in both
2855       *     the read and draw framebuffers, the corresponding bit is silently
2856       *     ignored."
2857       */
2858      if ((readRb == NULL) || (drawRb == NULL)) {
2859	 mask &= ~GL_STENCIL_BUFFER_BIT;
2860      }
2861      else if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
2862	       _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
2863	 /* There is no need to check the stencil datatype here, because
2864	  * there is only one: GL_UNSIGNED_INT.
2865	  */
2866         _mesa_error(ctx, GL_INVALID_OPERATION,
2867                     "glBlitFramebufferEXT(stencil buffer size mismatch)");
2868         return;
2869      }
2870   }
2871
2872   if (mask & GL_DEPTH_BUFFER_BIT) {
2873      struct gl_renderbuffer *readRb =
2874         readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
2875      struct gl_renderbuffer *drawRb =
2876         drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
2877
2878      /* From the EXT_framebuffer_object spec:
2879       *
2880       *     "If a buffer is specified in <mask> and does not exist in both
2881       *     the read and draw framebuffers, the corresponding bit is silently
2882       *     ignored."
2883       */
2884      if ((readRb == NULL) || (drawRb == NULL)) {
2885	 mask &= ~GL_DEPTH_BUFFER_BIT;
2886      }
2887      else if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
2888	        _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
2889	       (_mesa_get_format_datatype(readRb->Format) !=
2890		_mesa_get_format_datatype(drawRb->Format))) {
2891         _mesa_error(ctx, GL_INVALID_OPERATION,
2892                     "glBlitFramebufferEXT(depth buffer format mismatch)");
2893         return;
2894      }
2895   }
2896
2897   if (readFb->Visual.samples > 0 &&
2898       drawFb->Visual.samples > 0 &&
2899       readFb->Visual.samples != drawFb->Visual.samples) {
2900      _mesa_error(ctx, GL_INVALID_OPERATION,
2901                  "glBlitFramebufferEXT(mismatched samples)");
2902      return;
2903   }
2904
2905   /* extra checks for multisample copies... */
2906   if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
2907      /* src and dest region sizes must be the same */
2908      if (srcX1 - srcX0 != dstX1 - dstX0 ||
2909          srcY1 - srcY0 != dstY1 - dstY0) {
2910         _mesa_error(ctx, GL_INVALID_OPERATION,
2911                "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
2912         return;
2913      }
2914
2915      /* color formats must match */
2916      if (colorReadRb &&
2917          colorDrawRb &&
2918          !compatible_resolve_formats(colorReadRb, colorDrawRb)) {
2919         _mesa_error(ctx, GL_INVALID_OPERATION,
2920                "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
2921         return;
2922      }
2923   }
2924
2925   if (filter == GL_LINEAR && (mask & GL_COLOR_BUFFER_BIT)) {
2926      /* 3.1 spec, page 199:
2927       * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
2928       * if filter is LINEAR and read buffer contains integer data."
2929       */
2930      GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
2931      if (type == GL_INT || type == GL_UNSIGNED_INT) {
2932         _mesa_error(ctx, GL_INVALID_OPERATION,
2933                     "glBlitFramebufferEXT(integer color type)");
2934         return;
2935      }
2936   }
2937
2938   if (!ctx->Extensions.EXT_framebuffer_blit) {
2939      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
2940      return;
2941   }
2942
2943   /* Debug code */
2944   if (DEBUG_BLIT) {
2945      printf("glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d,"
2946	     " 0x%x, 0x%x)\n",
2947	     srcX0, srcY0, srcX1, srcY1,
2948	     dstX0, dstY0, dstX1, dstY1,
2949	     mask, filter);
2950      if (colorReadRb) {
2951         const struct gl_renderbuffer_attachment *att;
2952
2953         att = find_attachment(readFb, colorReadRb);
2954         printf("  Src FBO %u  RB %u (%dx%d)  ",
2955		readFb->Name, colorReadRb->Name,
2956		colorReadRb->Width, colorReadRb->Height);
2957         if (att && att->Texture) {
2958            printf("Tex %u  tgt 0x%x  level %u  face %u",
2959		   att->Texture->Name,
2960		   att->Texture->Target,
2961		   att->TextureLevel,
2962		   att->CubeMapFace);
2963         }
2964         printf("\n");
2965
2966         att = find_attachment(drawFb, colorDrawRb);
2967         printf("  Dst FBO %u  RB %u (%dx%d)  ",
2968		drawFb->Name, colorDrawRb->Name,
2969		colorDrawRb->Width, colorDrawRb->Height);
2970         if (att && att->Texture) {
2971            printf("Tex %u  tgt 0x%x  level %u  face %u",
2972		   att->Texture->Name,
2973		   att->Texture->Target,
2974		   att->TextureLevel,
2975		   att->CubeMapFace);
2976         }
2977         printf("\n");
2978      }
2979   }
2980
2981   if (!mask) {
2982      return;
2983   }
2984
2985   ASSERT(ctx->Driver.BlitFramebuffer);
2986   ctx->Driver.BlitFramebuffer(ctx,
2987                               srcX0, srcY0, srcX1, srcY1,
2988                               dstX0, dstY0, dstX1, dstY1,
2989                               mask, filter);
2990}
2991#endif /* FEATURE_EXT_framebuffer_blit */
2992
2993
2994#if FEATURE_ARB_geometry_shader4
2995void GLAPIENTRY
2996_mesa_FramebufferTextureARB(GLenum target, GLenum attachment,
2997                            GLuint texture, GLint level)
2998{
2999   GET_CURRENT_CONTEXT(ctx);
3000   _mesa_error(ctx, GL_INVALID_OPERATION,
3001               "glFramebufferTextureARB "
3002               "not implemented!");
3003}
3004
3005
3006void GLAPIENTRY
3007_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment,
3008                                GLuint texture, GLint level, GLenum face)
3009{
3010   GET_CURRENT_CONTEXT(ctx);
3011   _mesa_error(ctx, GL_INVALID_OPERATION,
3012               "glFramebufferTextureFaceARB "
3013               "not implemented!");
3014}
3015#endif /* FEATURE_ARB_geometry_shader4 */
3016
3017static void
3018invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
3019                               const GLenum *attachments, GLint x, GLint y,
3020                               GLsizei width, GLsizei height, const char *name)
3021{
3022   int i;
3023   struct gl_framebuffer *fb;
3024   GET_CURRENT_CONTEXT(ctx);
3025
3026   ASSERT_OUTSIDE_BEGIN_END(ctx);
3027
3028   fb = get_framebuffer_target(ctx, target);
3029   if (!fb) {
3030      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
3031      return;
3032   }
3033
3034   if (numAttachments < 0) {
3035      _mesa_error(ctx, GL_INVALID_VALUE,
3036                  "%s(numAttachments < 0)", name);
3037      return;
3038   }
3039
3040   /* The GL_ARB_invalidate_subdata spec says:
3041    *
3042    *     "If an attachment is specified that does not exist in the
3043    *     framebuffer bound to <target>, it is ignored."
3044    *
3045    * It also says:
3046    *
3047    *     "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
3048    *     or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
3049    *     INVALID_OPERATION is generated."
3050    *
3051    * No mention is made of GL_AUXi being out of range.  Therefore, we allow
3052    * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
3053    * set of retrictions).
3054    */
3055   for (i = 0; i < numAttachments; i++) {
3056      if (_mesa_is_winsys_fbo(fb)) {
3057         switch (attachments[i]) {
3058         case GL_ACCUM:
3059         case GL_AUX0:
3060         case GL_AUX1:
3061         case GL_AUX2:
3062         case GL_AUX3:
3063            /* Accumulation buffers and auxilary buffers were removed in
3064             * OpenGL 3.1, and they never existed in OpenGL ES.
3065             */
3066            if (ctx->API != API_OPENGL)
3067               goto invalid_enum;
3068            break;
3069         case GL_COLOR:
3070         case GL_DEPTH:
3071         case GL_STENCIL:
3072            break;
3073         case GL_BACK_LEFT:
3074         case GL_BACK_RIGHT:
3075         case GL_FRONT_LEFT:
3076         case GL_FRONT_RIGHT:
3077            if (!_mesa_is_desktop_gl(ctx))
3078               goto invalid_enum;
3079            break;
3080         default:
3081            goto invalid_enum;
3082         }
3083      } else {
3084         switch (attachments[i]) {
3085         case GL_DEPTH_ATTACHMENT:
3086         case GL_STENCIL_ATTACHMENT:
3087            break;
3088         case GL_COLOR_ATTACHMENT0:
3089         case GL_COLOR_ATTACHMENT1:
3090         case GL_COLOR_ATTACHMENT2:
3091         case GL_COLOR_ATTACHMENT3:
3092         case GL_COLOR_ATTACHMENT4:
3093         case GL_COLOR_ATTACHMENT5:
3094         case GL_COLOR_ATTACHMENT6:
3095         case GL_COLOR_ATTACHMENT7:
3096         case GL_COLOR_ATTACHMENT8:
3097         case GL_COLOR_ATTACHMENT9:
3098         case GL_COLOR_ATTACHMENT10:
3099         case GL_COLOR_ATTACHMENT11:
3100         case GL_COLOR_ATTACHMENT12:
3101         case GL_COLOR_ATTACHMENT13:
3102         case GL_COLOR_ATTACHMENT14:
3103         case GL_COLOR_ATTACHMENT15: {
3104            const int k = attachments[i] - GL_COLOR_ATTACHMENT0;
3105            if (k >= ctx->Const.MaxColorAttachments) {
3106               _mesa_error(ctx, GL_INVALID_OPERATION,
3107                           "%s(attachment >= max. color attachments)", name);
3108               return;
3109            }
3110         }
3111         default:
3112            goto invalid_enum;
3113         }
3114      }
3115   }
3116
3117   /* We don't actually do anything for this yet.  Just return after
3118    * validating the parameters and generating the required errors.
3119    */
3120   return;
3121
3122invalid_enum:
3123   _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
3124   return;
3125}
3126
3127void GLAPIENTRY
3128_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
3129                               const GLenum *attachments, GLint x, GLint y,
3130                               GLsizei width, GLsizei height)
3131{
3132   invalidate_framebuffer_storage(target, numAttachments, attachments,
3133                                  x, y, width, height,
3134                                  "glInvalidateSubFramebuffer");
3135}
3136
3137void GLAPIENTRY
3138_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
3139                            const GLenum *attachments)
3140{
3141   /* The GL_ARB_invalidate_subdata spec says:
3142    *
3143    *     "The command
3144    *
3145    *        void InvalidateFramebuffer(enum target,
3146    *                                   sizei numAttachments,
3147    *                                   const enum *attachments);
3148    *
3149    *     is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
3150    *     <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
3151    *     <MAX_VIEWPORT_DIMS[1]> respectively."
3152    */
3153   invalidate_framebuffer_storage(target, numAttachments, attachments,
3154                                  0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
3155                                  "glInvalidateFramebuffer");
3156}
3157