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