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