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