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