OSDN Git Service

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