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