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