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