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