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