• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5  * Copyright (C) 1999-2009  VMware, Inc.  All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * 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 #include <stdbool.h>
35 
36 #include "buffers.h"
37 #include "context.h"
38 #include "enums.h"
39 #include "fbobject.h"
40 #include "formats.h"
41 #include "framebuffer.h"
42 #include "glformats.h"
43 #include "hash.h"
44 #include "macros.h"
45 #include "multisample.h"
46 #include "mtypes.h"
47 #include "renderbuffer.h"
48 #include "state.h"
49 #include "teximage.h"
50 #include "texobj.h"
51 
52 
53 /**
54  * Notes:
55  *
56  * None of the GL_EXT_framebuffer_object functions are compiled into
57  * display lists.
58  */
59 
60 
61 
62 /*
63  * When glGenRender/FramebuffersEXT() is called we insert pointers to
64  * these placeholder objects into the hash table.
65  * Later, when the object ID is first bound, we replace the placeholder
66  * with the real frame/renderbuffer.
67  */
68 static struct gl_framebuffer DummyFramebuffer;
69 static struct gl_renderbuffer DummyRenderbuffer;
70 
71 /* We bind this framebuffer when applications pass a NULL
72  * drawable/surface in make current. */
73 static struct gl_framebuffer IncompleteFramebuffer;
74 
75 
76 static void
delete_dummy_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)77 delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
78 {
79    /* no op */
80 }
81 
82 static void
delete_dummy_framebuffer(struct gl_framebuffer * fb)83 delete_dummy_framebuffer(struct gl_framebuffer *fb)
84 {
85    /* no op */
86 }
87 
88 
89 void
_mesa_init_fbobjects(struct gl_context * ctx)90 _mesa_init_fbobjects(struct gl_context *ctx)
91 {
92    simple_mtx_init(&DummyFramebuffer.Mutex, mtx_plain);
93    simple_mtx_init(&DummyRenderbuffer.Mutex, mtx_plain);
94    simple_mtx_init(&IncompleteFramebuffer.Mutex, mtx_plain);
95    DummyFramebuffer.Delete = delete_dummy_framebuffer;
96    DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
97    IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
98 }
99 
100 struct gl_framebuffer *
_mesa_get_incomplete_framebuffer(void)101 _mesa_get_incomplete_framebuffer(void)
102 {
103    return &IncompleteFramebuffer;
104 }
105 
106 /**
107  * Helper routine for getting a gl_renderbuffer.
108  */
109 struct gl_renderbuffer *
_mesa_lookup_renderbuffer(struct gl_context * ctx,GLuint id)110 _mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
111 {
112    struct gl_renderbuffer *rb;
113 
114    if (id == 0)
115       return NULL;
116 
117    rb = (struct gl_renderbuffer *)
118       _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
119    return rb;
120 }
121 
122 
123 /**
124  * A convenience function for direct state access that throws
125  * GL_INVALID_OPERATION if the renderbuffer doesn't exist.
126  */
127 struct gl_renderbuffer *
_mesa_lookup_renderbuffer_err(struct gl_context * ctx,GLuint id,const char * func)128 _mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
129                               const char *func)
130 {
131    struct gl_renderbuffer *rb;
132 
133    rb = _mesa_lookup_renderbuffer(ctx, id);
134    if (!rb || rb == &DummyRenderbuffer) {
135       _mesa_error(ctx, GL_INVALID_OPERATION,
136                   "%s(non-existent renderbuffer %u)", func, id);
137       return NULL;
138    }
139 
140    return rb;
141 }
142 
143 
144 /**
145  * Helper routine for getting a gl_framebuffer.
146  */
147 struct gl_framebuffer *
_mesa_lookup_framebuffer(struct gl_context * ctx,GLuint id)148 _mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
149 {
150    struct gl_framebuffer *fb;
151 
152    if (id == 0)
153       return NULL;
154 
155    fb = (struct gl_framebuffer *)
156       _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
157    return fb;
158 }
159 
160 
161 /**
162  * A convenience function for direct state access that throws
163  * GL_INVALID_OPERATION if the framebuffer doesn't exist.
164  */
165 struct gl_framebuffer *
_mesa_lookup_framebuffer_err(struct gl_context * ctx,GLuint id,const char * func)166 _mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
167                              const char *func)
168 {
169    struct gl_framebuffer *fb;
170 
171    fb = _mesa_lookup_framebuffer(ctx, id);
172    if (!fb || fb == &DummyFramebuffer) {
173       _mesa_error(ctx, GL_INVALID_OPERATION,
174                   "%s(non-existent framebuffer %u)", func, id);
175       return NULL;
176    }
177 
178    return fb;
179 }
180 
181 
182 /**
183  * Mark the given framebuffer as invalid.  This will force the
184  * test for framebuffer completeness to be done before the framebuffer
185  * is used.
186  */
187 static void
invalidate_framebuffer(struct gl_framebuffer * fb)188 invalidate_framebuffer(struct gl_framebuffer *fb)
189 {
190    fb->_Status = 0; /* "indeterminate" */
191 }
192 
193 
194 /**
195  * Return the gl_framebuffer object which corresponds to the given
196  * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
197  * Check support for GL_EXT_framebuffer_blit to determine if certain
198  * targets are legal.
199  * \return gl_framebuffer pointer or NULL if target is illegal
200  */
201 static struct gl_framebuffer *
get_framebuffer_target(struct gl_context * ctx,GLenum target)202 get_framebuffer_target(struct gl_context *ctx, GLenum target)
203 {
204    bool have_fb_blit = _mesa_is_gles3(ctx) || _mesa_is_desktop_gl(ctx);
205    switch (target) {
206    case GL_DRAW_FRAMEBUFFER:
207       return have_fb_blit ? ctx->DrawBuffer : NULL;
208    case GL_READ_FRAMEBUFFER:
209       return have_fb_blit ? ctx->ReadBuffer : NULL;
210    case GL_FRAMEBUFFER_EXT:
211       return ctx->DrawBuffer;
212    default:
213       return NULL;
214    }
215 }
216 
217 
218 /**
219  * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
220  * gl_renderbuffer_attachment object.
221  * This function is only used for user-created FB objects, not the
222  * default / window-system FB object.
223  * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
224  * the depth buffer attachment point.
225  * Returns if the attachment is a GL_COLOR_ATTACHMENTm_EXT on
226  * is_color_attachment, because several callers would return different errors
227  * if they don't find the attachment.
228  */
229 static struct gl_renderbuffer_attachment *
get_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,bool * is_color_attachment)230 get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
231                GLenum attachment, bool *is_color_attachment)
232 {
233    GLuint i;
234 
235    assert(_mesa_is_user_fbo(fb));
236 
237    if (is_color_attachment)
238       *is_color_attachment = false;
239 
240    switch (attachment) {
241    case GL_COLOR_ATTACHMENT0_EXT:
242    case GL_COLOR_ATTACHMENT1_EXT:
243    case GL_COLOR_ATTACHMENT2_EXT:
244    case GL_COLOR_ATTACHMENT3_EXT:
245    case GL_COLOR_ATTACHMENT4_EXT:
246    case GL_COLOR_ATTACHMENT5_EXT:
247    case GL_COLOR_ATTACHMENT6_EXT:
248    case GL_COLOR_ATTACHMENT7_EXT:
249    case GL_COLOR_ATTACHMENT8_EXT:
250    case GL_COLOR_ATTACHMENT9_EXT:
251    case GL_COLOR_ATTACHMENT10_EXT:
252    case GL_COLOR_ATTACHMENT11_EXT:
253    case GL_COLOR_ATTACHMENT12_EXT:
254    case GL_COLOR_ATTACHMENT13_EXT:
255    case GL_COLOR_ATTACHMENT14_EXT:
256    case GL_COLOR_ATTACHMENT15_EXT:
257       if (is_color_attachment)
258          *is_color_attachment = true;
259       /* Only OpenGL ES 1.x forbids color attachments other than
260        * GL_COLOR_ATTACHMENT0.  For all other APIs the limit set by the
261        * hardware is used.
262        */
263       i = attachment - GL_COLOR_ATTACHMENT0_EXT;
264       if (i >= ctx->Const.MaxColorAttachments
265           || (i > 0 && ctx->API == API_OPENGLES)) {
266          return NULL;
267       }
268       return &fb->Attachment[BUFFER_COLOR0 + i];
269    case GL_DEPTH_STENCIL_ATTACHMENT:
270       if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
271          return NULL;
272       /* fall-through */
273    case GL_DEPTH_ATTACHMENT_EXT:
274       return &fb->Attachment[BUFFER_DEPTH];
275    case GL_STENCIL_ATTACHMENT_EXT:
276       return &fb->Attachment[BUFFER_STENCIL];
277    default:
278       return NULL;
279    }
280 }
281 
282 
283 /**
284  * As above, but only used for getting attachments of the default /
285  * window-system framebuffer (not user-created framebuffer objects).
286  */
287 static struct gl_renderbuffer_attachment *
get_fb0_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment)288 get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
289                    GLenum attachment)
290 {
291    assert(_mesa_is_winsys_fbo(fb));
292 
293    if (_mesa_is_gles3(ctx)) {
294       assert(attachment == GL_BACK ||
295              attachment == GL_DEPTH ||
296              attachment == GL_STENCIL);
297       switch (attachment) {
298       case GL_BACK:
299          /* Since there is no stereo rendering in ES 3.0, only return the
300           * LEFT bits.
301           */
302          if (ctx->DrawBuffer->Visual.doubleBufferMode)
303             return &fb->Attachment[BUFFER_BACK_LEFT];
304          return &fb->Attachment[BUFFER_FRONT_LEFT];
305       case GL_DEPTH:
306          return &fb->Attachment[BUFFER_DEPTH];
307       case GL_STENCIL:
308          return &fb->Attachment[BUFFER_STENCIL];
309       }
310    }
311 
312    switch (attachment) {
313    case GL_FRONT_LEFT:
314       /* Front buffers can be allocated on the first use, but
315        * glGetFramebufferAttachmentParameteriv must work even if that
316        * allocation hasn't happened yet. In such case, use the back buffer,
317        * which should be the same.
318        */
319       if (fb->Attachment[BUFFER_FRONT_LEFT].Type == GL_NONE)
320          return &fb->Attachment[BUFFER_BACK_LEFT];
321       else
322          return &fb->Attachment[BUFFER_FRONT_LEFT];
323    case GL_FRONT_RIGHT:
324       /* Same as above. */
325       if (fb->Attachment[BUFFER_FRONT_RIGHT].Type == GL_NONE)
326          return &fb->Attachment[BUFFER_BACK_RIGHT];
327       else
328          return &fb->Attachment[BUFFER_FRONT_RIGHT];
329    case GL_BACK_LEFT:
330       return &fb->Attachment[BUFFER_BACK_LEFT];
331    case GL_BACK_RIGHT:
332       return &fb->Attachment[BUFFER_BACK_RIGHT];
333    case GL_BACK:
334       /* The ARB_ES3_1_compatibility spec says:
335        *
336        *    "Since this command can only query a single framebuffer
337        *     attachment, BACK is equivalent to BACK_LEFT."
338        */
339       if (ctx->Extensions.ARB_ES3_1_compatibility)
340          return &fb->Attachment[BUFFER_BACK_LEFT];
341       return NULL;
342    case GL_AUX0:
343       if (fb->Visual.numAuxBuffers == 1) {
344          return &fb->Attachment[BUFFER_AUX0];
345       }
346       return NULL;
347 
348    /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
349     *
350     *     "If the default framebuffer is bound to target, then attachment must
351     *     be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
352     *     identifying a color buffer; DEPTH, identifying the depth buffer; or
353     *     STENCIL, identifying the stencil buffer."
354     *
355     * Revision #34 of the ARB_framebuffer_object spec has essentially the same
356     * language.  However, revision #33 of the ARB_framebuffer_object spec
357     * says:
358     *
359     *     "If the default framebuffer is bound to <target>, then <attachment>
360     *     must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
361     *     DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
362     *     depth buffer, or the stencil buffer, and <pname> may be
363     *     FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
364     *     FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
365     *
366     * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
367     * from glext.h, so shipping apps should not use those values.
368     *
369     * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
370     * support queries of the window system FBO.
371     */
372    case GL_DEPTH:
373       return &fb->Attachment[BUFFER_DEPTH];
374    case GL_STENCIL:
375       return &fb->Attachment[BUFFER_STENCIL];
376    default:
377       return NULL;
378    }
379 }
380 
381 
382 
383 /**
384  * Remove any texture or renderbuffer attached to the given attachment
385  * point.  Update reference counts, etc.
386  */
387 static void
remove_attachment(struct gl_context * ctx,struct gl_renderbuffer_attachment * att)388 remove_attachment(struct gl_context *ctx,
389                   struct gl_renderbuffer_attachment *att)
390 {
391    struct gl_renderbuffer *rb = att->Renderbuffer;
392 
393    /* tell driver that we're done rendering to this texture. */
394    if (rb && rb->NeedsFinishRenderTexture)
395       ctx->Driver.FinishRenderTexture(ctx, rb);
396 
397    if (att->Type == GL_TEXTURE) {
398       assert(att->Texture);
399       _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
400       assert(!att->Texture);
401    }
402    if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
403       assert(!att->Texture);
404       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
405       assert(!att->Renderbuffer);
406    }
407    att->Type = GL_NONE;
408    att->Complete = GL_TRUE;
409 }
410 
411 /**
412  * Verify a couple error conditions that will lead to an incomplete FBO and
413  * may cause problems for the driver's RenderTexture path.
414  */
415 static bool
driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment * att)416 driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
417 {
418    const struct gl_texture_image *const texImage =
419       att->Texture->Image[att->CubeMapFace][att->TextureLevel];
420 
421    if (!texImage ||
422        texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
423       return false;
424 
425    if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
426         && att->Zoffset >= texImage->Height)
427        || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
428            && att->Zoffset >= texImage->Depth))
429       return false;
430 
431    return true;
432 }
433 
434 /**
435  * Create a renderbuffer which will be set up by the driver to wrap the
436  * texture image slice.
437  *
438  * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
439  * to share most of their framebuffer rendering code between winsys,
440  * renderbuffer, and texture attachments.
441  *
442  * The allocated renderbuffer uses a non-zero Name so that drivers can check
443  * it for determining vertical orientation, but we use ~0 to make it fairly
444  * unambiguous with actual user (non-texture) renderbuffers.
445  */
446 void
_mesa_update_texture_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,struct gl_renderbuffer_attachment * att)447 _mesa_update_texture_renderbuffer(struct gl_context *ctx,
448                                   struct gl_framebuffer *fb,
449                                   struct gl_renderbuffer_attachment *att)
450 {
451    struct gl_texture_image *texImage;
452    struct gl_renderbuffer *rb;
453 
454    texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
455 
456    rb = att->Renderbuffer;
457    if (!rb) {
458       rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
459       if (!rb) {
460          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
461          return;
462       }
463       att->Renderbuffer = rb;
464 
465       /* This can't get called on a texture renderbuffer, so set it to NULL
466        * for clarity compared to user renderbuffers.
467        */
468       rb->AllocStorage = NULL;
469 
470       rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
471    }
472 
473    if (!texImage)
474       return;
475 
476    rb->_BaseFormat = texImage->_BaseFormat;
477    rb->Format = texImage->TexFormat;
478    rb->InternalFormat = texImage->InternalFormat;
479    rb->Width = texImage->Width2;
480    rb->Height = texImage->Height2;
481    rb->Depth = texImage->Depth2;
482    rb->NumSamples = texImage->NumSamples;
483    rb->TexImage = texImage;
484 
485    if (driver_RenderTexture_is_safe(att))
486       ctx->Driver.RenderTexture(ctx, fb, att);
487 }
488 
489 /**
490  * Bind a texture object to an attachment point.
491  * The previous binding, if any, will be removed first.
492  */
493 static void
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 layer,GLboolean layered)494 set_texture_attachment(struct gl_context *ctx,
495                        struct gl_framebuffer *fb,
496                        struct gl_renderbuffer_attachment *att,
497                        struct gl_texture_object *texObj,
498                        GLenum texTarget, GLuint level, GLuint layer,
499                        GLboolean layered)
500 {
501    struct gl_renderbuffer *rb = att->Renderbuffer;
502 
503    if (rb && rb->NeedsFinishRenderTexture)
504       ctx->Driver.FinishRenderTexture(ctx, rb);
505 
506    if (att->Texture == texObj) {
507       /* re-attaching same texture */
508       assert(att->Type == GL_TEXTURE);
509    }
510    else {
511       /* new attachment */
512       remove_attachment(ctx, att);
513       att->Type = GL_TEXTURE;
514       assert(!att->Texture);
515       _mesa_reference_texobj(&att->Texture, texObj);
516    }
517    invalidate_framebuffer(fb);
518 
519    /* always update these fields */
520    att->TextureLevel = level;
521    att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
522    att->Zoffset = layer;
523    att->Layered = layered;
524    att->Complete = GL_FALSE;
525 
526    _mesa_update_texture_renderbuffer(ctx, fb, att);
527 }
528 
529 
530 /**
531  * Bind a renderbuffer to an attachment point.
532  * The previous binding, if any, will be removed first.
533  */
534 static void
set_renderbuffer_attachment(struct gl_context * ctx,struct gl_renderbuffer_attachment * att,struct gl_renderbuffer * rb)535 set_renderbuffer_attachment(struct gl_context *ctx,
536                             struct gl_renderbuffer_attachment *att,
537                             struct gl_renderbuffer *rb)
538 {
539    /* XXX check if re-doing same attachment, exit early */
540    remove_attachment(ctx, att);
541    att->Type = GL_RENDERBUFFER_EXT;
542    att->Texture = NULL; /* just to be safe */
543    att->Layered = GL_FALSE;
544    att->Complete = GL_FALSE;
545    _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
546 }
547 
548 
549 /**
550  * Fallback for ctx->Driver.FramebufferRenderbuffer()
551  * Attach a renderbuffer object to a framebuffer object.
552  */
553 void
_mesa_FramebufferRenderbuffer_sw(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer * rb)554 _mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
555                                  struct gl_framebuffer *fb,
556                                  GLenum attachment,
557                                  struct gl_renderbuffer *rb)
558 {
559    struct gl_renderbuffer_attachment *att;
560 
561    simple_mtx_lock(&fb->Mutex);
562 
563    att = get_attachment(ctx, fb, attachment, NULL);
564    assert(att);
565    if (rb) {
566       set_renderbuffer_attachment(ctx, att, rb);
567       if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
568          /* do stencil attachment here (depth already done above) */
569          att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
570          assert(att);
571          set_renderbuffer_attachment(ctx, att, rb);
572       }
573       rb->AttachedAnytime = GL_TRUE;
574    }
575    else {
576       remove_attachment(ctx, att);
577       if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
578          /* detach stencil (depth was detached above) */
579          att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
580          assert(att);
581          remove_attachment(ctx, att);
582       }
583    }
584 
585    invalidate_framebuffer(fb);
586 
587    simple_mtx_unlock(&fb->Mutex);
588 }
589 
590 
591 /**
592  * Fallback for ctx->Driver.ValidateFramebuffer()
593  * Check if the renderbuffer's formats are supported by the software
594  * renderer.
595  * Drivers should probably override this.
596  */
597 void
_mesa_validate_framebuffer(struct gl_context * ctx,struct gl_framebuffer * fb)598 _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
599 {
600    gl_buffer_index buf;
601    for (buf = 0; buf < BUFFER_COUNT; buf++) {
602       const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
603       if (rb) {
604          switch (rb->_BaseFormat) {
605          case GL_ALPHA:
606          case GL_LUMINANCE_ALPHA:
607          case GL_LUMINANCE:
608          case GL_INTENSITY:
609          case GL_RED:
610          case GL_RG:
611             fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
612             return;
613 
614          default:
615             switch (rb->Format) {
616             /* XXX This list is likely incomplete. */
617             case MESA_FORMAT_R9G9B9E5_FLOAT:
618                fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
619                return;
620             default:;
621                /* render buffer format is supported by software rendering */
622             }
623          }
624       }
625    }
626 }
627 
628 
629 /**
630  * Return true if the framebuffer has a combined depth/stencil
631  * renderbuffer attached.
632  */
633 GLboolean
_mesa_has_depthstencil_combined(const struct gl_framebuffer * fb)634 _mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
635 {
636    const struct gl_renderbuffer_attachment *depth =
637          &fb->Attachment[BUFFER_DEPTH];
638    const struct gl_renderbuffer_attachment *stencil =
639          &fb->Attachment[BUFFER_STENCIL];
640 
641    if (depth->Type == stencil->Type) {
642       if (depth->Type == GL_RENDERBUFFER_EXT &&
643           depth->Renderbuffer == stencil->Renderbuffer)
644          return GL_TRUE;
645 
646       if (depth->Type == GL_TEXTURE &&
647           depth->Texture == stencil->Texture)
648          return GL_TRUE;
649    }
650 
651    return GL_FALSE;
652 }
653 
654 
655 /**
656  * For debug only.
657  */
658 static void
att_incomplete(const char * msg)659 att_incomplete(const char *msg)
660 {
661    if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
662       _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
663    }
664 }
665 
666 
667 /**
668  * For debug only.
669  */
670 static void
fbo_incomplete(struct gl_context * ctx,const char * msg,int index)671 fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
672 {
673    static GLuint msg_id;
674 
675    _mesa_gl_debug(ctx, &msg_id,
676                   MESA_DEBUG_SOURCE_API,
677                   MESA_DEBUG_TYPE_OTHER,
678                   MESA_DEBUG_SEVERITY_MEDIUM,
679                   "FBO incomplete: %s [%d]\n", msg, index);
680 
681    if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
682       _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
683    }
684 }
685 
686 
687 /**
688  * Is the given base format a legal format for a color renderbuffer?
689  */
690 GLboolean
_mesa_is_legal_color_format(const struct gl_context * ctx,GLenum baseFormat)691 _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
692 {
693    switch (baseFormat) {
694    case GL_RGB:
695    case GL_RGBA:
696       return GL_TRUE;
697    case GL_LUMINANCE:
698    case GL_LUMINANCE_ALPHA:
699    case GL_INTENSITY:
700    case GL_ALPHA:
701       return ctx->API == API_OPENGL_COMPAT &&
702              ctx->Extensions.ARB_framebuffer_object;
703    case GL_RED:
704    case GL_RG:
705       return ctx->Extensions.ARB_texture_rg;
706    default:
707       return GL_FALSE;
708    }
709 }
710 
711 
712 /**
713  * Is the given base format a legal format for a color renderbuffer?
714  */
715 static GLboolean
is_format_color_renderable(const struct gl_context * ctx,mesa_format format,GLenum internalFormat)716 is_format_color_renderable(const struct gl_context *ctx, mesa_format format,
717                            GLenum internalFormat)
718 {
719    const GLenum baseFormat =
720       _mesa_get_format_base_format(format);
721    GLboolean valid;
722 
723    valid = _mesa_is_legal_color_format(ctx, baseFormat);
724    if (!valid || _mesa_is_desktop_gl(ctx)) {
725       return valid;
726    }
727 
728    /* Reject additional cases for GLES */
729    switch (internalFormat) {
730    case GL_RGBA8_SNORM:
731    case GL_RGB32F:
732    case GL_RGB32I:
733    case GL_RGB32UI:
734    case GL_RGB16F:
735    case GL_RGB16I:
736    case GL_RGB16UI:
737    case GL_RGB8_SNORM:
738    case GL_RGB8I:
739    case GL_RGB8UI:
740    case GL_SRGB8:
741    case GL_RGB10:
742    case GL_RGB9_E5:
743    case GL_RG8_SNORM:
744    case GL_R8_SNORM:
745       return GL_FALSE;
746    default:
747       break;
748    }
749 
750    if (internalFormat != GL_RGB10_A2 &&
751        (format == MESA_FORMAT_B10G10R10A2_UNORM ||
752         format == MESA_FORMAT_B10G10R10X2_UNORM ||
753         format == MESA_FORMAT_R10G10B10A2_UNORM ||
754         format == MESA_FORMAT_R10G10B10X2_UNORM)) {
755       return GL_FALSE;
756    }
757 
758    return GL_TRUE;
759 }
760 
761 
762 /**
763  * Is the given base format a legal format for a depth/stencil renderbuffer?
764  */
765 static GLboolean
is_legal_depth_format(const struct gl_context * ctx,GLenum baseFormat)766 is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
767 {
768    switch (baseFormat) {
769    case GL_DEPTH_COMPONENT:
770    case GL_DEPTH_STENCIL_EXT:
771       return GL_TRUE;
772    default:
773       return GL_FALSE;
774    }
775 }
776 
777 
778 /**
779  * Test if an attachment point is complete and update its Complete field.
780  * \param format if GL_COLOR, this is a color attachment point,
781  *               if GL_DEPTH, this is a depth component attachment point,
782  *               if GL_STENCIL, this is a stencil component attachment point.
783  */
784 static void
test_attachment_completeness(const struct gl_context * ctx,GLenum format,struct gl_renderbuffer_attachment * att)785 test_attachment_completeness(const struct gl_context *ctx, GLenum format,
786                              struct gl_renderbuffer_attachment *att)
787 {
788    assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
789 
790    /* assume complete */
791    att->Complete = GL_TRUE;
792 
793    /* Look for reasons why the attachment might be incomplete */
794    if (att->Type == GL_TEXTURE) {
795       const struct gl_texture_object *texObj = att->Texture;
796       const struct gl_texture_image *texImage;
797       GLenum baseFormat;
798 
799       if (!texObj) {
800          att_incomplete("no texobj");
801          att->Complete = GL_FALSE;
802          return;
803       }
804 
805       texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
806       if (!texImage) {
807          att_incomplete("no teximage");
808          att->Complete = GL_FALSE;
809          return;
810       }
811       if (texImage->Width < 1 || texImage->Height < 1) {
812          att_incomplete("teximage width/height=0");
813          att->Complete = GL_FALSE;
814          return;
815       }
816 
817       switch (texObj->Target) {
818       case GL_TEXTURE_3D:
819          if (att->Zoffset >= texImage->Depth) {
820             att_incomplete("bad z offset");
821             att->Complete = GL_FALSE;
822             return;
823          }
824          break;
825       case GL_TEXTURE_1D_ARRAY:
826          if (att->Zoffset >= texImage->Height) {
827             att_incomplete("bad 1D-array layer");
828             att->Complete = GL_FALSE;
829             return;
830          }
831          break;
832       case GL_TEXTURE_2D_ARRAY:
833          if (att->Zoffset >= texImage->Depth) {
834             att_incomplete("bad 2D-array layer");
835             att->Complete = GL_FALSE;
836             return;
837          }
838          break;
839       case GL_TEXTURE_CUBE_MAP_ARRAY:
840          if (att->Zoffset >= texImage->Depth) {
841             att_incomplete("bad cube-array layer");
842             att->Complete = GL_FALSE;
843             return;
844          }
845          break;
846       }
847 
848       baseFormat = texImage->_BaseFormat;
849 
850       if (format == GL_COLOR) {
851          if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
852             att_incomplete("bad format");
853             att->Complete = GL_FALSE;
854             return;
855          }
856          if (_mesa_is_format_compressed(texImage->TexFormat)) {
857             att_incomplete("compressed internalformat");
858             att->Complete = GL_FALSE;
859             return;
860          }
861 
862          /* OES_texture_float allows creation and use of floating point
863           * textures with GL_FLOAT, GL_HALF_FLOAT but it does not allow
864           * these textures to be used as a render target, this is done via
865           * GL_EXT_color_buffer(_half)_float with set of new sized types.
866           */
867          if (_mesa_is_gles(ctx) && (texObj->_IsFloat || texObj->_IsHalfFloat)) {
868             att_incomplete("bad internal format");
869             att->Complete = GL_FALSE;
870             return;
871          }
872       }
873       else if (format == GL_DEPTH) {
874          if (baseFormat == GL_DEPTH_COMPONENT) {
875             /* OK */
876          }
877          else if (ctx->Extensions.ARB_depth_texture &&
878                   baseFormat == GL_DEPTH_STENCIL) {
879             /* OK */
880          }
881          else {
882             att->Complete = GL_FALSE;
883             att_incomplete("bad depth format");
884             return;
885          }
886       }
887       else {
888          assert(format == GL_STENCIL);
889          if (ctx->Extensions.ARB_depth_texture &&
890              baseFormat == GL_DEPTH_STENCIL) {
891             /* OK */
892          } else if (ctx->Extensions.ARB_texture_stencil8 &&
893                     baseFormat == GL_STENCIL_INDEX) {
894             /* OK */
895          } else {
896             /* no such thing as stencil-only textures */
897             att_incomplete("illegal stencil texture");
898             att->Complete = GL_FALSE;
899             return;
900          }
901       }
902    }
903    else if (att->Type == GL_RENDERBUFFER_EXT) {
904       const GLenum baseFormat = att->Renderbuffer->_BaseFormat;
905 
906       assert(att->Renderbuffer);
907       if (!att->Renderbuffer->InternalFormat ||
908           att->Renderbuffer->Width < 1 ||
909           att->Renderbuffer->Height < 1) {
910          att_incomplete("0x0 renderbuffer");
911          att->Complete = GL_FALSE;
912          return;
913       }
914       if (format == GL_COLOR) {
915          if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
916             att_incomplete("bad renderbuffer color format");
917             att->Complete = GL_FALSE;
918             return;
919          }
920       }
921       else if (format == GL_DEPTH) {
922          if (baseFormat == GL_DEPTH_COMPONENT) {
923             /* OK */
924          }
925          else if (baseFormat == GL_DEPTH_STENCIL) {
926             /* OK */
927          }
928          else {
929             att_incomplete("bad renderbuffer depth format");
930             att->Complete = GL_FALSE;
931             return;
932          }
933       }
934       else {
935          assert(format == GL_STENCIL);
936          if (baseFormat == GL_STENCIL_INDEX ||
937              baseFormat == GL_DEPTH_STENCIL) {
938             /* OK */
939          }
940          else {
941             att->Complete = GL_FALSE;
942             att_incomplete("bad renderbuffer stencil format");
943             return;
944          }
945       }
946    }
947    else {
948       assert(att->Type == GL_NONE);
949       /* complete */
950       return;
951    }
952 }
953 
954 
955 /**
956  * Test if the given framebuffer object is complete and update its
957  * Status field with the results.
958  * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
959  * driver to make hardware-specific validation/completeness checks.
960  * Also update the framebuffer's Width and Height fields if the
961  * framebuffer is complete.
962  */
963 void
_mesa_test_framebuffer_completeness(struct gl_context * ctx,struct gl_framebuffer * fb)964 _mesa_test_framebuffer_completeness(struct gl_context *ctx,
965                                     struct gl_framebuffer *fb)
966 {
967    GLuint numImages;
968    GLenum intFormat = GL_NONE; /* color buffers' internal format */
969    GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
970    GLint numSamples = -1;
971    GLint fixedSampleLocations = -1;
972    GLint i;
973    GLuint j;
974    /* Covers max_layer_count, is_layered, and layer_tex_target */
975    bool layer_info_valid = false;
976    GLuint max_layer_count = 0, att_layer_count;
977    bool is_layered = false;
978    GLenum layer_tex_target = 0;
979    bool has_depth_attachment = false;
980    bool has_stencil_attachment = false;
981 
982    assert(_mesa_is_user_fbo(fb));
983 
984    /* we're changing framebuffer fields here */
985    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
986 
987    numImages = 0;
988    fb->Width = 0;
989    fb->Height = 0;
990    fb->_AllColorBuffersFixedPoint = GL_TRUE;
991    fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
992    fb->_HasAttachments = true;
993    fb->_IntegerBuffers = 0;
994 
995    /* Start at -2 to more easily loop over all attachment points.
996     *  -2: depth buffer
997     *  -1: stencil buffer
998     * >=0: color buffer
999     */
1000    for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
1001       struct gl_renderbuffer_attachment *att;
1002       GLenum f;
1003       mesa_format attFormat;
1004       GLenum att_tex_target = GL_NONE;
1005 
1006       /*
1007        * XXX for ARB_fbo, only check color buffers that are named by
1008        * GL_READ_BUFFER and GL_DRAW_BUFFERi.
1009        */
1010 
1011       /* check for attachment completeness
1012        */
1013       if (i == -2) {
1014          att = &fb->Attachment[BUFFER_DEPTH];
1015          test_attachment_completeness(ctx, GL_DEPTH, att);
1016          if (!att->Complete) {
1017             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1018             fbo_incomplete(ctx, "depth attachment incomplete", -1);
1019             return;
1020          } else if (att->Type != GL_NONE) {
1021             has_depth_attachment = true;
1022          }
1023       }
1024       else if (i == -1) {
1025          att = &fb->Attachment[BUFFER_STENCIL];
1026          test_attachment_completeness(ctx, GL_STENCIL, att);
1027          if (!att->Complete) {
1028             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1029             fbo_incomplete(ctx, "stencil attachment incomplete", -1);
1030             return;
1031          } else if (att->Type != GL_NONE) {
1032             has_stencil_attachment = true;
1033          }
1034       }
1035       else {
1036          att = &fb->Attachment[BUFFER_COLOR0 + i];
1037          test_attachment_completeness(ctx, GL_COLOR, att);
1038          if (!att->Complete) {
1039             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
1040             fbo_incomplete(ctx, "color attachment incomplete", i);
1041             return;
1042          }
1043       }
1044 
1045       /* get width, height, format of the renderbuffer/texture
1046        */
1047       if (att->Type == GL_TEXTURE) {
1048          const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
1049          att_tex_target = att->Texture->Target;
1050          minWidth = MIN2(minWidth, texImg->Width);
1051          maxWidth = MAX2(maxWidth, texImg->Width);
1052          minHeight = MIN2(minHeight, texImg->Height);
1053          maxHeight = MAX2(maxHeight, texImg->Height);
1054          f = texImg->_BaseFormat;
1055          attFormat = texImg->TexFormat;
1056          numImages++;
1057 
1058          if (!is_format_color_renderable(ctx, attFormat,
1059                                          texImg->InternalFormat) &&
1060              !is_legal_depth_format(ctx, f) &&
1061              f != GL_STENCIL_INDEX) {
1062             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1063             fbo_incomplete(ctx, "texture attachment incomplete", -1);
1064             return;
1065          }
1066 
1067          if (numSamples < 0)
1068             numSamples = texImg->NumSamples;
1069          else if (numSamples != texImg->NumSamples) {
1070             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1071             fbo_incomplete(ctx, "inconsistent sample count", -1);
1072             return;
1073          }
1074 
1075          if (fixedSampleLocations < 0)
1076             fixedSampleLocations = texImg->FixedSampleLocations;
1077          else if (fixedSampleLocations != texImg->FixedSampleLocations) {
1078             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1079             fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1080             return;
1081          }
1082       }
1083       else if (att->Type == GL_RENDERBUFFER_EXT) {
1084          minWidth = MIN2(minWidth, att->Renderbuffer->Width);
1085          maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
1086          minHeight = MIN2(minHeight, att->Renderbuffer->Height);
1087          maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
1088          f = att->Renderbuffer->InternalFormat;
1089          attFormat = att->Renderbuffer->Format;
1090          numImages++;
1091 
1092          if (numSamples < 0)
1093             numSamples = att->Renderbuffer->NumSamples;
1094          else if (numSamples != att->Renderbuffer->NumSamples) {
1095             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1096             fbo_incomplete(ctx, "inconsistent sample count", -1);
1097             return;
1098          }
1099 
1100          /* RENDERBUFFER has fixedSampleLocations implicitly true */
1101          if (fixedSampleLocations < 0)
1102             fixedSampleLocations = GL_TRUE;
1103          else if (fixedSampleLocations != GL_TRUE) {
1104             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1105             fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1106             return;
1107          }
1108       }
1109       else {
1110          assert(att->Type == GL_NONE);
1111          continue;
1112       }
1113 
1114       /* Update flags describing color buffer datatypes */
1115       if (i >= 0) {
1116          GLenum type = _mesa_get_format_datatype(attFormat);
1117 
1118          /* check if integer color */
1119          if (_mesa_is_format_integer_color(attFormat))
1120             fb->_IntegerBuffers |= (1 << i);
1121 
1122          fb->_AllColorBuffersFixedPoint =
1123             fb->_AllColorBuffersFixedPoint &&
1124             (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
1125 
1126          fb->_HasSNormOrFloatColorBuffer =
1127             fb->_HasSNormOrFloatColorBuffer ||
1128             type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
1129       }
1130 
1131       /* Error-check width, height, format */
1132       if (numImages == 1) {
1133          /* save format */
1134          if (i >= 0) {
1135             intFormat = f;
1136          }
1137       }
1138       else {
1139          if (!ctx->Extensions.ARB_framebuffer_object) {
1140             /* check that width, height, format are same */
1141             if (minWidth != maxWidth || minHeight != maxHeight) {
1142                fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
1143                fbo_incomplete(ctx, "width or height mismatch", -1);
1144                return;
1145             }
1146             /* check that all color buffers are the same format */
1147             if (intFormat != GL_NONE && f != intFormat) {
1148                fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
1149                fbo_incomplete(ctx, "format mismatch", -1);
1150                return;
1151             }
1152          }
1153       }
1154 
1155       /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1156        */
1157       if (att->Type == GL_RENDERBUFFER &&
1158           att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1159          fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1160          fbo_incomplete(ctx, "unsupported renderbuffer format", i);
1161          return;
1162       }
1163 
1164       /* Check that layered rendering is consistent. */
1165       if (att->Layered) {
1166          if (att_tex_target == GL_TEXTURE_CUBE_MAP)
1167             att_layer_count = 6;
1168          else if (att_tex_target == GL_TEXTURE_1D_ARRAY)
1169             att_layer_count = att->Renderbuffer->Height;
1170          else
1171             att_layer_count = att->Renderbuffer->Depth;
1172       } else {
1173          att_layer_count = 0;
1174       }
1175       if (!layer_info_valid) {
1176          is_layered = att->Layered;
1177          max_layer_count = att_layer_count;
1178          layer_tex_target = att_tex_target;
1179          layer_info_valid = true;
1180       } else if (max_layer_count > 0 && layer_tex_target != att_tex_target) {
1181          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1182          fbo_incomplete(ctx, "layered framebuffer has mismatched targets", i);
1183          return;
1184       } else if (is_layered != att->Layered) {
1185          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1186          fbo_incomplete(ctx,
1187                         "framebuffer attachment layer mode is inconsistent",
1188                         i);
1189          return;
1190       } else if (att_layer_count > max_layer_count) {
1191          max_layer_count = att_layer_count;
1192       }
1193 
1194       /*
1195        * The extension GL_ARB_framebuffer_no_attachments places additional
1196        * requirement on each attachment. Those additional requirements are
1197        * tighter that those of previous versions of GL. In interest of better
1198        * compatibility, we will not enforce these restrictions. For the record
1199        * those additional restrictions are quoted below:
1200        *
1201        * "The width and height of image are greater than zero and less than or
1202        *  equal to the values of the implementation-dependent limits
1203        *  MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively."
1204        *
1205        * "If <image> is a three-dimensional texture or a one- or two-dimensional
1206        *  array texture and the attachment is layered, the depth or layer count
1207        *  of the texture is less than or equal to the implementation-dependent
1208        *  limit MAX_FRAMEBUFFER_LAYERS."
1209        *
1210        * "If image has multiple samples, its sample count is less than or equal
1211        *  to the value of the implementation-dependent limit
1212        *  MAX_FRAMEBUFFER_SAMPLES."
1213        *
1214        * The same requirements are also in place for GL 4.5,
1215        * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
1216        */
1217    }
1218 
1219    fb->MaxNumLayers = max_layer_count;
1220 
1221    if (numImages == 0) {
1222       fb->_HasAttachments = false;
1223 
1224       if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1225          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1226          fbo_incomplete(ctx, "no attachments", -1);
1227          return;
1228       }
1229 
1230       if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) {
1231          fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1232          fbo_incomplete(ctx, "no attachments and default width or height is 0", -1);
1233          return;
1234       }
1235    }
1236 
1237    if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
1238       /* Check that all DrawBuffers are present */
1239       for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
1240          if (fb->ColorDrawBuffer[j] != GL_NONE) {
1241             const struct gl_renderbuffer_attachment *att
1242                = get_attachment(ctx, fb, fb->ColorDrawBuffer[j], NULL);
1243             assert(att);
1244             if (att->Type == GL_NONE) {
1245                fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1246                fbo_incomplete(ctx, "missing drawbuffer", j);
1247                return;
1248             }
1249          }
1250       }
1251 
1252       /* Check that the ReadBuffer is present */
1253       if (fb->ColorReadBuffer != GL_NONE) {
1254          const struct gl_renderbuffer_attachment *att
1255             = get_attachment(ctx, fb, fb->ColorReadBuffer, NULL);
1256          assert(att);
1257          if (att->Type == GL_NONE) {
1258             fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
1259             fbo_incomplete(ctx, "missing readbuffer", -1);
1260             return;
1261          }
1262       }
1263    }
1264 
1265    /* The OpenGL ES3 spec, in chapter 9.4. FRAMEBUFFER COMPLETENESS, says:
1266     *
1267     *    "Depth and stencil attachments, if present, are the same image."
1268     *
1269     * This restriction is not present in the OpenGL ES2 spec.
1270     */
1271    if (_mesa_is_gles3(ctx) &&
1272        has_stencil_attachment && has_depth_attachment &&
1273        !_mesa_has_depthstencil_combined(fb)) {
1274       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1275       fbo_incomplete(ctx, "Depth and stencil attachments must be the same image", -1);
1276       return;
1277    }
1278 
1279    /* Provisionally set status = COMPLETE ... */
1280    fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
1281 
1282    /* ... but the driver may say the FB is incomplete.
1283     * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1284     * if anything.
1285     */
1286    if (ctx->Driver.ValidateFramebuffer) {
1287       ctx->Driver.ValidateFramebuffer(ctx, fb);
1288       if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1289          fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
1290          return;
1291       }
1292    }
1293 
1294    /*
1295     * Note that if ARB_framebuffer_object is supported and the attached
1296     * renderbuffers/textures are different sizes, the framebuffer
1297     * width/height will be set to the smallest width/height.
1298     */
1299    if (numImages != 0) {
1300       fb->Width = minWidth;
1301       fb->Height = minHeight;
1302    }
1303 
1304    /* finally, update the visual info for the framebuffer */
1305    _mesa_update_framebuffer_visual(ctx, fb);
1306 }
1307 
1308 
1309 GLboolean GLAPIENTRY
_mesa_IsRenderbuffer(GLuint renderbuffer)1310 _mesa_IsRenderbuffer(GLuint renderbuffer)
1311 {
1312    struct gl_renderbuffer *rb;
1313 
1314    GET_CURRENT_CONTEXT(ctx);
1315 
1316    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1317 
1318    rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1319    return rb != NULL && rb != &DummyRenderbuffer;
1320 }
1321 
1322 
1323 static struct gl_renderbuffer *
allocate_renderbuffer_locked(struct gl_context * ctx,GLuint renderbuffer,const char * func)1324 allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
1325                              const char *func)
1326 {
1327    struct gl_renderbuffer *newRb;
1328 
1329    /* create new renderbuffer object */
1330    newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1331    if (!newRb) {
1332       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1333       return NULL;
1334    }
1335    assert(newRb->AllocStorage);
1336    _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer, newRb);
1337 
1338    return newRb;
1339 }
1340 
1341 
1342 static void
bind_renderbuffer(GLenum target,GLuint renderbuffer,bool allow_user_names)1343 bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
1344 {
1345    struct gl_renderbuffer *newRb;
1346    GET_CURRENT_CONTEXT(ctx);
1347 
1348    if (target != GL_RENDERBUFFER_EXT) {
1349       _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
1350       return;
1351    }
1352 
1353    /* No need to flush here since the render buffer binding has no
1354     * effect on rendering state.
1355     */
1356 
1357    if (renderbuffer) {
1358       newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1359       if (newRb == &DummyRenderbuffer) {
1360          /* ID was reserved, but no real renderbuffer object made yet */
1361          newRb = NULL;
1362       }
1363       else if (!newRb && !allow_user_names) {
1364          /* All RB IDs must be Gen'd */
1365          _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
1366          return;
1367       }
1368 
1369       if (!newRb) {
1370          _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1371          newRb = allocate_renderbuffer_locked(ctx, renderbuffer,
1372                                               "glBindRenderbufferEXT");
1373          _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
1374       }
1375    }
1376    else {
1377       newRb = NULL;
1378    }
1379 
1380    assert(newRb != &DummyRenderbuffer);
1381 
1382    _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
1383 }
1384 
1385 void GLAPIENTRY
_mesa_BindRenderbuffer(GLenum target,GLuint renderbuffer)1386 _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1387 {
1388    GET_CURRENT_CONTEXT(ctx);
1389 
1390    /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1391     * entry point, but they allow the use of user-generated names.
1392     */
1393    bind_renderbuffer(target, renderbuffer, _mesa_is_gles(ctx));
1394 }
1395 
1396 void GLAPIENTRY
_mesa_BindRenderbufferEXT(GLenum target,GLuint renderbuffer)1397 _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1398 {
1399    /* This function should not be in the dispatch table for core profile /
1400     * OpenGL 3.1, so execution should never get here in those cases -- no
1401     * need for an explicit test.
1402     */
1403    bind_renderbuffer(target, renderbuffer, true);
1404 }
1405 
1406 /**
1407  * ARB_framebuffer_no_attachment - Application passes requested param's
1408  * here. NOTE: NumSamples requested need not be _NumSamples which is
1409  * what the hw supports.
1410  */
1411 static void
framebuffer_parameteri(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum pname,GLint param,const char * func)1412 framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
1413                        GLenum pname, GLint param, const char *func)
1414 {
1415    switch (pname) {
1416    case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1417       if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
1418         _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1419       else
1420          fb->DefaultGeometry.Width = param;
1421       break;
1422    case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1423       if (param < 0 || param > ctx->Const.MaxFramebufferHeight)
1424         _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1425       else
1426          fb->DefaultGeometry.Height = param;
1427       break;
1428    case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1429      /*
1430       * According to the OpenGL ES 3.1 specification section 9.2.1, the
1431       * GL_FRAMEBUFFER_DEFAULT_LAYERS parameter name is not supported.
1432       */
1433       if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1434          _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1435          break;
1436       }
1437       if (param < 0 || param > ctx->Const.MaxFramebufferLayers)
1438          _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1439       else
1440          fb->DefaultGeometry.Layers = param;
1441       break;
1442    case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1443       if (param < 0 || param > ctx->Const.MaxFramebufferSamples)
1444         _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1445       else
1446         fb->DefaultGeometry.NumSamples = param;
1447       break;
1448    case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1449       fb->DefaultGeometry.FixedSampleLocations = param;
1450       break;
1451    default:
1452       _mesa_error(ctx, GL_INVALID_ENUM,
1453                   "%s(pname=0x%x)", func, pname);
1454    }
1455 
1456    invalidate_framebuffer(fb);
1457    ctx->NewState |= _NEW_BUFFERS;
1458 }
1459 
1460 void GLAPIENTRY
_mesa_FramebufferParameteri(GLenum target,GLenum pname,GLint param)1461 _mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
1462 {
1463    GET_CURRENT_CONTEXT(ctx);
1464    struct gl_framebuffer *fb;
1465 
1466    if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1467       _mesa_error(ctx, GL_INVALID_OPERATION,
1468                   "glFramebufferParameteriv not supported "
1469                   "(ARB_framebuffer_no_attachments not implemented)");
1470       return;
1471    }
1472 
1473    fb = get_framebuffer_target(ctx, target);
1474    if (!fb) {
1475       _mesa_error(ctx, GL_INVALID_ENUM,
1476                   "glFramebufferParameteri(target=0x%x)", target);
1477       return;
1478    }
1479 
1480    /* check framebuffer binding */
1481    if (_mesa_is_winsys_fbo(fb)) {
1482       _mesa_error(ctx, GL_INVALID_OPERATION,
1483                   "glFramebufferParameteri");
1484       return;
1485    }
1486 
1487    framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
1488 }
1489 
1490 static bool
_pname_valid_for_default_framebuffer(struct gl_context * ctx,GLenum pname)1491 _pname_valid_for_default_framebuffer(struct gl_context *ctx,
1492                                      GLenum pname)
1493 {
1494    if (!_mesa_is_desktop_gl(ctx))
1495       return false;
1496 
1497    switch (pname) {
1498    case GL_DOUBLEBUFFER:
1499    case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1500    case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1501    case GL_SAMPLES:
1502    case GL_SAMPLE_BUFFERS:
1503    case GL_STEREO:
1504       return true;
1505    default:
1506       return false;
1507    }
1508 }
1509 
1510 static void
get_framebuffer_parameteriv(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum pname,GLint * params,const char * func)1511 get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
1512                             GLenum pname, GLint *params, const char *func)
1513 {
1514    /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
1515     *
1516     *    "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
1517     *     if the default framebuffer is bound to target and pname is not one
1518     *     of the accepted values from table 23.73, other than
1519     *     SAMPLE_POSITION."
1520     *
1521     * For OpenGL ES, using default framebuffer still raises INVALID_OPERATION
1522     * for any pname.
1523     */
1524    if (_mesa_is_winsys_fbo(fb) &&
1525        !_pname_valid_for_default_framebuffer(ctx, pname)) {
1526       _mesa_error(ctx, GL_INVALID_OPERATION,
1527                   "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1528       return;
1529    }
1530 
1531    switch (pname) {
1532    case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1533       *params = fb->DefaultGeometry.Width;
1534       break;
1535    case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1536       *params = fb->DefaultGeometry.Height;
1537       break;
1538    case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1539       /*
1540        * According to the OpenGL ES 3.1 specification section 9.2.3, the
1541        * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
1542        */
1543       if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1544          _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1545          break;
1546       }
1547       *params = fb->DefaultGeometry.Layers;
1548       break;
1549    case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1550       *params = fb->DefaultGeometry.NumSamples;
1551       break;
1552    case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1553       *params = fb->DefaultGeometry.FixedSampleLocations;
1554       break;
1555    case GL_DOUBLEBUFFER:
1556       *params = fb->Visual.doubleBufferMode;
1557       break;
1558    case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1559       *params = _mesa_get_color_read_format(ctx, fb, func);
1560       break;
1561    case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1562       *params = _mesa_get_color_read_type(ctx, fb, func);
1563       break;
1564    case GL_SAMPLES:
1565       *params = _mesa_geometric_samples(fb);
1566       break;
1567    case GL_SAMPLE_BUFFERS:
1568       *params = _mesa_geometric_samples(fb) > 0;
1569       break;
1570    case GL_STEREO:
1571       *params = fb->Visual.stereoMode;
1572       break;
1573    default:
1574       _mesa_error(ctx, GL_INVALID_ENUM,
1575                   "%s(pname=0x%x)", func, pname);
1576    }
1577 }
1578 
1579 void GLAPIENTRY
_mesa_GetFramebufferParameteriv(GLenum target,GLenum pname,GLint * params)1580 _mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
1581 {
1582    GET_CURRENT_CONTEXT(ctx);
1583    struct gl_framebuffer *fb;
1584 
1585    if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1586       _mesa_error(ctx, GL_INVALID_OPERATION,
1587                   "glGetFramebufferParameteriv not supported "
1588                   "(ARB_framebuffer_no_attachments not implemented)");
1589       return;
1590    }
1591 
1592    fb = get_framebuffer_target(ctx, target);
1593    if (!fb) {
1594       _mesa_error(ctx, GL_INVALID_ENUM,
1595                   "glGetFramebufferParameteriv(target=0x%x)", target);
1596       return;
1597    }
1598 
1599    get_framebuffer_parameteriv(ctx, fb, pname, params,
1600                                "glGetFramebufferParameteriv");
1601 }
1602 
1603 
1604 /**
1605  * Remove the specified renderbuffer or texture from any attachment point in
1606  * the framebuffer.
1607  *
1608  * \returns
1609  * \c true if the renderbuffer was detached from an attachment point.  \c
1610  * false otherwise.
1611  */
1612 bool
_mesa_detach_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,const void * att)1613 _mesa_detach_renderbuffer(struct gl_context *ctx,
1614                           struct gl_framebuffer *fb,
1615                           const void *att)
1616 {
1617    unsigned i;
1618    bool progress = false;
1619 
1620    for (i = 0; i < BUFFER_COUNT; i++) {
1621       if (fb->Attachment[i].Texture == att
1622           || fb->Attachment[i].Renderbuffer == att) {
1623          remove_attachment(ctx, &fb->Attachment[i]);
1624          progress = true;
1625       }
1626    }
1627 
1628    /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1629     * Completeness," of the OpenGL 3.1 spec says:
1630     *
1631     *     "Performing any of the following actions may change whether the
1632     *     framebuffer is considered complete or incomplete:
1633     *
1634     *     ...
1635     *
1636     *        - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1637     *          containing an image that is attached to a framebuffer object
1638     *          that is bound to the framebuffer."
1639     */
1640    if (progress)
1641       invalidate_framebuffer(fb);
1642 
1643    return progress;
1644 }
1645 
1646 
1647 void GLAPIENTRY
_mesa_DeleteRenderbuffers(GLsizei n,const GLuint * renderbuffers)1648 _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
1649 {
1650    GLint i;
1651    GET_CURRENT_CONTEXT(ctx);
1652 
1653    if (n < 0) {
1654       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteRenderbuffers(n < 0)");
1655       return;
1656    }
1657 
1658    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1659 
1660    for (i = 0; i < n; i++) {
1661       if (renderbuffers[i] > 0) {
1662          struct gl_renderbuffer *rb;
1663          rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
1664          if (rb) {
1665             /* check if deleting currently bound renderbuffer object */
1666             if (rb == ctx->CurrentRenderbuffer) {
1667                /* bind default */
1668                assert(rb->RefCount >= 2);
1669                _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
1670             }
1671 
1672             /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
1673              * subsection "Attaching Renderbuffer Images to a Framebuffer,"
1674              * of the OpenGL 3.1 spec says:
1675              *
1676              *     "If a renderbuffer object is deleted while its image is
1677              *     attached to one or more attachment points in the currently
1678              *     bound framebuffer, then it is as if FramebufferRenderbuffer
1679              *     had been called, with a renderbuffer of 0, for each
1680              *     attachment point to which this image was attached in the
1681              *     currently bound framebuffer. In other words, this
1682              *     renderbuffer image is first detached from all attachment
1683              *     points in the currently bound framebuffer. Note that the
1684              *     renderbuffer image is specifically not detached from any
1685              *     non-bound framebuffers. Detaching the image from any
1686              *     non-bound framebuffers is the responsibility of the
1687              *     application.
1688              */
1689             if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1690                _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
1691             }
1692             if (_mesa_is_user_fbo(ctx->ReadBuffer)
1693                 && ctx->ReadBuffer != ctx->DrawBuffer) {
1694                _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
1695             }
1696 
1697             /* Remove from hash table immediately, to free the ID.
1698              * But the object will not be freed until it's no longer
1699              * referenced anywhere else.
1700              */
1701             _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
1702 
1703             if (rb != &DummyRenderbuffer) {
1704                /* no longer referenced by hash table */
1705                _mesa_reference_renderbuffer(&rb, NULL);
1706             }
1707          }
1708       }
1709    }
1710 }
1711 
1712 static void
create_render_buffers(struct gl_context * ctx,GLsizei n,GLuint * renderbuffers,bool dsa)1713 create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
1714                       bool dsa)
1715 {
1716    const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
1717    GLuint first;
1718    GLint i;
1719 
1720    if (!renderbuffers)
1721       return;
1722 
1723    _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1724 
1725    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1726 
1727    for (i = 0; i < n; i++) {
1728       GLuint name = first + i;
1729       renderbuffers[i] = name;
1730 
1731       if (dsa) {
1732          allocate_renderbuffer_locked(ctx, name, func);
1733       } else {
1734          /* insert a dummy renderbuffer into the hash table */
1735          _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, name,
1736                                 &DummyRenderbuffer);
1737       }
1738    }
1739 
1740    _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
1741 }
1742 
1743 
1744 static void
create_render_buffers_err(struct gl_context * ctx,GLsizei n,GLuint * renderbuffers,bool dsa)1745 create_render_buffers_err(struct gl_context *ctx, GLsizei n,
1746                           GLuint *renderbuffers, bool dsa)
1747 {
1748    const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
1749 
1750    if (n < 0) {
1751       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
1752       return;
1753    }
1754 
1755    create_render_buffers(ctx, n, renderbuffers, dsa);
1756 }
1757 
1758 
1759 void GLAPIENTRY
_mesa_GenRenderbuffers_no_error(GLsizei n,GLuint * renderbuffers)1760 _mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
1761 {
1762    GET_CURRENT_CONTEXT(ctx);
1763    create_render_buffers(ctx, n, renderbuffers, false);
1764 }
1765 
1766 
1767 void GLAPIENTRY
_mesa_GenRenderbuffers(GLsizei n,GLuint * renderbuffers)1768 _mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
1769 {
1770    GET_CURRENT_CONTEXT(ctx);
1771    create_render_buffers_err(ctx, n, renderbuffers, false);
1772 }
1773 
1774 
1775 void GLAPIENTRY
_mesa_CreateRenderbuffers_no_error(GLsizei n,GLuint * renderbuffers)1776 _mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
1777 {
1778    GET_CURRENT_CONTEXT(ctx);
1779    create_render_buffers(ctx, n, renderbuffers, true);
1780 }
1781 
1782 
1783 void GLAPIENTRY
_mesa_CreateRenderbuffers(GLsizei n,GLuint * renderbuffers)1784 _mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
1785 {
1786    GET_CURRENT_CONTEXT(ctx);
1787    create_render_buffers_err(ctx, n, renderbuffers, true);
1788 }
1789 
1790 
1791 /**
1792  * Given an internal format token for a render buffer, return the
1793  * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
1794  * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
1795  * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
1796  *
1797  * This is similar to _mesa_base_tex_format() but the set of valid
1798  * internal formats is different.
1799  *
1800  * Note that even if a format is determined to be legal here, validation
1801  * of the FBO may fail if the format is not supported by the driver/GPU.
1802  *
1803  * \param internalFormat  as passed to glRenderbufferStorage()
1804  * \return the base internal format, or 0 if internalFormat is illegal
1805  */
1806 GLenum
_mesa_base_fbo_format(const struct gl_context * ctx,GLenum internalFormat)1807 _mesa_base_fbo_format(const struct gl_context *ctx, GLenum internalFormat)
1808 {
1809    /*
1810     * Notes: some formats such as alpha, luminance, etc. were added
1811     * with GL_ARB_framebuffer_object.
1812     */
1813    switch (internalFormat) {
1814    case GL_ALPHA:
1815    case GL_ALPHA4:
1816    case GL_ALPHA8:
1817    case GL_ALPHA12:
1818    case GL_ALPHA16:
1819       return (ctx->API == API_OPENGL_COMPAT &&
1820               ctx->Extensions.ARB_framebuffer_object) ? GL_ALPHA : 0;
1821    case GL_LUMINANCE:
1822    case GL_LUMINANCE4:
1823    case GL_LUMINANCE8:
1824    case GL_LUMINANCE12:
1825    case GL_LUMINANCE16:
1826       return (ctx->API == API_OPENGL_COMPAT &&
1827               ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE : 0;
1828    case GL_LUMINANCE_ALPHA:
1829    case GL_LUMINANCE4_ALPHA4:
1830    case GL_LUMINANCE6_ALPHA2:
1831    case GL_LUMINANCE8_ALPHA8:
1832    case GL_LUMINANCE12_ALPHA4:
1833    case GL_LUMINANCE12_ALPHA12:
1834    case GL_LUMINANCE16_ALPHA16:
1835       return (ctx->API == API_OPENGL_COMPAT &&
1836               ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE_ALPHA : 0;
1837    case GL_INTENSITY:
1838    case GL_INTENSITY4:
1839    case GL_INTENSITY8:
1840    case GL_INTENSITY12:
1841    case GL_INTENSITY16:
1842       return (ctx->API == API_OPENGL_COMPAT &&
1843               ctx->Extensions.ARB_framebuffer_object) ? GL_INTENSITY : 0;
1844    case GL_RGB8:
1845       return GL_RGB;
1846    case GL_RGB:
1847    case GL_R3_G3_B2:
1848    case GL_RGB4:
1849    case GL_RGB5:
1850    case GL_RGB10:
1851    case GL_RGB12:
1852    case GL_RGB16:
1853       return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
1854    case GL_SRGB8_EXT:
1855       return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
1856    case GL_RGBA4:
1857    case GL_RGB5_A1:
1858    case GL_RGBA8:
1859       return GL_RGBA;
1860    case GL_RGBA:
1861    case GL_RGBA2:
1862    case GL_RGBA12:
1863    case GL_RGBA16:
1864       return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
1865    case GL_RGB10_A2:
1866    case GL_SRGB8_ALPHA8_EXT:
1867       return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
1868    case GL_STENCIL_INDEX:
1869    case GL_STENCIL_INDEX1_EXT:
1870    case GL_STENCIL_INDEX4_EXT:
1871    case GL_STENCIL_INDEX16_EXT:
1872       /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
1873        * OpenGL ES, but Mesa does not currently support them.
1874        */
1875       return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
1876    case GL_STENCIL_INDEX8_EXT:
1877       return GL_STENCIL_INDEX;
1878    case GL_DEPTH_COMPONENT:
1879    case GL_DEPTH_COMPONENT32:
1880       return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
1881    case GL_DEPTH_COMPONENT16:
1882    case GL_DEPTH_COMPONENT24:
1883       return GL_DEPTH_COMPONENT;
1884    case GL_DEPTH_STENCIL:
1885       return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_STENCIL : 0;
1886    case GL_DEPTH24_STENCIL8:
1887       return GL_DEPTH_STENCIL;
1888    case GL_DEPTH_COMPONENT32F:
1889       return ctx->Version >= 30
1890          || (ctx->API == API_OPENGL_COMPAT &&
1891              ctx->Extensions.ARB_depth_buffer_float)
1892          ? GL_DEPTH_COMPONENT : 0;
1893    case GL_DEPTH32F_STENCIL8:
1894       return ctx->Version >= 30
1895          || (ctx->API == API_OPENGL_COMPAT &&
1896              ctx->Extensions.ARB_depth_buffer_float)
1897          ? GL_DEPTH_STENCIL : 0;
1898    case GL_RED:
1899    case GL_R16:
1900       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1901          ? GL_RED : 0;
1902    case GL_R8:
1903       return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1904          ? GL_RED : 0;
1905    case GL_RG:
1906    case GL_RG16:
1907       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1908          ? GL_RG : 0;
1909    case GL_RG8:
1910       return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1911          ? GL_RG : 0;
1912    /* signed normalized texture formats */
1913    case GL_RED_SNORM:
1914    case GL_R8_SNORM:
1915    case GL_R16_SNORM:
1916       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1917          ? GL_RED : 0;
1918    case GL_RG_SNORM:
1919    case GL_RG8_SNORM:
1920    case GL_RG16_SNORM:
1921       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1922          ? GL_RG : 0;
1923    case GL_RGB_SNORM:
1924    case GL_RGB8_SNORM:
1925    case GL_RGB16_SNORM:
1926       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1927          ? GL_RGB : 0;
1928    case GL_RGBA_SNORM:
1929    case GL_RGBA8_SNORM:
1930    case GL_RGBA16_SNORM:
1931       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1932          ? GL_RGBA : 0;
1933    case GL_ALPHA_SNORM:
1934    case GL_ALPHA8_SNORM:
1935    case GL_ALPHA16_SNORM:
1936       return ctx->API == API_OPENGL_COMPAT &&
1937              ctx->Extensions.EXT_texture_snorm &&
1938              ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1939    case GL_LUMINANCE_SNORM:
1940    case GL_LUMINANCE8_SNORM:
1941    case GL_LUMINANCE16_SNORM:
1942       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1943          ? GL_LUMINANCE : 0;
1944    case GL_LUMINANCE_ALPHA_SNORM:
1945    case GL_LUMINANCE8_ALPHA8_SNORM:
1946    case GL_LUMINANCE16_ALPHA16_SNORM:
1947       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1948          ? GL_LUMINANCE_ALPHA : 0;
1949    case GL_INTENSITY_SNORM:
1950    case GL_INTENSITY8_SNORM:
1951    case GL_INTENSITY16_SNORM:
1952       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1953          ? GL_INTENSITY : 0;
1954 
1955    case GL_R16F:
1956    case GL_R32F:
1957       return ((_mesa_is_desktop_gl(ctx) &&
1958                ctx->Extensions.ARB_texture_rg &&
1959                ctx->Extensions.ARB_texture_float) ||
1960               _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1961          ? GL_RED : 0;
1962    case GL_RG16F:
1963    case GL_RG32F:
1964       return ((_mesa_is_desktop_gl(ctx) &&
1965                ctx->Extensions.ARB_texture_rg &&
1966                ctx->Extensions.ARB_texture_float) ||
1967               _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1968          ? GL_RG : 0;
1969    case GL_RGB16F:
1970    case GL_RGB32F:
1971       return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
1972          ? GL_RGB : 0;
1973    case GL_RGBA16F:
1974    case GL_RGBA32F:
1975       return ((_mesa_is_desktop_gl(ctx) &&
1976                ctx->Extensions.ARB_texture_float) ||
1977               _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1978          ? GL_RGBA : 0;
1979    case GL_ALPHA16F_ARB:
1980    case GL_ALPHA32F_ARB:
1981       return ctx->API == API_OPENGL_COMPAT &&
1982              ctx->Extensions.ARB_texture_float &&
1983              ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1984    case GL_LUMINANCE16F_ARB:
1985    case GL_LUMINANCE32F_ARB:
1986       return ctx->API == API_OPENGL_COMPAT &&
1987              ctx->Extensions.ARB_texture_float &&
1988              ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1989    case GL_LUMINANCE_ALPHA16F_ARB:
1990    case GL_LUMINANCE_ALPHA32F_ARB:
1991       return ctx->API == API_OPENGL_COMPAT &&
1992              ctx->Extensions.ARB_texture_float &&
1993              ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1994    case GL_INTENSITY16F_ARB:
1995    case GL_INTENSITY32F_ARB:
1996       return ctx->API == API_OPENGL_COMPAT &&
1997              ctx->Extensions.ARB_texture_float &&
1998              ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1999    case GL_R11F_G11F_B10F:
2000       return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
2001               _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2002          ? GL_RGB : 0;
2003 
2004    case GL_RGBA8UI_EXT:
2005    case GL_RGBA16UI_EXT:
2006    case GL_RGBA32UI_EXT:
2007    case GL_RGBA8I_EXT:
2008    case GL_RGBA16I_EXT:
2009    case GL_RGBA32I_EXT:
2010       return ctx->Version >= 30
2011          || (_mesa_is_desktop_gl(ctx) &&
2012              ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
2013 
2014    case GL_RGB8UI_EXT:
2015    case GL_RGB16UI_EXT:
2016    case GL_RGB32UI_EXT:
2017    case GL_RGB8I_EXT:
2018    case GL_RGB16I_EXT:
2019    case GL_RGB32I_EXT:
2020       return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
2021          ? GL_RGB : 0;
2022    case GL_R8UI:
2023    case GL_R8I:
2024    case GL_R16UI:
2025    case GL_R16I:
2026    case GL_R32UI:
2027    case GL_R32I:
2028       return ctx->Version >= 30
2029          || (_mesa_is_desktop_gl(ctx) &&
2030              ctx->Extensions.ARB_texture_rg &&
2031              ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
2032 
2033    case GL_RG8UI:
2034    case GL_RG8I:
2035    case GL_RG16UI:
2036    case GL_RG16I:
2037    case GL_RG32UI:
2038    case GL_RG32I:
2039       return ctx->Version >= 30
2040          || (_mesa_is_desktop_gl(ctx) &&
2041              ctx->Extensions.ARB_texture_rg &&
2042              ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
2043 
2044    case GL_INTENSITY8I_EXT:
2045    case GL_INTENSITY8UI_EXT:
2046    case GL_INTENSITY16I_EXT:
2047    case GL_INTENSITY16UI_EXT:
2048    case GL_INTENSITY32I_EXT:
2049    case GL_INTENSITY32UI_EXT:
2050       return ctx->API == API_OPENGL_COMPAT &&
2051              ctx->Extensions.EXT_texture_integer &&
2052              ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2053 
2054    case GL_LUMINANCE8I_EXT:
2055    case GL_LUMINANCE8UI_EXT:
2056    case GL_LUMINANCE16I_EXT:
2057    case GL_LUMINANCE16UI_EXT:
2058    case GL_LUMINANCE32I_EXT:
2059    case GL_LUMINANCE32UI_EXT:
2060       return ctx->API == API_OPENGL_COMPAT &&
2061              ctx->Extensions.EXT_texture_integer &&
2062              ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2063 
2064    case GL_LUMINANCE_ALPHA8I_EXT:
2065    case GL_LUMINANCE_ALPHA8UI_EXT:
2066    case GL_LUMINANCE_ALPHA16I_EXT:
2067    case GL_LUMINANCE_ALPHA16UI_EXT:
2068    case GL_LUMINANCE_ALPHA32I_EXT:
2069    case GL_LUMINANCE_ALPHA32UI_EXT:
2070       return ctx->API == API_OPENGL_COMPAT &&
2071              ctx->Extensions.EXT_texture_integer &&
2072              ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2073 
2074    case GL_ALPHA8I_EXT:
2075    case GL_ALPHA8UI_EXT:
2076    case GL_ALPHA16I_EXT:
2077    case GL_ALPHA16UI_EXT:
2078    case GL_ALPHA32I_EXT:
2079    case GL_ALPHA32UI_EXT:
2080       return ctx->API == API_OPENGL_COMPAT &&
2081              ctx->Extensions.EXT_texture_integer &&
2082              ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2083 
2084    case GL_RGB10_A2UI:
2085       return (_mesa_is_desktop_gl(ctx) &&
2086               ctx->Extensions.ARB_texture_rgb10_a2ui)
2087          || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
2088 
2089    case GL_RGB565:
2090       return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
2091          ? GL_RGB : 0;
2092    default:
2093       return 0;
2094    }
2095 }
2096 
2097 
2098 /**
2099  * Invalidate a renderbuffer attachment.  Called from _mesa_HashWalk().
2100  */
2101 static void
invalidate_rb(GLuint key,void * data,void * userData)2102 invalidate_rb(GLuint key, void *data, void *userData)
2103 {
2104    struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2105    struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
2106 
2107    /* If this is a user-created FBO */
2108    if (_mesa_is_user_fbo(fb)) {
2109       GLuint i;
2110       for (i = 0; i < BUFFER_COUNT; i++) {
2111          struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2112          if (att->Type == GL_RENDERBUFFER &&
2113              att->Renderbuffer == rb) {
2114             /* Mark fb status as indeterminate to force re-validation */
2115             fb->_Status = 0;
2116             return;
2117          }
2118       }
2119    }
2120 }
2121 
2122 
2123 /** sentinal value, see below */
2124 #define NO_SAMPLES 1000
2125 
2126 void
_mesa_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples)2127 _mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2128                            GLenum internalFormat, GLsizei width,
2129                            GLsizei height, GLsizei samples)
2130 {
2131    const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2132 
2133    assert(baseFormat != 0);
2134    assert(width >= 0 && width <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2135    assert(height >= 0 && height <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2136    assert(samples != NO_SAMPLES);
2137    if (samples != 0) {
2138       assert(samples > 0);
2139       assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
2140                                       internalFormat, samples) == GL_NO_ERROR);
2141    }
2142 
2143    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2144 
2145    if (rb->InternalFormat == internalFormat &&
2146        rb->Width == (GLuint) width &&
2147        rb->Height == (GLuint) height &&
2148        rb->NumSamples == samples) {
2149       /* no change in allocation needed */
2150       return;
2151    }
2152 
2153    /* These MUST get set by the AllocStorage func */
2154    rb->Format = MESA_FORMAT_NONE;
2155    rb->NumSamples = samples;
2156 
2157    /* Now allocate the storage */
2158    assert(rb->AllocStorage);
2159    if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
2160       /* No error - check/set fields now */
2161       /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
2162       assert(rb->Width == (GLuint) width);
2163       assert(rb->Height == (GLuint) height);
2164       rb->InternalFormat = internalFormat;
2165       rb->_BaseFormat = baseFormat;
2166       assert(rb->_BaseFormat != 0);
2167    }
2168    else {
2169       /* Probably ran out of memory - clear the fields */
2170       rb->Width = 0;
2171       rb->Height = 0;
2172       rb->Format = MESA_FORMAT_NONE;
2173       rb->InternalFormat = GL_NONE;
2174       rb->_BaseFormat = GL_NONE;
2175       rb->NumSamples = 0;
2176    }
2177 
2178    /* Invalidate the framebuffers the renderbuffer is attached in. */
2179    if (rb->AttachedAnytime) {
2180       _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
2181    }
2182 }
2183 
2184 /**
2185  * Helper function used by renderbuffer_storage_direct() and
2186  * renderbuffer_storage_target().
2187  * samples will be NO_SAMPLES if called by a non-multisample function.
2188  */
2189 static void
renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples,const char * func)2190 renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2191                      GLenum internalFormat, GLsizei width,
2192                      GLsizei height, GLsizei samples, const char *func)
2193 {
2194    GLenum baseFormat;
2195    GLenum sample_count_error;
2196 
2197    baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2198    if (baseFormat == 0) {
2199       _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
2200                   func, _mesa_enum_to_string(internalFormat));
2201       return;
2202    }
2203 
2204    if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
2205       _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
2206                   width);
2207       return;
2208    }
2209 
2210    if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
2211       _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
2212                   height);
2213       return;
2214    }
2215 
2216    if (samples == NO_SAMPLES) {
2217       /* NumSamples == 0 indicates non-multisampling */
2218       samples = 0;
2219    }
2220    else {
2221       /* check the sample count;
2222        * note: driver may choose to use more samples than what's requested
2223        */
2224       sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
2225             internalFormat, samples);
2226 
2227       /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
2228        *
2229        * "If a negative number is provided where an argument of type sizei or
2230        * sizeiptr is specified, the error INVALID VALUE is generated."
2231        */
2232       if (samples < 0) {
2233          sample_count_error = GL_INVALID_VALUE;
2234       }
2235 
2236       if (sample_count_error != GL_NO_ERROR) {
2237          _mesa_error(ctx, sample_count_error, "%s(samples=%d)", func, samples);
2238          return;
2239       }
2240    }
2241 
2242    _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples);
2243 }
2244 
2245 /**
2246  * Helper function used by _mesa_NamedRenderbufferStorage*().
2247  * samples will be NO_SAMPLES if called by a non-multisample function.
2248  */
2249 static void
renderbuffer_storage_named(GLuint renderbuffer,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples,const char * func)2250 renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
2251                            GLsizei width, GLsizei height, GLsizei samples,
2252                            const char *func)
2253 {
2254    GET_CURRENT_CONTEXT(ctx);
2255 
2256    if (MESA_VERBOSE & VERBOSE_API) {
2257       if (samples == NO_SAMPLES)
2258          _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
2259                      func, renderbuffer,
2260                      _mesa_enum_to_string(internalFormat),
2261                      width, height);
2262       else
2263          _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
2264                      func, renderbuffer,
2265                      _mesa_enum_to_string(internalFormat),
2266                      width, height, samples);
2267    }
2268 
2269    struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2270    if (!rb || rb == &DummyRenderbuffer) {
2271       /* ID was reserved, but no real renderbuffer object made yet */
2272       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
2273                   func, renderbuffer);
2274       return;
2275    }
2276 
2277    renderbuffer_storage(ctx, rb, internalFormat, width, height, samples, func);
2278 }
2279 
2280 /**
2281  * Helper function used by _mesa_RenderbufferStorage() and
2282  * _mesa_RenderbufferStorageMultisample().
2283  * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
2284  */
2285 static void
renderbuffer_storage_target(GLenum target,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei samples,const char * func)2286 renderbuffer_storage_target(GLenum target, GLenum internalFormat,
2287                             GLsizei width, GLsizei height, GLsizei samples,
2288                             const char *func)
2289 {
2290    GET_CURRENT_CONTEXT(ctx);
2291 
2292    if (MESA_VERBOSE & VERBOSE_API) {
2293       if (samples == NO_SAMPLES)
2294          _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
2295                      func,
2296                      _mesa_enum_to_string(target),
2297                      _mesa_enum_to_string(internalFormat),
2298                      width, height);
2299       else
2300          _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
2301                      func,
2302                      _mesa_enum_to_string(target),
2303                      _mesa_enum_to_string(internalFormat),
2304                      width, height, samples);
2305    }
2306 
2307    if (target != GL_RENDERBUFFER_EXT) {
2308       _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
2309       return;
2310    }
2311 
2312    if (!ctx->CurrentRenderbuffer) {
2313       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
2314                   func);
2315       return;
2316    }
2317 
2318    renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
2319                         height, samples, func);
2320 }
2321 
2322 
2323 void GLAPIENTRY
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target,GLeglImageOES image)2324 _mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
2325 {
2326    struct gl_renderbuffer *rb;
2327    GET_CURRENT_CONTEXT(ctx);
2328 
2329    if (!ctx->Extensions.OES_EGL_image) {
2330       _mesa_error(ctx, GL_INVALID_OPERATION,
2331                   "glEGLImageTargetRenderbufferStorageOES(unsupported)");
2332       return;
2333    }
2334 
2335    if (target != GL_RENDERBUFFER) {
2336       _mesa_error(ctx, GL_INVALID_ENUM,
2337                   "EGLImageTargetRenderbufferStorageOES");
2338       return;
2339    }
2340 
2341    rb = ctx->CurrentRenderbuffer;
2342    if (!rb) {
2343       _mesa_error(ctx, GL_INVALID_OPERATION,
2344                   "EGLImageTargetRenderbufferStorageOES");
2345       return;
2346    }
2347 
2348    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2349 
2350    ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
2351 }
2352 
2353 
2354 /**
2355  * Helper function for _mesa_GetRenderbufferParameteriv() and
2356  * _mesa_GetFramebufferAttachmentParameteriv()
2357  * We have to be careful to respect the base format.  For example, if a
2358  * renderbuffer/texture was created with internalFormat=GL_RGB but the
2359  * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
2360  * we need to return zero.
2361  */
2362 static GLint
get_component_bits(GLenum pname,GLenum baseFormat,mesa_format format)2363 get_component_bits(GLenum pname, GLenum baseFormat, mesa_format format)
2364 {
2365    if (_mesa_base_format_has_channel(baseFormat, pname))
2366       return _mesa_get_format_bits(format, pname);
2367    else
2368       return 0;
2369 }
2370 
2371 
2372 
2373 void GLAPIENTRY
_mesa_RenderbufferStorage(GLenum target,GLenum internalFormat,GLsizei width,GLsizei height)2374 _mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
2375                              GLsizei width, GLsizei height)
2376 {
2377    /* GL_ARB_fbo says calling this function is equivalent to calling
2378     * glRenderbufferStorageMultisample() with samples=0.  We pass in
2379     * a token value here just for error reporting purposes.
2380     */
2381    renderbuffer_storage_target(target, internalFormat, width, height,
2382                                NO_SAMPLES, "glRenderbufferStorage");
2383 }
2384 
2385 
2386 void GLAPIENTRY
_mesa_RenderbufferStorageMultisample(GLenum target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height)2387 _mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
2388                                      GLenum internalFormat,
2389                                      GLsizei width, GLsizei height)
2390 {
2391    renderbuffer_storage_target(target, internalFormat, width, height,
2392                                samples, "glRenderbufferStorageMultisample");
2393 }
2394 
2395 
2396 /**
2397  * OpenGL ES version of glRenderBufferStorage.
2398  */
2399 void GLAPIENTRY
_es_RenderbufferStorageEXT(GLenum target,GLenum internalFormat,GLsizei width,GLsizei height)2400 _es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
2401                            GLsizei width, GLsizei height)
2402 {
2403    switch (internalFormat) {
2404    case GL_RGB565:
2405       /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
2406       /* choose a closest format */
2407       internalFormat = GL_RGB5;
2408       break;
2409    default:
2410       break;
2411    }
2412 
2413    renderbuffer_storage_target(target, internalFormat, width, height, 0,
2414                                "glRenderbufferStorageEXT");
2415 }
2416 
2417 void GLAPIENTRY
_mesa_NamedRenderbufferStorage(GLuint renderbuffer,GLenum internalformat,GLsizei width,GLsizei height)2418 _mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
2419                                GLsizei width, GLsizei height)
2420 {
2421    /* GL_ARB_fbo says calling this function is equivalent to calling
2422     * glRenderbufferStorageMultisample() with samples=0.  We pass in
2423     * a token value here just for error reporting purposes.
2424     */
2425    renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2426                               NO_SAMPLES, "glNamedRenderbufferStorage");
2427 }
2428 
2429 void GLAPIENTRY
_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)2430 _mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
2431                                           GLenum internalformat,
2432                                           GLsizei width, GLsizei height)
2433 {
2434    renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2435                               samples,
2436                               "glNamedRenderbufferStorageMultisample");
2437 }
2438 
2439 
2440 static void
get_render_buffer_parameteriv(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum pname,GLint * params,const char * func)2441 get_render_buffer_parameteriv(struct gl_context *ctx,
2442                               struct gl_renderbuffer *rb, GLenum pname,
2443                               GLint *params, const char *func)
2444 {
2445    /* No need to flush here since we're just quering state which is
2446     * not effected by rendering.
2447     */
2448 
2449    switch (pname) {
2450    case GL_RENDERBUFFER_WIDTH_EXT:
2451       *params = rb->Width;
2452       return;
2453    case GL_RENDERBUFFER_HEIGHT_EXT:
2454       *params = rb->Height;
2455       return;
2456    case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
2457       *params = rb->InternalFormat;
2458       return;
2459    case GL_RENDERBUFFER_RED_SIZE_EXT:
2460    case GL_RENDERBUFFER_GREEN_SIZE_EXT:
2461    case GL_RENDERBUFFER_BLUE_SIZE_EXT:
2462    case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
2463    case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
2464    case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
2465       *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
2466       break;
2467    case GL_RENDERBUFFER_SAMPLES:
2468       if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
2469           || _mesa_is_gles3(ctx)) {
2470          *params = rb->NumSamples;
2471          break;
2472       }
2473       /* fallthrough */
2474    default:
2475       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
2476                   _mesa_enum_to_string(pname));
2477       return;
2478    }
2479 }
2480 
2481 
2482 void GLAPIENTRY
_mesa_GetRenderbufferParameteriv(GLenum target,GLenum pname,GLint * params)2483 _mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
2484 {
2485    GET_CURRENT_CONTEXT(ctx);
2486 
2487    if (target != GL_RENDERBUFFER_EXT) {
2488       _mesa_error(ctx, GL_INVALID_ENUM,
2489                   "glGetRenderbufferParameterivEXT(target)");
2490       return;
2491    }
2492 
2493    if (!ctx->CurrentRenderbuffer) {
2494       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
2495                   "(no renderbuffer bound)");
2496       return;
2497    }
2498 
2499    get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
2500                                  params, "glGetRenderbufferParameteriv");
2501 }
2502 
2503 
2504 void GLAPIENTRY
_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer,GLenum pname,GLint * params)2505 _mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
2506                                       GLint *params)
2507 {
2508    GET_CURRENT_CONTEXT(ctx);
2509 
2510    struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2511    if (!rb || rb == &DummyRenderbuffer) {
2512       /* ID was reserved, but no real renderbuffer object made yet */
2513       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
2514                   "(invalid renderbuffer %i)", renderbuffer);
2515       return;
2516    }
2517 
2518    get_render_buffer_parameteriv(ctx, rb, pname, params,
2519                                  "glGetNamedRenderbufferParameteriv");
2520 }
2521 
2522 
2523 GLboolean GLAPIENTRY
_mesa_IsFramebuffer(GLuint framebuffer)2524 _mesa_IsFramebuffer(GLuint framebuffer)
2525 {
2526    GET_CURRENT_CONTEXT(ctx);
2527    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2528    if (framebuffer) {
2529       struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
2530       if (rb != NULL && rb != &DummyFramebuffer)
2531          return GL_TRUE;
2532    }
2533    return GL_FALSE;
2534 }
2535 
2536 
2537 /**
2538  * Check if any of the attachments of the given framebuffer are textures
2539  * (render to texture).  Call ctx->Driver.RenderTexture() for such
2540  * attachments.
2541  */
2542 static void
check_begin_texture_render(struct gl_context * ctx,struct gl_framebuffer * fb)2543 check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
2544 {
2545    GLuint i;
2546    assert(ctx->Driver.RenderTexture);
2547 
2548    if (_mesa_is_winsys_fbo(fb))
2549       return; /* can't render to texture with winsys framebuffers */
2550 
2551    for (i = 0; i < BUFFER_COUNT; i++) {
2552       struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2553       if (att->Texture && att->Renderbuffer->TexImage
2554           && driver_RenderTexture_is_safe(att)) {
2555          ctx->Driver.RenderTexture(ctx, fb, att);
2556       }
2557    }
2558 }
2559 
2560 
2561 /**
2562  * Examine all the framebuffer's attachments to see if any are textures.
2563  * If so, call ctx->Driver.FinishRenderTexture() for each texture to
2564  * notify the device driver that the texture image may have changed.
2565  */
2566 static void
check_end_texture_render(struct gl_context * ctx,struct gl_framebuffer * fb)2567 check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
2568 {
2569    /* Skip if we know NeedsFinishRenderTexture won't be set. */
2570    if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
2571       return;
2572 
2573    if (ctx->Driver.FinishRenderTexture) {
2574       GLuint i;
2575       for (i = 0; i < BUFFER_COUNT; i++) {
2576          struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2577          struct gl_renderbuffer *rb = att->Renderbuffer;
2578          if (rb && rb->NeedsFinishRenderTexture) {
2579             ctx->Driver.FinishRenderTexture(ctx, rb);
2580          }
2581       }
2582    }
2583 }
2584 
2585 
2586 static void
bind_framebuffer(GLenum target,GLuint framebuffer,bool allow_user_names)2587 bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names)
2588 {
2589    struct gl_framebuffer *newDrawFb, *newReadFb;
2590    GLboolean bindReadBuf, bindDrawBuf;
2591    GET_CURRENT_CONTEXT(ctx);
2592 
2593    switch (target) {
2594    case GL_DRAW_FRAMEBUFFER_EXT:
2595       bindDrawBuf = GL_TRUE;
2596       bindReadBuf = GL_FALSE;
2597       break;
2598    case GL_READ_FRAMEBUFFER_EXT:
2599       bindDrawBuf = GL_FALSE;
2600       bindReadBuf = GL_TRUE;
2601       break;
2602    case GL_FRAMEBUFFER_EXT:
2603       bindDrawBuf = GL_TRUE;
2604       bindReadBuf = GL_TRUE;
2605       break;
2606    default:
2607       _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2608       return;
2609    }
2610 
2611    if (framebuffer) {
2612       /* Binding a user-created framebuffer object */
2613       newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
2614       if (newDrawFb == &DummyFramebuffer) {
2615          /* ID was reserved, but no real framebuffer object made yet */
2616          newDrawFb = NULL;
2617       }
2618       else if (!newDrawFb && !allow_user_names) {
2619          /* All FBO IDs must be Gen'd */
2620          _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
2621          return;
2622       }
2623 
2624       if (!newDrawFb) {
2625          /* create new framebuffer object */
2626          newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
2627          if (!newDrawFb) {
2628             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
2629             return;
2630          }
2631          _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
2632       }
2633       newReadFb = newDrawFb;
2634    }
2635    else {
2636       /* Binding the window system framebuffer (which was originally set
2637        * with MakeCurrent).
2638        */
2639       newDrawFb = ctx->WinSysDrawBuffer;
2640       newReadFb = ctx->WinSysReadBuffer;
2641    }
2642 
2643    _mesa_bind_framebuffers(ctx,
2644                            bindDrawBuf ? newDrawFb : ctx->DrawBuffer,
2645                            bindReadBuf ? newReadFb : ctx->ReadBuffer);
2646 }
2647 
2648 void
_mesa_bind_framebuffers(struct gl_context * ctx,struct gl_framebuffer * newDrawFb,struct gl_framebuffer * newReadFb)2649 _mesa_bind_framebuffers(struct gl_context *ctx,
2650                         struct gl_framebuffer *newDrawFb,
2651                         struct gl_framebuffer *newReadFb)
2652 {
2653    struct gl_framebuffer *const oldDrawFb = ctx->DrawBuffer;
2654    struct gl_framebuffer *const oldReadFb = ctx->ReadBuffer;
2655    const bool bindDrawBuf = oldDrawFb != newDrawFb;
2656    const bool bindReadBuf = oldReadFb != newReadFb;
2657 
2658    assert(newDrawFb);
2659    assert(newDrawFb != &DummyFramebuffer);
2660 
2661    /*
2662     * OK, now bind the new Draw/Read framebuffers, if they're changing.
2663     *
2664     * We also check if we're beginning and/or ending render-to-texture.
2665     * When a framebuffer with texture attachments is unbound, call
2666     * ctx->Driver.FinishRenderTexture().
2667     * When a framebuffer with texture attachments is bound, call
2668     * ctx->Driver.RenderTexture().
2669     *
2670     * Note that if the ReadBuffer has texture attachments we don't consider
2671     * that a render-to-texture case.
2672     */
2673    if (bindReadBuf) {
2674       FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2675 
2676       /* check if old readbuffer was render-to-texture */
2677       check_end_texture_render(ctx, oldReadFb);
2678 
2679       _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
2680    }
2681 
2682    if (bindDrawBuf) {
2683       FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2684 
2685       /* check if old framebuffer had any texture attachments */
2686       if (oldDrawFb)
2687          check_end_texture_render(ctx, oldDrawFb);
2688 
2689       /* check if newly bound framebuffer has any texture attachments */
2690       check_begin_texture_render(ctx, newDrawFb);
2691 
2692       _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
2693    }
2694 
2695    if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
2696       /* The few classic drivers that actually hook this function really only
2697        * want to know if the draw framebuffer changed.
2698        */
2699       ctx->Driver.BindFramebuffer(ctx,
2700                                   bindDrawBuf ? GL_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
2701                                   newDrawFb, newReadFb);
2702    }
2703 }
2704 
2705 void GLAPIENTRY
_mesa_BindFramebuffer(GLenum target,GLuint framebuffer)2706 _mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
2707 {
2708    GET_CURRENT_CONTEXT(ctx);
2709 
2710    /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
2711     * point, but they allow the use of user-generated names.
2712     */
2713    bind_framebuffer(target, framebuffer, _mesa_is_gles(ctx));
2714 }
2715 
2716 
2717 void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target,GLuint framebuffer)2718 _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
2719 {
2720    /* This function should not be in the dispatch table for core profile /
2721     * OpenGL 3.1, so execution should never get here in those cases -- no
2722     * need for an explicit test.
2723     */
2724    bind_framebuffer(target, framebuffer, true);
2725 }
2726 
2727 
2728 void GLAPIENTRY
_mesa_DeleteFramebuffers(GLsizei n,const GLuint * framebuffers)2729 _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
2730 {
2731    GLint i;
2732    GET_CURRENT_CONTEXT(ctx);
2733 
2734    if (n < 0) {
2735       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
2736       return;
2737    }
2738 
2739    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2740 
2741    for (i = 0; i < n; i++) {
2742       if (framebuffers[i] > 0) {
2743          struct gl_framebuffer *fb;
2744          fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
2745          if (fb) {
2746             assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
2747 
2748             /* check if deleting currently bound framebuffer object */
2749             if (fb == ctx->DrawBuffer) {
2750                /* bind default */
2751                assert(fb->RefCount >= 2);
2752                _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
2753             }
2754             if (fb == ctx->ReadBuffer) {
2755                /* bind default */
2756                assert(fb->RefCount >= 2);
2757                _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
2758             }
2759 
2760             /* remove from hash table immediately, to free the ID */
2761             _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
2762 
2763             if (fb != &DummyFramebuffer) {
2764                /* But the object will not be freed until it's no longer
2765                 * bound in any context.
2766                 */
2767                _mesa_reference_framebuffer(&fb, NULL);
2768             }
2769          }
2770       }
2771    }
2772 }
2773 
2774 
2775 /**
2776  * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
2777  * It is not exposed to the rest of Mesa to encourage the use of
2778  * nameless buffers in driver internals.
2779  */
2780 static void
create_framebuffers(GLsizei n,GLuint * framebuffers,bool dsa)2781 create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
2782 {
2783    GET_CURRENT_CONTEXT(ctx);
2784    GLuint first;
2785    GLint i;
2786    struct gl_framebuffer *fb;
2787 
2788    const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
2789 
2790    if (n < 0) {
2791       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
2792       return;
2793    }
2794 
2795    if (!framebuffers)
2796       return;
2797 
2798    _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
2799 
2800    first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
2801 
2802    for (i = 0; i < n; i++) {
2803       GLuint name = first + i;
2804       framebuffers[i] = name;
2805 
2806       if (dsa) {
2807          fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
2808          if (!fb) {
2809             _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
2810             _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
2811             return;
2812          }
2813       }
2814       else
2815          fb = &DummyFramebuffer;
2816 
2817       _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, name, fb);
2818    }
2819 
2820    _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
2821 }
2822 
2823 
2824 void GLAPIENTRY
_mesa_GenFramebuffers(GLsizei n,GLuint * framebuffers)2825 _mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
2826 {
2827    create_framebuffers(n, framebuffers, false);
2828 }
2829 
2830 
2831 void GLAPIENTRY
_mesa_CreateFramebuffers(GLsizei n,GLuint * framebuffers)2832 _mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
2833 {
2834    create_framebuffers(n, framebuffers, true);
2835 }
2836 
2837 
2838 GLenum
_mesa_check_framebuffer_status(struct gl_context * ctx,struct gl_framebuffer * buffer)2839 _mesa_check_framebuffer_status(struct gl_context *ctx,
2840                                struct gl_framebuffer *buffer)
2841 {
2842    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
2843 
2844    if (_mesa_is_winsys_fbo(buffer)) {
2845       /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
2846       if (buffer != &IncompleteFramebuffer) {
2847          return GL_FRAMEBUFFER_COMPLETE_EXT;
2848       } else {
2849          return GL_FRAMEBUFFER_UNDEFINED;
2850       }
2851    }
2852 
2853    /* No need to flush here */
2854 
2855    if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
2856       _mesa_test_framebuffer_completeness(ctx, buffer);
2857    }
2858 
2859    return buffer->_Status;
2860 }
2861 
2862 
2863 GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus_no_error(GLenum target)2864 _mesa_CheckFramebufferStatus_no_error(GLenum target)
2865 {
2866    GET_CURRENT_CONTEXT(ctx);
2867 
2868    struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
2869    return _mesa_check_framebuffer_status(ctx, fb);
2870 }
2871 
2872 
2873 GLenum GLAPIENTRY
_mesa_CheckFramebufferStatus(GLenum target)2874 _mesa_CheckFramebufferStatus(GLenum target)
2875 {
2876    struct gl_framebuffer *fb;
2877    GET_CURRENT_CONTEXT(ctx);
2878 
2879    if (MESA_VERBOSE & VERBOSE_API)
2880       _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
2881                   _mesa_enum_to_string(target));
2882 
2883    fb = get_framebuffer_target(ctx, target);
2884    if (!fb) {
2885       _mesa_error(ctx, GL_INVALID_ENUM,
2886                   "glCheckFramebufferStatus(invalid target %s)",
2887                   _mesa_enum_to_string(target));
2888       return 0;
2889    }
2890 
2891    return _mesa_check_framebuffer_status(ctx, fb);
2892 }
2893 
2894 
2895 GLenum GLAPIENTRY
_mesa_CheckNamedFramebufferStatus(GLuint framebuffer,GLenum target)2896 _mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
2897 {
2898    struct gl_framebuffer *fb;
2899    GET_CURRENT_CONTEXT(ctx);
2900 
2901    /* Validate the target (for conformance's sake) and grab a reference to the
2902     * default framebuffer in case framebuffer = 0.
2903     * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
2904     * (30.10.2014, PDF page 336) says:
2905     *    "If framebuffer is zero, then the status of the default read or
2906     *    draw framebuffer (as determined by target) is returned."
2907     */
2908    switch (target) {
2909       case GL_DRAW_FRAMEBUFFER:
2910       case GL_FRAMEBUFFER:
2911          fb = ctx->WinSysDrawBuffer;
2912          break;
2913       case GL_READ_FRAMEBUFFER:
2914          fb = ctx->WinSysReadBuffer;
2915          break;
2916       default:
2917          _mesa_error(ctx, GL_INVALID_ENUM,
2918                      "glCheckNamedFramebufferStatus(invalid target %s)",
2919                      _mesa_enum_to_string(target));
2920          return 0;
2921    }
2922 
2923    if (framebuffer) {
2924       fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
2925                                         "glCheckNamedFramebufferStatus");
2926       if (!fb)
2927          return 0;
2928    }
2929 
2930    return _mesa_check_framebuffer_status(ctx, fb);
2931 }
2932 
2933 
2934 /**
2935  * Replicate the src attachment point. Used by framebuffer_texture() when
2936  * the same texture is attached at GL_DEPTH_ATTACHMENT and
2937  * GL_STENCIL_ATTACHMENT.
2938  */
2939 static void
reuse_framebuffer_texture_attachment(struct gl_framebuffer * fb,gl_buffer_index dst,gl_buffer_index src)2940 reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
2941                                      gl_buffer_index dst,
2942                                      gl_buffer_index src)
2943 {
2944    struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
2945    struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
2946 
2947    assert(src_att->Texture != NULL);
2948    assert(src_att->Renderbuffer != NULL);
2949 
2950    _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
2951    _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
2952    dst_att->Type = src_att->Type;
2953    dst_att->Complete = src_att->Complete;
2954    dst_att->TextureLevel = src_att->TextureLevel;
2955    dst_att->CubeMapFace = src_att->CubeMapFace;
2956    dst_att->Zoffset = src_att->Zoffset;
2957    dst_att->Layered = src_att->Layered;
2958 }
2959 
2960 
2961 static struct gl_texture_object *
get_texture_for_framebuffer(struct gl_context * ctx,GLuint texture)2962 get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
2963 {
2964    if (!texture)
2965       return NULL;
2966 
2967    return _mesa_lookup_texture(ctx, texture);
2968 }
2969 
2970 
2971 /**
2972  * Common code called by gl*FramebufferTexture*() to retrieve the correct
2973  * texture object pointer.
2974  *
2975  * \param texObj where the pointer to the texture object is returned.  Note
2976  * that a successful call may return texObj = NULL.
2977  *
2978  * \return true if no errors, false if errors
2979  */
2980 static bool
get_texture_for_framebuffer_err(struct gl_context * ctx,GLuint texture,bool layered,const char * caller,struct gl_texture_object ** texObj)2981 get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
2982                                 bool layered, const char *caller,
2983                                 struct gl_texture_object **texObj)
2984 {
2985    *texObj = NULL; /* This will get returned if texture = 0. */
2986 
2987    if (!texture)
2988       return true;
2989 
2990    *texObj = _mesa_lookup_texture(ctx, texture);
2991    if (*texObj == NULL || (*texObj)->Target == 0) {
2992       /* Can't render to a non-existent texture object.
2993        *
2994        * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
2995        * Managing Framebuffer Objects specifies a different error
2996        * depending upon the calling function (PDF pages 325-328).
2997        * *FramebufferTexture (where layered = GL_TRUE) throws invalid
2998        * value, while the other commands throw invalid operation (where
2999        * layered = GL_FALSE).
3000        */
3001       const GLenum error = layered ? GL_INVALID_VALUE :
3002                            GL_INVALID_OPERATION;
3003       _mesa_error(ctx, error,
3004                   "%s(non-existent texture %u)", caller, texture);
3005       return false;
3006    }
3007 
3008    return true;
3009 }
3010 
3011 
3012 /**
3013  * Common code called by gl*FramebufferTexture() to verify the texture target
3014  * and decide whether or not the attachment should truly be considered
3015  * layered.
3016  *
3017  * \param layered true if attachment should be considered layered, false if
3018  * not
3019  *
3020  * \return true if no errors, false if errors
3021  */
3022 static bool
check_layered_texture_target(struct gl_context * ctx,GLenum target,const char * caller,GLboolean * layered)3023 check_layered_texture_target(struct gl_context *ctx, GLenum target,
3024                              const char *caller, GLboolean *layered)
3025 {
3026    *layered = GL_TRUE;
3027 
3028    switch (target) {
3029    case GL_TEXTURE_3D:
3030    case GL_TEXTURE_1D_ARRAY_EXT:
3031    case GL_TEXTURE_2D_ARRAY_EXT:
3032    case GL_TEXTURE_CUBE_MAP:
3033    case GL_TEXTURE_CUBE_MAP_ARRAY:
3034    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3035       return true;
3036    case GL_TEXTURE_1D:
3037    case GL_TEXTURE_2D:
3038    case GL_TEXTURE_RECTANGLE:
3039    case GL_TEXTURE_2D_MULTISAMPLE:
3040       /* These texture types are valid to pass to
3041        * glFramebufferTexture(), but since they aren't layered, it
3042        * is equivalent to calling glFramebufferTexture{1D,2D}().
3043        */
3044       *layered = GL_FALSE;
3045       return true;
3046    }
3047 
3048    _mesa_error(ctx, GL_INVALID_OPERATION,
3049                "%s(invalid texture target %s)", caller,
3050                _mesa_enum_to_string(target));
3051    return false;
3052 }
3053 
3054 
3055 /**
3056  * Common code called by gl*FramebufferTextureLayer() to verify the texture
3057  * target.
3058  *
3059  * \return true if no errors, false if errors
3060  */
3061 static bool
check_texture_target(struct gl_context * ctx,GLenum target,const char * caller)3062 check_texture_target(struct gl_context *ctx, GLenum target,
3063                      const char *caller)
3064 {
3065    /* We're being called by glFramebufferTextureLayer().
3066     * The only legal texture types for that function are 3D,
3067     * cube-map, and 1D/2D/cube-map array textures.
3068     *
3069     * We don't need to check for GL_ARB_texture_cube_map_array because the
3070     * application wouldn't have been able to create a texture with a
3071     * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
3072     */
3073    switch (target) {
3074    case GL_TEXTURE_3D:
3075    case GL_TEXTURE_1D_ARRAY:
3076    case GL_TEXTURE_2D_ARRAY:
3077    case GL_TEXTURE_CUBE_MAP_ARRAY:
3078    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3079       return true;
3080    case GL_TEXTURE_CUBE_MAP:
3081       /* We don't need to check the extension (GL_ARB_direct_state_access) or
3082        * GL version (4.5) for GL_TEXTURE_CUBE_MAP because DSA is always
3083        * enabled in core profile.  This can be called from
3084        * _mesa_FramebufferTextureLayer in compatibility profile (OpenGL 3.0),
3085        * so we do have to check the profile.
3086        */
3087       return ctx->API == API_OPENGL_CORE;
3088    }
3089 
3090    _mesa_error(ctx, GL_INVALID_OPERATION,
3091                "%s(invalid texture target %s)", caller,
3092                _mesa_enum_to_string(target));
3093    return false;
3094 }
3095 
3096 
3097 /**
3098  * Common code called by glFramebufferTexture*D() to verify the texture
3099  * target.
3100  *
3101  * \return true if no errors, false if errors
3102  */
3103 static bool
check_textarget(struct gl_context * ctx,int dims,GLenum target,GLenum textarget,const char * caller)3104 check_textarget(struct gl_context *ctx, int dims, GLenum target,
3105                 GLenum textarget, const char *caller)
3106 {
3107    bool err = false;
3108 
3109    switch (textarget) {
3110    case GL_TEXTURE_1D:
3111       err = dims != 1;
3112       break;
3113    case GL_TEXTURE_1D_ARRAY:
3114       err = dims != 1 || !ctx->Extensions.EXT_texture_array;
3115       break;
3116    case GL_TEXTURE_2D:
3117       err = dims != 2;
3118       break;
3119    case GL_TEXTURE_2D_ARRAY:
3120       err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
3121             (_mesa_is_gles(ctx) && ctx->Version < 30);
3122       break;
3123    case GL_TEXTURE_2D_MULTISAMPLE:
3124    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3125       err = dims != 2 ||
3126             !ctx->Extensions.ARB_texture_multisample ||
3127             (_mesa_is_gles(ctx) && ctx->Version < 31);
3128       break;
3129    case GL_TEXTURE_RECTANGLE:
3130       err = dims != 2 || _mesa_is_gles(ctx) ||
3131             !ctx->Extensions.NV_texture_rectangle;
3132       break;
3133    case GL_TEXTURE_CUBE_MAP:
3134    case GL_TEXTURE_CUBE_MAP_ARRAY:
3135       err = true;
3136       break;
3137    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3138    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3139    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3140    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3141    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3142    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3143       err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
3144       break;
3145    case GL_TEXTURE_3D:
3146       err = dims != 3;
3147       break;
3148    default:
3149       _mesa_error(ctx, GL_INVALID_ENUM,
3150                   "%s(unknown textarget 0x%x)", caller, textarget);
3151       return false;
3152    }
3153 
3154    if (err) {
3155       _mesa_error(ctx, GL_INVALID_OPERATION,
3156                   "%s(invalid textarget %s)",
3157                   caller, _mesa_enum_to_string(textarget));
3158       return false;
3159    }
3160 
3161    /* Make sure textarget is consistent with the texture's type */
3162    err = (target == GL_TEXTURE_CUBE_MAP) ?
3163           !_mesa_is_cube_face(textarget): (target != textarget);
3164 
3165    if (err) {
3166       _mesa_error(ctx, GL_INVALID_OPERATION,
3167                   "%s(mismatched texture target)", caller);
3168       return false;
3169    }
3170 
3171    return true;
3172 }
3173 
3174 
3175 /**
3176  * Common code called by gl*FramebufferTextureLayer() and
3177  * glFramebufferTexture3D() to validate the layer.
3178  *
3179  * \return true if no errors, false if errors
3180  */
3181 static bool
check_layer(struct gl_context * ctx,GLenum target,GLint layer,const char * caller)3182 check_layer(struct gl_context *ctx, GLenum target, GLint layer,
3183             const char *caller)
3184 {
3185    /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
3186     * spec says:
3187     *
3188     *    "An INVALID_VALUE error is generated if texture is non-zero
3189     *     and layer is negative."
3190     */
3191    if (layer < 0) {
3192       _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
3193       return false;
3194    }
3195 
3196    if (target == GL_TEXTURE_3D) {
3197       const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
3198       if (layer >= maxSize) {
3199          _mesa_error(ctx, GL_INVALID_VALUE,
3200                      "%s(invalid layer %u)", caller, layer);
3201          return false;
3202       }
3203    }
3204    else if ((target == GL_TEXTURE_1D_ARRAY) ||
3205             (target == GL_TEXTURE_2D_ARRAY) ||
3206             (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
3207             (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
3208       if (layer >= ctx->Const.MaxArrayTextureLayers) {
3209          _mesa_error(ctx, GL_INVALID_VALUE,
3210                      "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
3211                      caller, layer);
3212          return false;
3213       }
3214    }
3215    else if (target == GL_TEXTURE_CUBE_MAP) {
3216       if (layer >= 6) {
3217          _mesa_error(ctx, GL_INVALID_VALUE,
3218                      "%s(layer %u >= 6)", caller, layer);
3219          return false;
3220       }
3221    }
3222 
3223    return true;
3224 }
3225 
3226 
3227 /**
3228  * Common code called by all gl*FramebufferTexture*() entry points to verify
3229  * the level.
3230  *
3231  * \return true if no errors, false if errors
3232  */
3233 static bool
check_level(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum target,GLint level,const char * caller)3234 check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
3235             GLenum target, GLint level, const char *caller)
3236 {
3237    /* Section 9.2.8 of the OpenGL 4.6 specification says:
3238     *
3239     *    "If texture refers to an immutable-format texture, level must be
3240     *     greater than or equal to zero and smaller than the value of
3241     *     TEXTURE_VIEW_NUM_LEVELS for texture."
3242     */
3243    const int max_levels = texObj->Immutable ? texObj->ImmutableLevels :
3244                           _mesa_max_texture_levels(ctx, target);
3245 
3246    if (level < 0 || level >= max_levels) {
3247       _mesa_error(ctx, GL_INVALID_VALUE,
3248                   "%s(invalid level %d)", caller, level);
3249       return false;
3250    }
3251 
3252    return true;
3253 }
3254 
3255 
3256 struct gl_renderbuffer_attachment *
_mesa_get_and_validate_attachment(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,const char * caller)3257 _mesa_get_and_validate_attachment(struct gl_context *ctx,
3258                                   struct gl_framebuffer *fb,
3259                                   GLenum attachment, const char *caller)
3260 {
3261    /* The window-system framebuffer object is immutable */
3262    if (_mesa_is_winsys_fbo(fb)) {
3263       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
3264                   caller);
3265       return NULL;
3266    }
3267 
3268    /* Not a hash lookup, so we can afford to get the attachment here. */
3269    bool is_color_attachment;
3270    struct gl_renderbuffer_attachment *att =
3271       get_attachment(ctx, fb, attachment, &is_color_attachment);
3272    if (att == NULL) {
3273       if (is_color_attachment) {
3274          _mesa_error(ctx, GL_INVALID_OPERATION,
3275                      "%s(invalid color attachment %s)", caller,
3276                      _mesa_enum_to_string(attachment));
3277       } else {
3278          _mesa_error(ctx, GL_INVALID_ENUM,
3279                      "%s(invalid attachment %s)", caller,
3280                      _mesa_enum_to_string(attachment));
3281       }
3282       return NULL;
3283    }
3284 
3285    return att;
3286 }
3287 
3288 
3289 void
_mesa_framebuffer_texture(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer_attachment * att,struct gl_texture_object * texObj,GLenum textarget,GLint level,GLuint layer,GLboolean layered)3290 _mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
3291                           GLenum attachment,
3292                           struct gl_renderbuffer_attachment *att,
3293                           struct gl_texture_object *texObj, GLenum textarget,
3294                           GLint level, GLuint layer, GLboolean layered)
3295 {
3296    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3297 
3298    simple_mtx_lock(&fb->Mutex);
3299    if (texObj) {
3300       if (attachment == GL_DEPTH_ATTACHMENT &&
3301           texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
3302           level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
3303           _mesa_tex_target_to_face(textarget) ==
3304           fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
3305           layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
3306          /* The texture object is already attached to the stencil attachment
3307           * point. Don't create a new renderbuffer; just reuse the stencil
3308           * attachment's. This is required to prevent a GL error in
3309           * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
3310           */
3311          reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
3312                                               BUFFER_STENCIL);
3313       } else if (attachment == GL_STENCIL_ATTACHMENT &&
3314                  texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
3315                  level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
3316                  _mesa_tex_target_to_face(textarget) ==
3317                  fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
3318                  layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
3319          /* As above, but with depth and stencil transposed. */
3320          reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
3321                                               BUFFER_DEPTH);
3322       } else {
3323          set_texture_attachment(ctx, fb, att, texObj, textarget,
3324                                 level, layer, layered);
3325 
3326          if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3327             /* Above we created a new renderbuffer and attached it to the
3328              * depth attachment point. Now attach it to the stencil attachment
3329              * point too.
3330              */
3331             assert(att == &fb->Attachment[BUFFER_DEPTH]);
3332             reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
3333                                                  BUFFER_DEPTH);
3334          }
3335       }
3336 
3337       /* Set the render-to-texture flag.  We'll check this flag in
3338        * glTexImage() and friends to determine if we need to revalidate
3339        * any FBOs that might be rendering into this texture.
3340        * This flag never gets cleared since it's non-trivial to determine
3341        * when all FBOs might be done rendering to this texture.  That's OK
3342        * though since it's uncommon to render to a texture then repeatedly
3343        * call glTexImage() to change images in the texture.
3344        */
3345       texObj->_RenderToTexture = GL_TRUE;
3346    }
3347    else {
3348       remove_attachment(ctx, att);
3349       if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3350          assert(att == &fb->Attachment[BUFFER_DEPTH]);
3351          remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
3352       }
3353    }
3354 
3355    invalidate_framebuffer(fb);
3356 
3357    simple_mtx_unlock(&fb->Mutex);
3358 }
3359 
3360 
3361 static void
framebuffer_texture_with_dims_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint layer)3362 framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
3363                                        GLenum textarget, GLuint texture,
3364                                        GLint level, GLint layer)
3365 {
3366    GET_CURRENT_CONTEXT(ctx);
3367 
3368    /* Get the framebuffer object */
3369    struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3370 
3371    /* Get the texture object */
3372    struct gl_texture_object *texObj =
3373       get_texture_for_framebuffer(ctx, texture);
3374 
3375    struct gl_renderbuffer_attachment *att =
3376       get_attachment(ctx, fb, attachment, NULL);
3377 
3378    _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3379                              level, layer, GL_FALSE);
3380 }
3381 
3382 
3383 static void
framebuffer_texture_with_dims(int dims,GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint layer,const char * caller)3384 framebuffer_texture_with_dims(int dims, GLenum target,
3385                               GLenum attachment, GLenum textarget,
3386                               GLuint texture, GLint level, GLint layer,
3387                               const char *caller)
3388 {
3389    GET_CURRENT_CONTEXT(ctx);
3390    struct gl_framebuffer *fb;
3391    struct gl_texture_object *texObj;
3392 
3393    /* Get the framebuffer object */
3394    fb = get_framebuffer_target(ctx, target);
3395    if (!fb) {
3396       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
3397                   _mesa_enum_to_string(target));
3398       return;
3399    }
3400 
3401    /* Get the texture object */
3402    if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
3403       return;
3404 
3405    if (texObj) {
3406       if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
3407          return;
3408 
3409       if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
3410          return;
3411 
3412       if (!check_level(ctx, texObj, textarget, level, caller))
3413          return;
3414    }
3415 
3416    struct gl_renderbuffer_attachment *att =
3417       _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
3418    if (!att)
3419       return;
3420 
3421    _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3422                              level, layer, GL_FALSE);
3423 }
3424 
3425 
3426 void GLAPIENTRY
_mesa_FramebufferTexture1D_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3427 _mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
3428                                     GLenum textarget, GLuint texture,
3429                                     GLint level)
3430 {
3431    framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3432                                           texture, level, 0);
3433 }
3434 
3435 
3436 void GLAPIENTRY
_mesa_FramebufferTexture1D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3437 _mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
3438                            GLenum textarget, GLuint texture, GLint level)
3439 {
3440    framebuffer_texture_with_dims(1, target, attachment, textarget, texture,
3441                                  level, 0, "glFramebufferTexture1D");
3442 }
3443 
3444 
3445 void GLAPIENTRY
_mesa_FramebufferTexture2D_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3446 _mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
3447                                     GLenum textarget, GLuint texture,
3448                                     GLint level)
3449 {
3450    framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3451                                           texture, level, 0);
3452 }
3453 
3454 
3455 void GLAPIENTRY
_mesa_FramebufferTexture2D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)3456 _mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
3457                            GLenum textarget, GLuint texture, GLint level)
3458 {
3459    framebuffer_texture_with_dims(2, target, attachment, textarget, texture,
3460                                  level, 0, "glFramebufferTexture2D");
3461 }
3462 
3463 
3464 void GLAPIENTRY
_mesa_FramebufferTexture3D_no_error(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint layer)3465 _mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
3466                                     GLenum textarget, GLuint texture,
3467                                     GLint level, GLint layer)
3468 {
3469    framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3470                                           texture, level, layer);
3471 }
3472 
3473 
3474 void GLAPIENTRY
_mesa_FramebufferTexture3D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level,GLint layer)3475 _mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
3476                            GLenum textarget, GLuint texture,
3477                            GLint level, GLint layer)
3478 {
3479    framebuffer_texture_with_dims(3, target, attachment, textarget, texture,
3480                                  level, layer, "glFramebufferTexture3D");
3481 }
3482 
3483 
3484 static ALWAYS_INLINE void
frame_buffer_texture(GLuint framebuffer,GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer,const char * func,bool dsa,bool no_error,bool check_layered)3485 frame_buffer_texture(GLuint framebuffer, GLenum target,
3486                      GLenum attachment, GLuint texture,
3487                      GLint level, GLint layer, const char *func,
3488                      bool dsa, bool no_error, bool check_layered)
3489 {
3490    GET_CURRENT_CONTEXT(ctx);
3491    GLboolean layered = GL_FALSE;
3492 
3493    if (!no_error && check_layered) {
3494       if (!_mesa_has_geometry_shaders(ctx)) {
3495          _mesa_error(ctx, GL_INVALID_OPERATION,
3496                      "unsupported function (%s) called", func);
3497          return;
3498       }
3499    }
3500 
3501    /* Get the framebuffer object */
3502    struct gl_framebuffer *fb;
3503    if (no_error) {
3504       if (dsa) {
3505          fb = _mesa_lookup_framebuffer(ctx, framebuffer);
3506       } else {
3507          fb = get_framebuffer_target(ctx, target);
3508       }
3509    } else {
3510       if (dsa) {
3511          fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
3512          if (!fb)
3513             return;
3514       } else {
3515          fb = get_framebuffer_target(ctx, target);
3516          if (!fb) {
3517             _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
3518                         func, _mesa_enum_to_string(target));
3519             return;
3520          }
3521       }
3522    }
3523 
3524    /* Get the texture object and framebuffer attachment*/
3525    struct gl_renderbuffer_attachment *att;
3526    struct gl_texture_object *texObj;
3527    if (no_error) {
3528       texObj = get_texture_for_framebuffer(ctx, texture);
3529       att = get_attachment(ctx, fb, attachment, NULL);
3530    } else {
3531       if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
3532                                            &texObj))
3533          return;
3534 
3535       att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
3536       if (!att)
3537          return;
3538    }
3539 
3540    GLenum textarget = 0;
3541    if (texObj) {
3542       if (check_layered) {
3543          /* We do this regardless of no_error because this sets layered */
3544          if (!check_layered_texture_target(ctx, texObj->Target, func,
3545                                            &layered))
3546             return;
3547       }
3548 
3549       if (!no_error) {
3550          if (!check_layered) {
3551             if (!check_texture_target(ctx, texObj->Target, func))
3552                return;
3553 
3554             if (!check_layer(ctx, texObj->Target, layer, func))
3555                return;
3556          }
3557 
3558          if (!check_level(ctx, texObj, texObj->Target, level, func))
3559             return;
3560       }
3561 
3562       if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
3563          assert(layer >= 0 && layer < 6);
3564          textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
3565          layer = 0;
3566       }
3567    }
3568 
3569    _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
3570                              level, layer, layered);
3571 }
3572 
3573 void GLAPIENTRY
_mesa_FramebufferTextureLayer_no_error(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)3574 _mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
3575                                        GLuint texture, GLint level,
3576                                        GLint layer)
3577 {
3578    frame_buffer_texture(0, target, attachment, texture, level, layer,
3579                         "glFramebufferTextureLayer", false, true, false);
3580 }
3581 
3582 
3583 void GLAPIENTRY
_mesa_FramebufferTextureLayer(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)3584 _mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
3585                               GLuint texture, GLint level, GLint layer)
3586 {
3587    frame_buffer_texture(0, target, attachment, texture, level, layer,
3588                         "glFramebufferTextureLayer", false, false, false);
3589 }
3590 
3591 
3592 void GLAPIENTRY
_mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level,GLint layer)3593 _mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
3594                                             GLenum attachment,
3595                                             GLuint texture, GLint level,
3596                                             GLint layer)
3597 {
3598    frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3599                         "glNamedFramebufferTextureLayer", true, true, false);
3600 }
3601 
3602 
3603 void GLAPIENTRY
_mesa_NamedFramebufferTextureLayer(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level,GLint layer)3604 _mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
3605                                    GLuint texture, GLint level, GLint layer)
3606 {
3607    frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3608                         "glNamedFramebufferTextureLayer", true, false, false);
3609 }
3610 
3611 
3612 void GLAPIENTRY
_mesa_FramebufferTexture_no_error(GLenum target,GLenum attachment,GLuint texture,GLint level)3613 _mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
3614                                   GLuint texture, GLint level)
3615 {
3616    frame_buffer_texture(0, target, attachment, texture, level, 0,
3617                         "glFramebufferTexture", false, true, true);
3618 }
3619 
3620 
3621 void GLAPIENTRY
_mesa_FramebufferTexture(GLenum target,GLenum attachment,GLuint texture,GLint level)3622 _mesa_FramebufferTexture(GLenum target, GLenum attachment,
3623                          GLuint texture, GLint level)
3624 {
3625    frame_buffer_texture(0, target, attachment, texture, level, 0,
3626                         "glFramebufferTexture", false, false, true);
3627 }
3628 
3629 void GLAPIENTRY
_mesa_NamedFramebufferTexture_no_error(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level)3630 _mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
3631                                        GLuint texture, GLint level)
3632 {
3633    frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
3634                         "glNamedFramebufferTexture", true, true, true);
3635 }
3636 
3637 
3638 void GLAPIENTRY
_mesa_NamedFramebufferTexture(GLuint framebuffer,GLenum attachment,GLuint texture,GLint level)3639 _mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
3640                               GLuint texture, GLint level)
3641 {
3642    frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
3643                         "glNamedFramebufferTexture", true, false, true);
3644 }
3645 
3646 
3647 void
_mesa_framebuffer_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer * rb)3648 _mesa_framebuffer_renderbuffer(struct gl_context *ctx,
3649                                struct gl_framebuffer *fb,
3650                                GLenum attachment,
3651                                struct gl_renderbuffer *rb)
3652 {
3653    assert(!_mesa_is_winsys_fbo(fb));
3654 
3655    FLUSH_VERTICES(ctx, _NEW_BUFFERS);
3656 
3657    assert(ctx->Driver.FramebufferRenderbuffer);
3658    ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
3659 
3660    /* Some subsequent GL commands may depend on the framebuffer's visual
3661     * after the binding is updated.  Update visual info now.
3662     */
3663    _mesa_update_framebuffer_visual(ctx, fb);
3664 }
3665 
3666 static ALWAYS_INLINE void
framebuffer_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer,const char * func,bool no_error)3667 framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
3668                          GLenum attachment, GLenum renderbuffertarget,
3669                          GLuint renderbuffer, const char *func, bool no_error)
3670 {
3671    struct gl_renderbuffer_attachment *att;
3672    struct gl_renderbuffer *rb;
3673    bool is_color_attachment;
3674 
3675    if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
3676       _mesa_error(ctx, GL_INVALID_ENUM,
3677                   "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
3678       return;
3679    }
3680 
3681    if (renderbuffer) {
3682       if (!no_error) {
3683          rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
3684          if (!rb)
3685             return;
3686       } else {
3687          rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
3688       }
3689    } else {
3690       /* remove renderbuffer attachment */
3691       rb = NULL;
3692    }
3693 
3694    if (!no_error) {
3695       if (_mesa_is_winsys_fbo(fb)) {
3696          /* Can't attach new renderbuffers to a window system framebuffer */
3697          _mesa_error(ctx, GL_INVALID_OPERATION,
3698                      "%s(window-system framebuffer)", func);
3699          return;
3700       }
3701 
3702       att = get_attachment(ctx, fb, attachment, &is_color_attachment);
3703       if (att == NULL) {
3704          /*
3705           * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
3706           * to a Framebuffer":
3707           *
3708           *    "An INVALID_OPERATION error is generated if attachment is
3709           *    COLOR_- ATTACHMENTm where m is greater than or equal to the
3710           *    value of MAX_COLOR_- ATTACHMENTS ."
3711           *
3712           * If we are at this point, is because the attachment is not valid, so
3713           * if is_color_attachment is true, is because of the previous reason.
3714           */
3715          if (is_color_attachment) {
3716             _mesa_error(ctx, GL_INVALID_OPERATION,
3717                         "%s(invalid color attachment %s)", func,
3718                         _mesa_enum_to_string(attachment));
3719          } else {
3720             _mesa_error(ctx, GL_INVALID_ENUM,
3721                         "%s(invalid attachment %s)", func,
3722                         _mesa_enum_to_string(attachment));
3723          }
3724 
3725          return;
3726       }
3727 
3728       if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
3729           rb && rb->Format != MESA_FORMAT_NONE) {
3730          /* make sure the renderbuffer is a depth/stencil format */
3731          const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
3732          if (baseFormat != GL_DEPTH_STENCIL) {
3733             _mesa_error(ctx, GL_INVALID_OPERATION,
3734                         "%s(renderbuffer is not DEPTH_STENCIL format)", func);
3735             return;
3736          }
3737       }
3738    }
3739 
3740    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
3741 }
3742 
3743 static void
framebuffer_renderbuffer_error(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer,const char * func)3744 framebuffer_renderbuffer_error(struct gl_context *ctx,
3745                                struct gl_framebuffer *fb, GLenum attachment,
3746                                GLenum renderbuffertarget,
3747                                GLuint renderbuffer, const char *func)
3748 {
3749    framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
3750                             renderbuffer, func, false);
3751 }
3752 
3753 static void
framebuffer_renderbuffer_no_error(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer,const char * func)3754 framebuffer_renderbuffer_no_error(struct gl_context *ctx,
3755                                   struct gl_framebuffer *fb, GLenum attachment,
3756                                   GLenum renderbuffertarget,
3757                                   GLuint renderbuffer, const char *func)
3758 {
3759    framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
3760                             renderbuffer, func, true);
3761 }
3762 
3763 void GLAPIENTRY
_mesa_FramebufferRenderbuffer_no_error(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)3764 _mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
3765                                        GLenum renderbuffertarget,
3766                                        GLuint renderbuffer)
3767 {
3768    GET_CURRENT_CONTEXT(ctx);
3769 
3770    struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3771    framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
3772                                      renderbuffer, "glFramebufferRenderbuffer");
3773 }
3774 
3775 void GLAPIENTRY
_mesa_FramebufferRenderbuffer(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)3776 _mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
3777                               GLenum renderbuffertarget,
3778                               GLuint renderbuffer)
3779 {
3780    struct gl_framebuffer *fb;
3781    GET_CURRENT_CONTEXT(ctx);
3782 
3783    fb = get_framebuffer_target(ctx, target);
3784    if (!fb) {
3785       _mesa_error(ctx, GL_INVALID_ENUM,
3786                   "glFramebufferRenderbuffer(invalid target %s)",
3787                   _mesa_enum_to_string(target));
3788       return;
3789    }
3790 
3791    framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
3792                                   renderbuffer, "glFramebufferRenderbuffer");
3793 }
3794 
3795 void GLAPIENTRY
_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)3796 _mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
3797                                             GLenum attachment,
3798                                             GLenum renderbuffertarget,
3799                                             GLuint renderbuffer)
3800 {
3801    GET_CURRENT_CONTEXT(ctx);
3802 
3803    struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
3804    framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
3805                                      renderbuffer,
3806                                      "glNamedFramebufferRenderbuffer");
3807 }
3808 
3809 void GLAPIENTRY
_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)3810 _mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
3811                                    GLenum renderbuffertarget,
3812                                    GLuint renderbuffer)
3813 {
3814    struct gl_framebuffer *fb;
3815    GET_CURRENT_CONTEXT(ctx);
3816 
3817    fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
3818                                      "glNamedFramebufferRenderbuffer");
3819    if (!fb)
3820       return;
3821 
3822    framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
3823                                   renderbuffer,
3824                                   "glNamedFramebufferRenderbuffer");
3825 }
3826 
3827 
3828 static void
get_framebuffer_attachment_parameter(struct gl_context * ctx,struct gl_framebuffer * buffer,GLenum attachment,GLenum pname,GLint * params,const char * caller)3829 get_framebuffer_attachment_parameter(struct gl_context *ctx,
3830                                      struct gl_framebuffer *buffer,
3831                                      GLenum attachment, GLenum pname,
3832                                      GLint *params, const char *caller)
3833 {
3834    const struct gl_renderbuffer_attachment *att;
3835    bool is_color_attachment = false;
3836    GLenum err;
3837 
3838    /* The error code for an attachment type of GL_NONE differs between APIs.
3839     *
3840     * From the ES 2.0.25 specification, page 127:
3841     * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
3842     *  querying any other pname will generate INVALID_ENUM."
3843     *
3844     * From the OpenGL 3.0 specification, page 337, or identically,
3845     * the OpenGL ES 3.0.4 specification, page 240:
3846     *
3847     * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no
3848     *  framebuffer is bound to target.  In this case querying pname
3849     *  FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero, and all other
3850     *  queries will generate an INVALID_OPERATION error."
3851     */
3852    err = ctx->API == API_OPENGLES2 && ctx->Version < 30 ?
3853       GL_INVALID_ENUM : GL_INVALID_OPERATION;
3854 
3855    if (_mesa_is_winsys_fbo(buffer)) {
3856       /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
3857        * says:
3858        *
3859        *     "If the framebuffer currently bound to target is zero, then
3860        *     INVALID_OPERATION is generated."
3861        *
3862        * The EXT_framebuffer_object spec has the same wording, and the
3863        * OES_framebuffer_object spec refers to the EXT_framebuffer_object
3864        * spec.
3865        */
3866       if ((!_mesa_is_desktop_gl(ctx) ||
3867            !ctx->Extensions.ARB_framebuffer_object)
3868           && !_mesa_is_gles3(ctx)) {
3869          _mesa_error(ctx, GL_INVALID_OPERATION,
3870                      "%s(window-system framebuffer)", caller);
3871          return;
3872       }
3873 
3874       if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
3875           attachment != GL_DEPTH && attachment != GL_STENCIL) {
3876          _mesa_error(ctx, GL_INVALID_ENUM,
3877                      "%s(invalid attachment %s)", caller,
3878                      _mesa_enum_to_string(attachment));
3879          return;
3880       }
3881 
3882       /* The specs are not clear about how to handle
3883        * GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME with the default framebuffer,
3884        * but dEQP-GLES3 expects an INVALID_ENUM error. This has also been
3885        * discussed in:
3886        *
3887        * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=12928#c1
3888        * and https://bugs.freedesktop.org/show_bug.cgi?id=31947
3889        */
3890       if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
3891          _mesa_error(ctx, GL_INVALID_ENUM,
3892                      "%s(requesting GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME "
3893                      "when GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
3894                      "GL_FRAMEBUFFER_DEFAULT is not allowed)", caller);
3895          return;
3896       }
3897 
3898       /* the default / window-system FBO */
3899       att = get_fb0_attachment(ctx, buffer, attachment);
3900    }
3901    else {
3902       /* user-created framebuffer FBO */
3903       att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
3904    }
3905 
3906    if (att == NULL) {
3907       /*
3908        * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
3909        *
3910        *    "An INVALID_OPERATION error is generated if a framebuffer object
3911        *     is bound to target and attachment is COLOR_ATTACHMENTm where m is
3912        *     greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
3913        *
3914        * If we are at this point, is because the attachment is not valid, so
3915        * if is_color_attachment is true, is because of the previous reason.
3916        */
3917       if (is_color_attachment) {
3918          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
3919                      caller, _mesa_enum_to_string(attachment));
3920       } else {
3921          _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
3922                      _mesa_enum_to_string(attachment));
3923       }
3924       return;
3925    }
3926 
3927    if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3928       const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
3929       if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
3930          /* This behavior is first specified in OpenGL 4.4 specification.
3931           *
3932           * From the OpenGL 4.4 spec page 275:
3933           *   "This query cannot be performed for a combined depth+stencil
3934           *    attachment, since it does not have a single format."
3935           */
3936          _mesa_error(ctx, GL_INVALID_OPERATION,
3937                      "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
3938                      " is invalid for depth+stencil attachment)", caller);
3939          return;
3940       }
3941       /* the depth and stencil attachments must point to the same buffer */
3942       depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
3943       stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
3944       if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
3945          _mesa_error(ctx, GL_INVALID_OPERATION,
3946                      "%s(DEPTH/STENCIL attachments differ)", caller);
3947          return;
3948       }
3949    }
3950 
3951    /* No need to flush here */
3952 
3953    switch (pname) {
3954    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
3955       /* From the OpenGL spec, 9.2. Binding and Managing Framebuffer Objects:
3956        *
3957        * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
3958        *  either no framebuffer is bound to target; or the default framebuffer
3959        *  is bound, attachment is DEPTH or STENCIL, and the number of depth or
3960        *  stencil bits, respectively, is zero."
3961        *
3962        * Note that we don't need explicit checks on DEPTH and STENCIL, because
3963        * on the case the spec is pointing, att->Type is already NONE, so we
3964        * just need to check att->Type.
3965        */
3966       *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
3967          GL_FRAMEBUFFER_DEFAULT : att->Type;
3968       return;
3969    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
3970       if (att->Type == GL_RENDERBUFFER_EXT) {
3971          *params = att->Renderbuffer->Name;
3972       }
3973       else if (att->Type == GL_TEXTURE) {
3974          *params = att->Texture->Name;
3975       }
3976       else {
3977          assert(att->Type == GL_NONE);
3978          if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
3979             *params = 0;
3980          } else {
3981             goto invalid_pname_enum;
3982          }
3983       }
3984       return;
3985    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
3986       if (att->Type == GL_TEXTURE) {
3987          *params = att->TextureLevel;
3988       }
3989       else if (att->Type == GL_NONE) {
3990          _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
3991                      _mesa_enum_to_string(pname));
3992       }
3993       else {
3994          goto invalid_pname_enum;
3995       }
3996       return;
3997    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
3998       if (att->Type == GL_TEXTURE) {
3999          if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
4000             *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
4001          }
4002          else {
4003             *params = 0;
4004          }
4005       }
4006       else if (att->Type == GL_NONE) {
4007          _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4008                      _mesa_enum_to_string(pname));
4009       }
4010       else {
4011          goto invalid_pname_enum;
4012       }
4013       return;
4014    case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
4015       if (ctx->API == API_OPENGLES) {
4016          goto invalid_pname_enum;
4017       } else if (att->Type == GL_NONE) {
4018          _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4019                      _mesa_enum_to_string(pname));
4020       } else if (att->Type == GL_TEXTURE) {
4021          if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
4022              att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
4023             *params = att->Zoffset;
4024          }
4025          else {
4026             *params = 0;
4027          }
4028       }
4029       else {
4030          goto invalid_pname_enum;
4031       }
4032       return;
4033    case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4034       if ((!_mesa_is_desktop_gl(ctx) ||
4035            !ctx->Extensions.ARB_framebuffer_object)
4036           && !_mesa_is_gles3(ctx)) {
4037          goto invalid_pname_enum;
4038       }
4039       else if (att->Type == GL_NONE) {
4040          if (_mesa_is_winsys_fbo(buffer) &&
4041              (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
4042             *params = GL_LINEAR;
4043          } else {
4044             _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4045                         _mesa_enum_to_string(pname));
4046          }
4047       }
4048       else {
4049          if (ctx->Extensions.EXT_framebuffer_sRGB) {
4050             *params =
4051                _mesa_get_format_color_encoding(att->Renderbuffer->Format);
4052          }
4053          else {
4054             /* According to ARB_framebuffer_sRGB, we should return LINEAR
4055              * if the sRGB conversion is unsupported. */
4056             *params = GL_LINEAR;
4057          }
4058       }
4059       return;
4060    case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4061       if ((ctx->API != API_OPENGL_COMPAT ||
4062            !ctx->Extensions.ARB_framebuffer_object)
4063           && ctx->API != API_OPENGL_CORE
4064           && !_mesa_is_gles3(ctx)) {
4065          goto invalid_pname_enum;
4066       }
4067       else if (att->Type == GL_NONE) {
4068          _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4069                      _mesa_enum_to_string(pname));
4070       }
4071       else {
4072          mesa_format format = att->Renderbuffer->Format;
4073 
4074          /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
4075           * 3.0.1 spec says:
4076           *
4077           *     "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
4078           *     attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
4079           *     generate an INVALID_OPERATION error.
4080           */
4081          if (_mesa_is_gles3(ctx) &&
4082              attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
4083             _mesa_error(ctx, GL_INVALID_OPERATION,
4084                         "%s(cannot query "
4085                         "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
4086                         "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
4087             return;
4088          }
4089 
4090          if (format == MESA_FORMAT_S_UINT8) {
4091             /* special cases */
4092             *params = GL_INDEX;
4093          }
4094          else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
4095             /* depends on the attachment parameter */
4096             if (attachment == GL_STENCIL_ATTACHMENT) {
4097                *params = GL_INDEX;
4098             }
4099             else {
4100                *params = GL_FLOAT;
4101             }
4102          }
4103          else {
4104             *params = _mesa_get_format_datatype(format);
4105          }
4106       }
4107       return;
4108    case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4109    case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4110    case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4111    case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4112    case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4113    case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4114       if ((!_mesa_is_desktop_gl(ctx) ||
4115            !ctx->Extensions.ARB_framebuffer_object)
4116           && !_mesa_is_gles3(ctx)) {
4117          goto invalid_pname_enum;
4118       }
4119       else if (att->Texture) {
4120          const struct gl_texture_image *texImage =
4121             _mesa_select_tex_image(att->Texture, att->Texture->Target,
4122                                    att->TextureLevel);
4123          if (texImage) {
4124             *params = get_component_bits(pname, texImage->_BaseFormat,
4125                                          texImage->TexFormat);
4126          }
4127          else {
4128             *params = 0;
4129          }
4130       }
4131       else if (att->Renderbuffer) {
4132          *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
4133                                       att->Renderbuffer->Format);
4134       }
4135       else {
4136          assert(att->Type == GL_NONE);
4137          _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4138                      _mesa_enum_to_string(pname));
4139       }
4140       return;
4141    case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
4142       if (!_mesa_has_geometry_shaders(ctx)) {
4143          goto invalid_pname_enum;
4144       } else if (att->Type == GL_TEXTURE) {
4145          *params = att->Layered;
4146       } else if (att->Type == GL_NONE) {
4147          _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4148                      _mesa_enum_to_string(pname));
4149       } else {
4150          goto invalid_pname_enum;
4151       }
4152       return;
4153    default:
4154       goto invalid_pname_enum;
4155    }
4156 
4157    return;
4158 
4159 invalid_pname_enum:
4160    _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
4161                _mesa_enum_to_string(pname));
4162    return;
4163 }
4164 
4165 
4166 void GLAPIENTRY
_mesa_GetFramebufferAttachmentParameteriv(GLenum target,GLenum attachment,GLenum pname,GLint * params)4167 _mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
4168                                           GLenum pname, GLint *params)
4169 {
4170    GET_CURRENT_CONTEXT(ctx);
4171    struct gl_framebuffer *buffer;
4172 
4173    buffer = get_framebuffer_target(ctx, target);
4174    if (!buffer) {
4175       _mesa_error(ctx, GL_INVALID_ENUM,
4176                   "glGetFramebufferAttachmentParameteriv(invalid target %s)",
4177                   _mesa_enum_to_string(target));
4178       return;
4179    }
4180 
4181    get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4182                                         params,
4183                                     "glGetFramebufferAttachmentParameteriv");
4184 }
4185 
4186 
4187 void GLAPIENTRY
_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,GLenum attachment,GLenum pname,GLint * params)4188 _mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
4189                                                GLenum attachment,
4190                                                GLenum pname, GLint *params)
4191 {
4192    GET_CURRENT_CONTEXT(ctx);
4193    struct gl_framebuffer *buffer;
4194 
4195    if (framebuffer) {
4196       buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4197                               "glGetNamedFramebufferAttachmentParameteriv");
4198       if (!buffer)
4199          return;
4200    }
4201    else {
4202       /*
4203        * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4204        * 4.5 core spec (30.10.2014, PDF page 314):
4205        *    "If framebuffer is zero, then the default draw framebuffer is
4206        *    queried."
4207        */
4208       buffer = ctx->WinSysDrawBuffer;
4209    }
4210 
4211    get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4212                                         params,
4213                               "glGetNamedFramebufferAttachmentParameteriv");
4214 }
4215 
4216 
4217 void GLAPIENTRY
_mesa_NamedFramebufferParameteri(GLuint framebuffer,GLenum pname,GLint param)4218 _mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
4219                                  GLint param)
4220 {
4221    GET_CURRENT_CONTEXT(ctx);
4222    struct gl_framebuffer *fb = NULL;
4223 
4224    if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4225       _mesa_error(ctx, GL_INVALID_OPERATION,
4226                   "glNamedFramebufferParameteri("
4227                   "ARB_framebuffer_no_attachments not implemented)");
4228       return;
4229    }
4230 
4231    fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4232                                      "glNamedFramebufferParameteri");
4233 
4234    if (fb) {
4235       framebuffer_parameteri(ctx, fb, pname, param,
4236                              "glNamedFramebufferParameteriv");
4237    }
4238 }
4239 
4240 
4241 void GLAPIENTRY
_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer,GLenum pname,GLint * param)4242 _mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
4243                                      GLint *param)
4244 {
4245    GET_CURRENT_CONTEXT(ctx);
4246    struct gl_framebuffer *fb;
4247 
4248    if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4249       _mesa_error(ctx, GL_INVALID_OPERATION,
4250                   "glNamedFramebufferParameteriv("
4251                   "ARB_framebuffer_no_attachments not implemented)");
4252       return;
4253    }
4254 
4255    if (framebuffer) {
4256       fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4257                                         "glGetNamedFramebufferParameteriv");
4258    } else {
4259       fb = ctx->WinSysDrawBuffer;
4260    }
4261 
4262    if (fb) {
4263       get_framebuffer_parameteriv(ctx, fb, pname, param,
4264                                   "glGetNamedFramebufferParameteriv");
4265    }
4266 }
4267 
4268 
4269 static void
invalidate_framebuffer_storage(struct gl_context * ctx,struct gl_framebuffer * fb,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height,const char * name)4270 invalidate_framebuffer_storage(struct gl_context *ctx,
4271                                struct gl_framebuffer *fb,
4272                                GLsizei numAttachments,
4273                                const GLenum *attachments, GLint x, GLint y,
4274                                GLsizei width, GLsizei height, const char *name)
4275 {
4276    int i;
4277 
4278    /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
4279     * Spec (2.2.2015, PDF page 522) says:
4280     *    "An INVALID_VALUE error is generated if numAttachments, width, or
4281     *    height is negative."
4282     */
4283    if (numAttachments < 0) {
4284       _mesa_error(ctx, GL_INVALID_VALUE,
4285                   "%s(numAttachments < 0)", name);
4286       return;
4287    }
4288 
4289    if (width < 0) {
4290       _mesa_error(ctx, GL_INVALID_VALUE,
4291                   "%s(width < 0)", name);
4292       return;
4293    }
4294 
4295    if (height < 0) {
4296       _mesa_error(ctx, GL_INVALID_VALUE,
4297                   "%s(height < 0)", name);
4298       return;
4299    }
4300 
4301    /* The GL_ARB_invalidate_subdata spec says:
4302     *
4303     *     "If an attachment is specified that does not exist in the
4304     *     framebuffer bound to <target>, it is ignored."
4305     *
4306     * It also says:
4307     *
4308     *     "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
4309     *     or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
4310     *     INVALID_OPERATION is generated."
4311     *
4312     * No mention is made of GL_AUXi being out of range.  Therefore, we allow
4313     * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
4314     * set of retrictions).
4315     */
4316    for (i = 0; i < numAttachments; i++) {
4317       if (_mesa_is_winsys_fbo(fb)) {
4318          switch (attachments[i]) {
4319          case GL_ACCUM:
4320          case GL_AUX0:
4321          case GL_AUX1:
4322          case GL_AUX2:
4323          case GL_AUX3:
4324             /* Accumulation buffers and auxilary buffers were removed in
4325              * OpenGL 3.1, and they never existed in OpenGL ES.
4326              */
4327             if (ctx->API != API_OPENGL_COMPAT)
4328                goto invalid_enum;
4329             break;
4330          case GL_COLOR:
4331          case GL_DEPTH:
4332          case GL_STENCIL:
4333             break;
4334          case GL_BACK_LEFT:
4335          case GL_BACK_RIGHT:
4336          case GL_FRONT_LEFT:
4337          case GL_FRONT_RIGHT:
4338             if (!_mesa_is_desktop_gl(ctx))
4339                goto invalid_enum;
4340             break;
4341          default:
4342             goto invalid_enum;
4343          }
4344       } else {
4345          switch (attachments[i]) {
4346          case GL_DEPTH_ATTACHMENT:
4347          case GL_STENCIL_ATTACHMENT:
4348             break;
4349          case GL_DEPTH_STENCIL_ATTACHMENT:
4350             /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
4351              * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
4352              * extension does not make this attachment point valid on ES 2.0.
4353              */
4354             if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
4355                break;
4356             /* fallthrough */
4357          case GL_COLOR_ATTACHMENT0:
4358          case GL_COLOR_ATTACHMENT1:
4359          case GL_COLOR_ATTACHMENT2:
4360          case GL_COLOR_ATTACHMENT3:
4361          case GL_COLOR_ATTACHMENT4:
4362          case GL_COLOR_ATTACHMENT5:
4363          case GL_COLOR_ATTACHMENT6:
4364          case GL_COLOR_ATTACHMENT7:
4365          case GL_COLOR_ATTACHMENT8:
4366          case GL_COLOR_ATTACHMENT9:
4367          case GL_COLOR_ATTACHMENT10:
4368          case GL_COLOR_ATTACHMENT11:
4369          case GL_COLOR_ATTACHMENT12:
4370          case GL_COLOR_ATTACHMENT13:
4371          case GL_COLOR_ATTACHMENT14:
4372          case GL_COLOR_ATTACHMENT15: {
4373             unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
4374             if (k >= ctx->Const.MaxColorAttachments) {
4375                _mesa_error(ctx, GL_INVALID_OPERATION,
4376                            "%s(attachment >= max. color attachments)", name);
4377                return;
4378             }
4379             break;
4380          }
4381          default:
4382             goto invalid_enum;
4383          }
4384       }
4385    }
4386 
4387    /* We don't actually do anything for this yet.  Just return after
4388     * validating the parameters and generating the required errors.
4389     */
4390    return;
4391 
4392 invalid_enum:
4393    _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
4394                _mesa_enum_to_string(attachments[i]));
4395    return;
4396 }
4397 
4398 
4399 void GLAPIENTRY
_mesa_InvalidateSubFramebuffer_no_error(GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)4400 _mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
4401                                         const GLenum *attachments, GLint x,
4402                                         GLint y, GLsizei width, GLsizei height)
4403 {
4404    /* no-op */
4405 }
4406 
4407 
4408 void GLAPIENTRY
_mesa_InvalidateSubFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)4409 _mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
4410                                const GLenum *attachments, GLint x, GLint y,
4411                                GLsizei width, GLsizei height)
4412 {
4413    struct gl_framebuffer *fb;
4414    GET_CURRENT_CONTEXT(ctx);
4415 
4416    fb = get_framebuffer_target(ctx, target);
4417    if (!fb) {
4418       _mesa_error(ctx, GL_INVALID_ENUM,
4419                   "glInvalidateSubFramebuffer(invalid target %s)",
4420                   _mesa_enum_to_string(target));
4421       return;
4422    }
4423 
4424    invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4425                                   x, y, width, height,
4426                                   "glInvalidateSubFramebuffer");
4427 }
4428 
4429 
4430 void GLAPIENTRY
_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)4431 _mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
4432                                         GLsizei numAttachments,
4433                                         const GLenum *attachments,
4434                                         GLint x, GLint y,
4435                                         GLsizei width, GLsizei height)
4436 {
4437    struct gl_framebuffer *fb;
4438    GET_CURRENT_CONTEXT(ctx);
4439 
4440    /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
4441     * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
4442     * default draw framebuffer is affected."
4443     */
4444    if (framebuffer) {
4445       fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4446                                         "glInvalidateNamedFramebufferSubData");
4447       if (!fb)
4448          return;
4449    }
4450    else
4451       fb = ctx->WinSysDrawBuffer;
4452 
4453    invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4454                                   x, y, width, height,
4455                                   "glInvalidateNamedFramebufferSubData");
4456 }
4457 
4458 
4459 void GLAPIENTRY
_mesa_InvalidateFramebuffer_no_error(GLenum target,GLsizei numAttachments,const GLenum * attachments)4460 _mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
4461                                      const GLenum *attachments)
4462 {
4463    /* no-op */
4464 }
4465 
4466 
4467 void GLAPIENTRY
_mesa_InvalidateFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments)4468 _mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
4469                             const GLenum *attachments)
4470 {
4471    struct gl_framebuffer *fb;
4472    GET_CURRENT_CONTEXT(ctx);
4473 
4474    fb = get_framebuffer_target(ctx, target);
4475    if (!fb) {
4476       _mesa_error(ctx, GL_INVALID_ENUM,
4477                   "glInvalidateFramebuffer(invalid target %s)",
4478                   _mesa_enum_to_string(target));
4479       return;
4480    }
4481 
4482    /* The GL_ARB_invalidate_subdata spec says:
4483     *
4484     *     "The command
4485     *
4486     *        void InvalidateFramebuffer(enum target,
4487     *                                   sizei numAttachments,
4488     *                                   const enum *attachments);
4489     *
4490     *     is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
4491     *     <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
4492     *     <MAX_VIEWPORT_DIMS[1]> respectively."
4493     */
4494    invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4495                                   0, 0,
4496                                   ctx->Const.MaxViewportWidth,
4497                                   ctx->Const.MaxViewportHeight,
4498                                   "glInvalidateFramebuffer");
4499 }
4500 
4501 
4502 void GLAPIENTRY
_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,GLsizei numAttachments,const GLenum * attachments)4503 _mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
4504                                      GLsizei numAttachments,
4505                                      const GLenum *attachments)
4506 {
4507    struct gl_framebuffer *fb;
4508    GET_CURRENT_CONTEXT(ctx);
4509 
4510    /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
4511     * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
4512     * default draw framebuffer is affected."
4513     */
4514    if (framebuffer) {
4515       fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4516                                         "glInvalidateNamedFramebufferData");
4517       if (!fb)
4518          return;
4519    }
4520    else
4521       fb = ctx->WinSysDrawBuffer;
4522 
4523    /* The GL_ARB_invalidate_subdata spec says:
4524     *
4525     *     "The command
4526     *
4527     *        void InvalidateFramebuffer(enum target,
4528     *                                   sizei numAttachments,
4529     *                                   const enum *attachments);
4530     *
4531     *     is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
4532     *     <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
4533     *     <MAX_VIEWPORT_DIMS[1]> respectively."
4534     */
4535    invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
4536                                   0, 0,
4537                                   ctx->Const.MaxViewportWidth,
4538                                   ctx->Const.MaxViewportHeight,
4539                                   "glInvalidateNamedFramebufferData");
4540 }
4541 
4542 
4543 void GLAPIENTRY
_mesa_DiscardFramebufferEXT(GLenum target,GLsizei numAttachments,const GLenum * attachments)4544 _mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
4545                             const GLenum *attachments)
4546 {
4547    struct gl_framebuffer *fb;
4548    GLint i;
4549 
4550    GET_CURRENT_CONTEXT(ctx);
4551 
4552    fb = get_framebuffer_target(ctx, target);
4553    if (!fb) {
4554       _mesa_error(ctx, GL_INVALID_ENUM,
4555          "glDiscardFramebufferEXT(target %s)",
4556          _mesa_enum_to_string(target));
4557       return;
4558    }
4559 
4560    if (numAttachments < 0) {
4561       _mesa_error(ctx, GL_INVALID_VALUE,
4562                   "glDiscardFramebufferEXT(numAttachments < 0)");
4563       return;
4564    }
4565 
4566    for (i = 0; i < numAttachments; i++) {
4567       switch (attachments[i]) {
4568       case GL_COLOR:
4569       case GL_DEPTH:
4570       case GL_STENCIL:
4571          if (_mesa_is_user_fbo(fb))
4572             goto invalid_enum;
4573          break;
4574       case GL_COLOR_ATTACHMENT0:
4575       case GL_DEPTH_ATTACHMENT:
4576       case GL_STENCIL_ATTACHMENT:
4577          if (_mesa_is_winsys_fbo(fb))
4578             goto invalid_enum;
4579          break;
4580       default:
4581          goto invalid_enum;
4582       }
4583    }
4584 
4585    if (ctx->Driver.DiscardFramebuffer)
4586       ctx->Driver.DiscardFramebuffer(ctx, target, numAttachments, attachments);
4587 
4588    return;
4589 
4590 invalid_enum:
4591    _mesa_error(ctx, GL_INVALID_ENUM,
4592                "glDiscardFramebufferEXT(attachment %s)",
4593               _mesa_enum_to_string(attachments[i]));
4594 }
4595