blob: bc4f69c149e315f9d331b46e8b1a0fd15dd8b233 [file] [log] [blame]
Brian Paulddc82ee2005-02-05 19:56:45 +00001/*
2 * Mesa 3-D graphics library
Brian Paulddc82ee2005-02-05 19:56:45 +00003 *
Brian Paul3dc65912008-07-03 15:40:38 -06004 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
Brian Paul989edea2009-01-22 15:05:13 -07005 * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
Brian Paulddc82ee2005-02-05 19:56:45 +00006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Kenneth Graunke3d8d5b22013-04-21 13:46:48 -070020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
Brian Paulddc82ee2005-02-05 19:56:45 +000024 */
25
26
Brian Paul463642c2005-02-08 02:06:00 +000027/*
Brian Paul989edea2009-01-22 15:05:13 -070028 * GL_EXT/ARB_framebuffer_object extensions
29 *
Brian Paul463642c2005-02-08 02:06:00 +000030 * Authors:
31 * Brian Paul
32 */
33
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -080034#include <stdbool.h>
Brian Paul463642c2005-02-08 02:06:00 +000035
Roland Scheideggera1bc0d02007-07-18 20:17:14 +020036#include "buffers.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000037#include "context.h"
Rhys Perry67f40da2018-06-14 19:56:28 -060038#include "debug_output.h"
Brian Paul9b50cea2009-10-23 11:34:14 -060039#include "enums.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000040#include "fbobject.h"
Brian Paul5cf5d4b2009-09-27 20:51:18 -060041#include "formats.h"
Brian Paule4b23562005-05-04 20:11:35 +000042#include "framebuffer.h"
Brian Paula1287f52012-07-22 11:20:00 -060043#include "glformats.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000044#include "hash.h"
Brian Paul989edea2009-01-22 15:05:13 -070045#include "macros.h"
Chris Forbes90b5a242013-02-06 20:42:53 +130046#include "multisample.h"
Vinson Lee0117da42011-01-05 23:11:54 -080047#include "mtypes.h"
Brian Paule4b23562005-05-04 20:11:35 +000048#include "renderbuffer.h"
Brian Paul99745402006-03-01 02:02:43 +000049#include "state.h"
Brian Paul463642c2005-02-08 02:06:00 +000050#include "teximage.h"
Brian Paulea4fe662006-03-26 05:22:17 +000051#include "texobj.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000052
53
Brian Pauld9468c92005-02-10 16:08:07 +000054/**
55 * Notes:
56 *
57 * None of the GL_EXT_framebuffer_object functions are compiled into
58 * display lists.
59 */
60
61
62
Brian Paul923b6fc2005-02-08 04:08:56 +000063/*
64 * When glGenRender/FramebuffersEXT() is called we insert pointers to
65 * these placeholder objects into the hash table.
66 * Later, when the object ID is first bound, we replace the placeholder
67 * with the real frame/renderbuffer.
68 */
Brian Paul2c6f9112005-02-24 05:47:06 +000069static struct gl_framebuffer DummyFramebuffer;
70static struct gl_renderbuffer DummyRenderbuffer;
Brian Paul1864c7d2005-02-08 03:46:37 +000071
Kristian Høgsberg144356f2010-09-09 17:08:12 -040072/* We bind this framebuffer when applications pass a NULL
73 * drawable/surface in make current. */
74static struct gl_framebuffer IncompleteFramebuffer;
75
Brian Paul1864c7d2005-02-08 03:46:37 +000076
Brian Paul3dc65912008-07-03 15:40:38 -060077static void
Brian Paulc7324582012-11-30 10:04:48 -070078delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
Brian Paul3dc65912008-07-03 15:40:38 -060079{
80 /* no op */
81}
82
83static void
84delete_dummy_framebuffer(struct gl_framebuffer *fb)
85{
86 /* no op */
87}
88
89
90void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -040091_mesa_init_fbobjects(struct gl_context *ctx)
Brian Paul3dc65912008-07-03 15:40:38 -060092{
Timothy Arcerif0857fe2017-10-16 11:59:31 +110093 simple_mtx_init(&DummyFramebuffer.Mutex, mtx_plain);
94 simple_mtx_init(&DummyRenderbuffer.Mutex, mtx_plain);
95 simple_mtx_init(&IncompleteFramebuffer.Mutex, mtx_plain);
Brian Paul3dc65912008-07-03 15:40:38 -060096 DummyFramebuffer.Delete = delete_dummy_framebuffer;
97 DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
Kristian Høgsberg144356f2010-09-09 17:08:12 -040098 IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
Brian Paul3dc65912008-07-03 15:40:38 -060099}
100
Kristian Høgsberg9456e222010-06-04 14:28:59 -0400101struct gl_framebuffer *
102_mesa_get_incomplete_framebuffer(void)
103{
Kristian Høgsberg144356f2010-09-09 17:08:12 -0400104 return &IncompleteFramebuffer;
Kristian Høgsberg9456e222010-06-04 14:28:59 -0400105}
Brian Paul3dc65912008-07-03 15:40:38 -0600106
Brian Paulddc82ee2005-02-05 19:56:45 +0000107/**
Brian Paul2c6f9112005-02-24 05:47:06 +0000108 * Helper routine for getting a gl_renderbuffer.
Brian Paulddc82ee2005-02-05 19:56:45 +0000109 */
Brian Paulea4fe662006-03-26 05:22:17 +0000110struct gl_renderbuffer *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400111_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
Brian Paulddc82ee2005-02-05 19:56:45 +0000112{
Brian Paul2c6f9112005-02-24 05:47:06 +0000113 struct gl_renderbuffer *rb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000114
Brian Paul1864c7d2005-02-08 03:46:37 +0000115 if (id == 0)
Brian Paulddc82ee2005-02-05 19:56:45 +0000116 return NULL;
117
Brian Paul2c6f9112005-02-24 05:47:06 +0000118 rb = (struct gl_renderbuffer *)
Brian Paulddc82ee2005-02-05 19:56:45 +0000119 _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
120 return rb;
121}
122
123
124/**
Laura Ekstrand2bb138e2015-01-23 16:38:36 -0800125 * A convenience function for direct state access that throws
126 * GL_INVALID_OPERATION if the renderbuffer doesn't exist.
127 */
128struct gl_renderbuffer *
129_mesa_lookup_renderbuffer_err(struct gl_context *ctx, GLuint id,
130 const char *func)
131{
132 struct gl_renderbuffer *rb;
133
134 rb = _mesa_lookup_renderbuffer(ctx, id);
135 if (!rb || rb == &DummyRenderbuffer) {
136 _mesa_error(ctx, GL_INVALID_OPERATION,
137 "%s(non-existent renderbuffer %u)", func, id);
138 return NULL;
139 }
140
141 return rb;
142}
143
144
145/**
Brian Paul2c6f9112005-02-24 05:47:06 +0000146 * Helper routine for getting a gl_framebuffer.
Brian Paulddc82ee2005-02-05 19:56:45 +0000147 */
Brian Paulea4fe662006-03-26 05:22:17 +0000148struct gl_framebuffer *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400149_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
Brian Paulddc82ee2005-02-05 19:56:45 +0000150{
Brian Paul2c6f9112005-02-24 05:47:06 +0000151 struct gl_framebuffer *fb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000152
Brian Paul1864c7d2005-02-08 03:46:37 +0000153 if (id == 0)
Brian Paulddc82ee2005-02-05 19:56:45 +0000154 return NULL;
155
Brian Paul2c6f9112005-02-24 05:47:06 +0000156 fb = (struct gl_framebuffer *)
Brian Paulddc82ee2005-02-05 19:56:45 +0000157 _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +0200158
159 return fb;
160}
161
162
163struct gl_framebuffer *
164_mesa_lookup_framebuffer_dsa(struct gl_context *ctx, GLuint id,
165 const char* func)
166{
167 struct gl_framebuffer *fb;
168
169 if (id == 0)
170 return NULL;
171
172 fb = _mesa_lookup_framebuffer(ctx, id);
173
174 /* Name exists but buffer is not initialized */
175 if (fb == &DummyFramebuffer) {
176 fb = ctx->Driver.NewFramebuffer(ctx, id);
177 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
178 _mesa_HashInsert(ctx->Shared->FrameBuffers, id, fb);
179 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
180 }
181 /* Name doesn't exist */
182 else if (!fb) {
183 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
184 fb = ctx->Driver.NewFramebuffer(ctx, id);
185 if (!fb) {
186 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
187 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
188 return NULL;
189 }
190 _mesa_HashInsertLocked(ctx->Shared->BufferObjects, id, fb);
191 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
192 }
Brian Paul463642c2005-02-08 02:06:00 +0000193 return fb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000194}
195
196
197/**
Laura Ekstrand6d8eff42015-01-22 10:23:35 -0800198 * A convenience function for direct state access that throws
199 * GL_INVALID_OPERATION if the framebuffer doesn't exist.
200 */
201struct gl_framebuffer *
202_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
203 const char *func)
204{
205 struct gl_framebuffer *fb;
206
207 fb = _mesa_lookup_framebuffer(ctx, id);
208 if (!fb || fb == &DummyFramebuffer) {
209 _mesa_error(ctx, GL_INVALID_OPERATION,
210 "%s(non-existent framebuffer %u)", func, id);
211 return NULL;
212 }
213
214 return fb;
215}
216
217
218/**
Brian Paul72966362009-01-21 16:28:38 -0700219 * Mark the given framebuffer as invalid. This will force the
220 * test for framebuffer completeness to be done before the framebuffer
221 * is used.
222 */
223static void
224invalidate_framebuffer(struct gl_framebuffer *fb)
225{
226 fb->_Status = 0; /* "indeterminate" */
227}
228
229
230/**
Brian Paulc6991432011-02-28 18:24:25 -0700231 * Return the gl_framebuffer object which corresponds to the given
232 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
233 * Check support for GL_EXT_framebuffer_blit to determine if certain
234 * targets are legal.
235 * \return gl_framebuffer pointer or NULL if target is illegal
236 */
237static struct gl_framebuffer *
238get_framebuffer_target(struct gl_context *ctx, GLenum target)
239{
Ian Romanicka6729732013-11-13 13:30:37 -0800240 bool have_fb_blit = _mesa_is_gles3(ctx) || _mesa_is_desktop_gl(ctx);
Brian Paulc6991432011-02-28 18:24:25 -0700241 switch (target) {
242 case GL_DRAW_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800243 return have_fb_blit ? ctx->DrawBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700244 case GL_READ_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800245 return have_fb_blit ? ctx->ReadBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700246 case GL_FRAMEBUFFER_EXT:
247 return ctx->DrawBuffer;
248 default:
249 return NULL;
250 }
251}
252
253
254/**
Brian Pauld9468c92005-02-10 16:08:07 +0000255 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
Brian Paul2c6f9112005-02-24 05:47:06 +0000256 * gl_renderbuffer_attachment object.
Brian Paul61ec2052010-06-22 08:37:44 -0600257 * This function is only used for user-created FB objects, not the
258 * default / window-system FB object.
Brian Paul30590072009-01-21 11:06:11 -0700259 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
260 * the depth buffer attachment point.
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200261 * Returns if the attachment is a GL_COLOR_ATTACHMENTm_EXT on
262 * is_color_attachment, because several callers would return different errors
263 * if they don't find the attachment.
Brian Pauld9468c92005-02-10 16:08:07 +0000264 */
Brian Paul94512812014-02-01 08:58:43 -0700265static struct gl_renderbuffer_attachment *
266get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200267 GLenum attachment, bool *is_color_attachment)
Brian Paul3deaa012005-02-07 05:08:24 +0000268{
269 GLuint i;
270
Brian Paul36ede892012-01-12 09:17:23 -0700271 assert(_mesa_is_user_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600272
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200273 if (is_color_attachment)
274 *is_color_attachment = false;
275
Brian Paul3deaa012005-02-07 05:08:24 +0000276 switch (attachment) {
277 case GL_COLOR_ATTACHMENT0_EXT:
278 case GL_COLOR_ATTACHMENT1_EXT:
279 case GL_COLOR_ATTACHMENT2_EXT:
280 case GL_COLOR_ATTACHMENT3_EXT:
281 case GL_COLOR_ATTACHMENT4_EXT:
282 case GL_COLOR_ATTACHMENT5_EXT:
283 case GL_COLOR_ATTACHMENT6_EXT:
284 case GL_COLOR_ATTACHMENT7_EXT:
285 case GL_COLOR_ATTACHMENT8_EXT:
286 case GL_COLOR_ATTACHMENT9_EXT:
287 case GL_COLOR_ATTACHMENT10_EXT:
288 case GL_COLOR_ATTACHMENT11_EXT:
289 case GL_COLOR_ATTACHMENT12_EXT:
290 case GL_COLOR_ATTACHMENT13_EXT:
291 case GL_COLOR_ATTACHMENT14_EXT:
292 case GL_COLOR_ATTACHMENT15_EXT:
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200293 if (is_color_attachment)
294 *is_color_attachment = true;
Ian Romanick2e3a4ab2011-10-02 15:03:07 -0700295 /* Only OpenGL ES 1.x forbids color attachments other than
296 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the
297 * hardware is used.
298 */
Brian Paul3deaa012005-02-07 05:08:24 +0000299 i = attachment - GL_COLOR_ATTACHMENT0_EXT;
Ian Romanick7e4cb322011-10-02 14:50:21 -0700300 if (i >= ctx->Const.MaxColorAttachments
Martin Peres7bd8b482015-02-12 17:54:43 +0200301 || (i > 0 && ctx->API == API_OPENGLES)) {
302 return NULL;
Brian Paul3deaa012005-02-07 05:08:24 +0000303 }
Brian Paule4b23562005-05-04 20:11:35 +0000304 return &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paul30590072009-01-21 11:06:11 -0700305 case GL_DEPTH_STENCIL_ATTACHMENT:
Matt Turnerec8ee912012-11-15 22:13:48 -0800306 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
Martin Peres7bd8b482015-02-12 17:54:43 +0200307 return NULL;
Brian Paul30590072009-01-21 11:06:11 -0700308 /* fall-through */
Brian Paul3deaa012005-02-07 05:08:24 +0000309 case GL_DEPTH_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000310 return &fb->Attachment[BUFFER_DEPTH];
Brian Paul3deaa012005-02-07 05:08:24 +0000311 case GL_STENCIL_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000312 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul61ec2052010-06-22 08:37:44 -0600313 default:
314 return NULL;
315 }
316}
317
318
319/**
320 * As above, but only used for getting attachments of the default /
321 * window-system framebuffer (not user-created framebuffer objects).
322 */
323static struct gl_renderbuffer_attachment *
Timothy Arcerie6187612017-05-05 15:02:20 +1000324get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
325 GLenum attachment)
Brian Paul61ec2052010-06-22 08:37:44 -0600326{
Brian Paul36ede892012-01-12 09:17:23 -0700327 assert(_mesa_is_winsys_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600328
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800329 if (_mesa_is_gles3(ctx)) {
330 assert(attachment == GL_BACK ||
331 attachment == GL_DEPTH ||
332 attachment == GL_STENCIL);
333 switch (attachment) {
334 case GL_BACK:
335 /* Since there is no stereo rendering in ES 3.0, only return the
336 * LEFT bits.
337 */
338 if (ctx->DrawBuffer->Visual.doubleBufferMode)
339 return &fb->Attachment[BUFFER_BACK_LEFT];
340 return &fb->Attachment[BUFFER_FRONT_LEFT];
341 case GL_DEPTH:
Timothy Arceria754e4c2017-05-05 15:09:37 +1000342 return &fb->Attachment[BUFFER_DEPTH];
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800343 case GL_STENCIL:
344 return &fb->Attachment[BUFFER_STENCIL];
345 }
346 }
347
Brian Paul61ec2052010-06-22 08:37:44 -0600348 switch (attachment) {
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400349 case GL_FRONT_LEFT:
Marek Olšákd58a3902016-09-08 21:02:29 +0200350 /* Front buffers can be allocated on the first use, but
351 * glGetFramebufferAttachmentParameteriv must work even if that
352 * allocation hasn't happened yet. In such case, use the back buffer,
353 * which should be the same.
354 */
355 if (fb->Attachment[BUFFER_FRONT_LEFT].Type == GL_NONE)
356 return &fb->Attachment[BUFFER_BACK_LEFT];
357 else
358 return &fb->Attachment[BUFFER_FRONT_LEFT];
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400359 case GL_FRONT_RIGHT:
Marek Olšákd58a3902016-09-08 21:02:29 +0200360 /* Same as above. */
361 if (fb->Attachment[BUFFER_FRONT_RIGHT].Type == GL_NONE)
362 return &fb->Attachment[BUFFER_BACK_RIGHT];
363 else
364 return &fb->Attachment[BUFFER_FRONT_RIGHT];
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400365 case GL_BACK_LEFT:
366 return &fb->Attachment[BUFFER_BACK_LEFT];
367 case GL_BACK_RIGHT:
368 return &fb->Attachment[BUFFER_BACK_RIGHT];
Kenneth Graunke4f538c32017-10-26 11:44:09 -0700369 case GL_BACK:
370 /* The ARB_ES3_1_compatibility spec says:
371 *
372 * "Since this command can only query a single framebuffer
373 * attachment, BACK is equivalent to BACK_LEFT."
374 */
375 if (ctx->Extensions.ARB_ES3_1_compatibility)
376 return &fb->Attachment[BUFFER_BACK_LEFT];
377 return NULL;
Brian Paul61ec2052010-06-22 08:37:44 -0600378 case GL_AUX0:
379 if (fb->Visual.numAuxBuffers == 1) {
380 return &fb->Attachment[BUFFER_AUX0];
381 }
382 return NULL;
Ian Romanicka8328cc2011-10-03 12:02:18 -0700383
384 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
385 *
386 * "If the default framebuffer is bound to target, then attachment must
387 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
388 * identifying a color buffer; DEPTH, identifying the depth buffer; or
389 * STENCIL, identifying the stencil buffer."
390 *
391 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
392 * language. However, revision #33 of the ARB_framebuffer_object spec
393 * says:
394 *
395 * "If the default framebuffer is bound to <target>, then <attachment>
396 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
397 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
398 * depth buffer, or the stencil buffer, and <pname> may be
399 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
400 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
401 *
402 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
403 * from glext.h, so shipping apps should not use those values.
404 *
405 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
406 * support queries of the window system FBO.
407 */
408 case GL_DEPTH:
Brian Paul61ec2052010-06-22 08:37:44 -0600409 return &fb->Attachment[BUFFER_DEPTH];
Ian Romanicka8328cc2011-10-03 12:02:18 -0700410 case GL_STENCIL:
Brian Paul61ec2052010-06-22 08:37:44 -0600411 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul3deaa012005-02-07 05:08:24 +0000412 default:
413 return NULL;
414 }
415}
416
417
Brian Paul61ec2052010-06-22 08:37:44 -0600418
Brian Pauld9468c92005-02-10 16:08:07 +0000419/**
420 * Remove any texture or renderbuffer attached to the given attachment
421 * point. Update reference counts, etc.
422 */
Brian Paul94512812014-02-01 08:58:43 -0700423static void
424remove_attachment(struct gl_context *ctx,
425 struct gl_renderbuffer_attachment *att)
Brian Paul3deaa012005-02-07 05:08:24 +0000426{
Eric Anholtc810e672013-05-10 12:36:43 -0700427 struct gl_renderbuffer *rb = att->Renderbuffer;
428
429 /* tell driver that we're done rendering to this texture. */
430 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700431 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700432
Brian Paul3deaa012005-02-07 05:08:24 +0000433 if (att->Type == GL_TEXTURE) {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800434 assert(att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100435 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800436 assert(!att->Texture);
Brian Paul3deaa012005-02-07 05:08:24 +0000437 }
Brian Paul0e31e022005-12-01 00:25:00 +0000438 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800439 assert(!att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100440 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800441 assert(!att->Renderbuffer);
Brian Paul3deaa012005-02-07 05:08:24 +0000442 }
443 att->Type = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000444 att->Complete = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +0000445}
446
Eric Anholt749a9272013-04-22 10:38:41 -0700447/**
Ian Romanickfb497132013-07-27 12:04:20 -0700448 * Verify a couple error conditions that will lead to an incomplete FBO and
449 * may cause problems for the driver's RenderTexture path.
450 */
451static bool
452driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
453{
454 const struct gl_texture_image *const texImage =
455 att->Texture->Image[att->CubeMapFace][att->TextureLevel];
456
Marek Olšák8a101922016-05-30 16:29:18 +0200457 if (!texImage ||
458 texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
Ian Romanickfb497132013-07-27 12:04:20 -0700459 return false;
460
Ian Romanick41485fe2013-07-27 12:16:56 -0700461 if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
462 && att->Zoffset >= texImage->Height)
463 || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
464 && att->Zoffset >= texImage->Depth))
465 return false;
466
Ian Romanickfb497132013-07-27 12:04:20 -0700467 return true;
468}
469
470/**
Eric Anholt749a9272013-04-22 10:38:41 -0700471 * Create a renderbuffer which will be set up by the driver to wrap the
472 * texture image slice.
473 *
474 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
475 * to share most of their framebuffer rendering code between winsys,
476 * renderbuffer, and texture attachments.
477 *
478 * The allocated renderbuffer uses a non-zero Name so that drivers can check
479 * it for determining vertical orientation, but we use ~0 to make it fairly
480 * unambiguous with actual user (non-texture) renderbuffers.
481 */
482void
483_mesa_update_texture_renderbuffer(struct gl_context *ctx,
484 struct gl_framebuffer *fb,
485 struct gl_renderbuffer_attachment *att)
486{
487 struct gl_texture_image *texImage;
488 struct gl_renderbuffer *rb;
489
Eric Anholte98c39c2013-05-10 11:51:01 -0700490 texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
Eric Anholt749a9272013-04-22 10:38:41 -0700491
492 rb = att->Renderbuffer;
493 if (!rb) {
494 rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
495 if (!rb) {
496 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
497 return;
498 }
Timothy Arceri8046a942017-04-07 07:55:17 +1000499 att->Renderbuffer = rb;
Eric Anholt749a9272013-04-22 10:38:41 -0700500
501 /* This can't get called on a texture renderbuffer, so set it to NULL
502 * for clarity compared to user renderbuffers.
503 */
504 rb->AllocStorage = NULL;
Eric Anholtc810e672013-05-10 12:36:43 -0700505
506 rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
Eric Anholt749a9272013-04-22 10:38:41 -0700507 }
508
Ian Romanick2f9fe2d2013-07-28 13:08:27 -0700509 if (!texImage)
510 return;
511
Eric Anholt77a405d2013-04-22 11:04:21 -0700512 rb->_BaseFormat = texImage->_BaseFormat;
513 rb->Format = texImage->TexFormat;
514 rb->InternalFormat = texImage->InternalFormat;
515 rb->Width = texImage->Width2;
516 rb->Height = texImage->Height2;
Marek Olšáka3969aa2013-11-20 01:47:36 +0100517 rb->Depth = texImage->Depth2;
Eric Anholt77a405d2013-04-22 11:04:21 -0700518 rb->NumSamples = texImage->NumSamples;
Marek Olšák328c1c82018-06-11 17:24:16 -0400519 rb->NumStorageSamples = texImage->NumSamples;
Eric Anholte98c39c2013-05-10 11:51:01 -0700520 rb->TexImage = texImage;
Eric Anholt77a405d2013-04-22 11:04:21 -0700521
Ian Romanickfb497132013-07-27 12:04:20 -0700522 if (driver_RenderTexture_is_safe(att))
523 ctx->Driver.RenderTexture(ctx, fb, att);
Eric Anholt749a9272013-04-22 10:38:41 -0700524}
Brian Paul3deaa012005-02-07 05:08:24 +0000525
Brian Pauld9468c92005-02-10 16:08:07 +0000526/**
527 * Bind a texture object to an attachment point.
528 * The previous binding, if any, will be removed first.
529 */
Brian Paul94512812014-02-01 08:58:43 -0700530static void
531set_texture_attachment(struct gl_context *ctx,
532 struct gl_framebuffer *fb,
533 struct gl_renderbuffer_attachment *att,
534 struct gl_texture_object *texObj,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -0800535 GLenum texTarget, GLuint level, GLsizei samples,
536 GLuint layer, GLboolean layered)
Brian Paul3deaa012005-02-07 05:08:24 +0000537{
Eric Anholtc810e672013-05-10 12:36:43 -0700538 struct gl_renderbuffer *rb = att->Renderbuffer;
539
540 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700541 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700542
Brian Paul0e31e022005-12-01 00:25:00 +0000543 if (att->Texture == texObj) {
544 /* re-attaching same texture */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800545 assert(att->Type == GL_TEXTURE);
Brian Paul0e31e022005-12-01 00:25:00 +0000546 }
547 else {
548 /* new attachment */
Brian Paul94512812014-02-01 08:58:43 -0700549 remove_attachment(ctx, att);
Brian Paul0e31e022005-12-01 00:25:00 +0000550 att->Type = GL_TEXTURE;
Brian9e01b912007-08-13 11:29:46 +0100551 assert(!att->Texture);
552 _mesa_reference_texobj(&att->Texture, texObj);
Brian Paul0e31e022005-12-01 00:25:00 +0000553 }
Eric Anholt749a9272013-04-22 10:38:41 -0700554 invalidate_framebuffer(fb);
Brian Paul0e31e022005-12-01 00:25:00 +0000555
556 /* always update these fields */
Brian Paul3deaa012005-02-07 05:08:24 +0000557 att->TextureLevel = level;
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -0800558 att->NumSamples = samples;
Brian Paul26f1ad62009-10-23 18:15:55 -0600559 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
Laura Ekstrand085c67d2015-03-02 16:48:59 -0800560 att->Zoffset = layer;
Jordan Justena6280802013-04-18 10:08:50 -0700561 att->Layered = layered;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000562 att->Complete = GL_FALSE;
Brian Paul519b23b2006-03-20 18:51:57 +0000563
Eric Anholt749a9272013-04-22 10:38:41 -0700564 _mesa_update_texture_renderbuffer(ctx, fb, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000565}
566
567
Brian Pauld9468c92005-02-10 16:08:07 +0000568/**
569 * Bind a renderbuffer to an attachment point.
570 * The previous binding, if any, will be removed first.
571 */
Brian Paul94512812014-02-01 08:58:43 -0700572static void
573set_renderbuffer_attachment(struct gl_context *ctx,
574 struct gl_renderbuffer_attachment *att,
575 struct gl_renderbuffer *rb)
Brian Paul3deaa012005-02-07 05:08:24 +0000576{
Brian Paulea4fe662006-03-26 05:22:17 +0000577 /* XXX check if re-doing same attachment, exit early */
Brian Paul94512812014-02-01 08:58:43 -0700578 remove_attachment(ctx, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000579 att->Type = GL_RENDERBUFFER_EXT;
Brian Paul2c6f9112005-02-24 05:47:06 +0000580 att->Texture = NULL; /* just to be safe */
James Legg1581e122015-02-07 23:33:15 +0000581 att->Layered = GL_FALSE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000582 att->Complete = GL_FALSE;
Briandccd9c42007-04-02 09:56:28 -0600583 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
Brian Paul3deaa012005-02-07 05:08:24 +0000584}
585
Brian Paulddc82ee2005-02-05 19:56:45 +0000586
Brian Paulf0bbbf62005-02-09 03:50:30 +0000587/**
Brian Paule4b23562005-05-04 20:11:35 +0000588 * Fallback for ctx->Driver.FramebufferRenderbuffer()
Brian Paul84716042005-11-16 04:05:54 +0000589 * Attach a renderbuffer object to a framebuffer object.
Brian Paule4b23562005-05-04 20:11:35 +0000590 */
591void
Laura Ekstrand3d100372015-02-27 17:23:59 -0800592_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
593 struct gl_framebuffer *fb,
594 GLenum attachment,
595 struct gl_renderbuffer *rb)
Brian Paule4b23562005-05-04 20:11:35 +0000596{
Brian Paul84716042005-11-16 04:05:54 +0000597 struct gl_renderbuffer_attachment *att;
598
Timothy Arcerif0857fe2017-10-16 11:59:31 +1100599 simple_mtx_lock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +0000600
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200601 att = get_attachment(ctx, fb, attachment, NULL);
Matt Turnerbfcdb842015-02-20 20:18:47 -0800602 assert(att);
Brian Paule4b23562005-05-04 20:11:35 +0000603 if (rb) {
Brian Paul94512812014-02-01 08:58:43 -0700604 set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700605 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
606 /* do stencil attachment here (depth already done above) */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200607 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
Brian Paul30590072009-01-21 11:06:11 -0700608 assert(att);
Brian Paul94512812014-02-01 08:58:43 -0700609 set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700610 }
Marek Olšákdf818d52011-03-06 05:26:12 +0100611 rb->AttachedAnytime = GL_TRUE;
Brian Paule4b23562005-05-04 20:11:35 +0000612 }
613 else {
Brian Paul94512812014-02-01 08:58:43 -0700614 remove_attachment(ctx, att);
James Legg846c7152014-05-23 12:25:37 +0100615 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
616 /* detach stencil (depth was detached above) */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200617 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
James Legg846c7152014-05-23 12:25:37 +0100618 assert(att);
619 remove_attachment(ctx, att);
620 }
Brian Paule4b23562005-05-04 20:11:35 +0000621 }
Brian Paulea4fe662006-03-26 05:22:17 +0000622
Brian Paul72966362009-01-21 16:28:38 -0700623 invalidate_framebuffer(fb);
624
Timothy Arcerif0857fe2017-10-16 11:59:31 +1100625 simple_mtx_unlock(&fb->Mutex);
Brian Paule4b23562005-05-04 20:11:35 +0000626}
627
628
629/**
Brian Paul62c66b32011-01-24 19:38:52 -0700630 * Fallback for ctx->Driver.ValidateFramebuffer()
631 * Check if the renderbuffer's formats are supported by the software
632 * renderer.
633 * Drivers should probably override this.
634 */
635void
636_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
637{
638 gl_buffer_index buf;
639 for (buf = 0; buf < BUFFER_COUNT; buf++) {
640 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
641 if (rb) {
642 switch (rb->_BaseFormat) {
643 case GL_ALPHA:
644 case GL_LUMINANCE_ALPHA:
645 case GL_LUMINANCE:
646 case GL_INTENSITY:
Brian Pauld3015652011-01-24 19:38:52 -0700647 case GL_RED:
648 case GL_RG:
Brian Paul62c66b32011-01-24 19:38:52 -0700649 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
650 return;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200651
652 default:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200653 switch (rb->Format) {
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200654 /* XXX This list is likely incomplete. */
Mark Muellereeed49f2014-01-26 15:12:56 -0800655 case MESA_FORMAT_R9G9B9E5_FLOAT:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200656 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
657 return;
658 default:;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200659 /* render buffer format is supported by software rendering */
Marek Olšák9d7698c2011-04-26 02:18:24 +0200660 }
Brian Paul62c66b32011-01-24 19:38:52 -0700661 }
662 }
663 }
664}
665
666
667/**
Marek Olšákf8855a42013-03-14 14:22:56 +0100668 * Return true if the framebuffer has a combined depth/stencil
669 * renderbuffer attached.
670 */
671GLboolean
672_mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
673{
674 const struct gl_renderbuffer_attachment *depth =
675 &fb->Attachment[BUFFER_DEPTH];
676 const struct gl_renderbuffer_attachment *stencil =
677 &fb->Attachment[BUFFER_STENCIL];
678
679 if (depth->Type == stencil->Type) {
680 if (depth->Type == GL_RENDERBUFFER_EXT &&
681 depth->Renderbuffer == stencil->Renderbuffer)
682 return GL_TRUE;
683
684 if (depth->Type == GL_TEXTURE &&
685 depth->Texture == stencil->Texture)
686 return GL_TRUE;
687 }
688
689 return GL_FALSE;
690}
691
692
693/**
Brian Paul9f731c82009-02-17 16:47:54 -0700694 * For debug only.
695 */
696static void
697att_incomplete(const char *msg)
698{
Brian Paul93bcf782012-05-09 12:09:21 -0600699 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
700 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
701 }
Brian Paul9f731c82009-02-17 16:47:54 -0700702}
703
704
705/**
Brian Paulc26c2002009-09-15 17:20:32 -0600706 * For debug only.
707 */
708static void
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700709fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
Brian Paulc26c2002009-09-15 17:20:32 -0600710{
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700711 static GLuint msg_id;
712
Mark Janesb8a1a322018-12-06 16:35:43 -0800713 _mesa_gl_debugf(ctx, &msg_id,
714 MESA_DEBUG_SOURCE_API,
715 MESA_DEBUG_TYPE_OTHER,
716 MESA_DEBUG_SEVERITY_MEDIUM,
717 "FBO incomplete: %s [%d]\n", msg, index);
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700718
Brian Paul93bcf782012-05-09 12:09:21 -0600719 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
720 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
721 }
Brian Paulc26c2002009-09-15 17:20:32 -0600722}
723
724
Brian Paule67f6ee2010-10-22 11:38:23 -0600725/**
726 * Is the given base format a legal format for a color renderbuffer?
727 */
Eric Anholt059cca92011-01-02 17:58:07 -0800728GLboolean
729_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
Brian Paule67f6ee2010-10-22 11:38:23 -0600730{
731 switch (baseFormat) {
732 case GL_RGB:
733 case GL_RGBA:
734 return GL_TRUE;
Marek Olšák6e618532010-10-02 21:53:03 +0200735 case GL_LUMINANCE:
736 case GL_LUMINANCE_ALPHA:
737 case GL_INTENSITY:
Brian Paule67f6ee2010-10-22 11:38:23 -0600738 case GL_ALPHA:
Jordan Justencf300ea2012-12-27 12:41:10 -0800739 return ctx->API == API_OPENGL_COMPAT &&
740 ctx->Extensions.ARB_framebuffer_object;
Brian Paule67f6ee2010-10-22 11:38:23 -0600741 case GL_RED:
742 case GL_RG:
743 return ctx->Extensions.ARB_texture_rg;
744 default:
745 return GL_FALSE;
746 }
747}
748
749
750/**
Jordan Justen6c7fa722012-12-27 13:34:44 -0800751 * Is the given base format a legal format for a color renderbuffer?
752 */
753static GLboolean
Brian Paulc1377ed2014-03-22 10:31:58 -0600754is_format_color_renderable(const struct gl_context *ctx, mesa_format format,
755 GLenum internalFormat)
Jordan Justen6c7fa722012-12-27 13:34:44 -0800756{
757 const GLenum baseFormat =
758 _mesa_get_format_base_format(format);
759 GLboolean valid;
760
761 valid = _mesa_is_legal_color_format(ctx, baseFormat);
762 if (!valid || _mesa_is_desktop_gl(ctx)) {
763 return valid;
764 }
765
766 /* Reject additional cases for GLES */
767 switch (internalFormat) {
Tapani Pälli0d356cf2018-05-24 14:05:27 +0300768 case GL_R8_SNORM:
769 case GL_RG8_SNORM:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800770 case GL_RGBA8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +0300771 return _mesa_has_EXT_render_snorm(ctx);
772 case GL_R16_SNORM:
773 case GL_RG16_SNORM:
774 case GL_RGBA16_SNORM:
775 return _mesa_has_EXT_texture_norm16(ctx) &&
776 _mesa_has_EXT_render_snorm(ctx);
Jordan Justen6c7fa722012-12-27 13:34:44 -0800777 case GL_RGB32F:
778 case GL_RGB32I:
779 case GL_RGB32UI:
780 case GL_RGB16F:
781 case GL_RGB16I:
782 case GL_RGB16UI:
783 case GL_RGB8_SNORM:
784 case GL_RGB8I:
785 case GL_RGB8UI:
786 case GL_SRGB8:
Eric Anholtc16a7442017-05-01 09:28:33 -0700787 case GL_RGB10:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800788 case GL_RGB9_E5:
Marek Olšák32a33472018-11-09 16:47:46 -0500789 case GL_SR8_EXT:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800790 return GL_FALSE;
791 default:
792 break;
793 }
794
Nicolai Hähnled2b60e42017-09-27 15:25:10 +0200795 if (internalFormat != GL_RGB10_A2 &&
796 (format == MESA_FORMAT_B10G10R10A2_UNORM ||
797 format == MESA_FORMAT_B10G10R10X2_UNORM ||
798 format == MESA_FORMAT_R10G10B10A2_UNORM ||
799 format == MESA_FORMAT_R10G10B10X2_UNORM)) {
Jordan Justen6c7fa722012-12-27 13:34:44 -0800800 return GL_FALSE;
801 }
802
803 return GL_TRUE;
804}
805
806
807/**
Brian Paule67f6ee2010-10-22 11:38:23 -0600808 * Is the given base format a legal format for a depth/stencil renderbuffer?
809 */
810static GLboolean
811is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
812{
813 switch (baseFormat) {
814 case GL_DEPTH_COMPONENT:
815 case GL_DEPTH_STENCIL_EXT:
816 return GL_TRUE;
817 default:
818 return GL_FALSE;
819 }
820}
Brian Paulc26c2002009-09-15 17:20:32 -0600821
822
823/**
Brian Paulf0bbbf62005-02-09 03:50:30 +0000824 * Test if an attachment point is complete and update its Complete field.
825 * \param format if GL_COLOR, this is a color attachment point,
826 * if GL_DEPTH, this is a depth component attachment point,
827 * if GL_STENCIL, this is a stencil component attachment point.
828 */
829static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400830test_attachment_completeness(const struct gl_context *ctx, GLenum format,
Brian Paul2c6f9112005-02-24 05:47:06 +0000831 struct gl_renderbuffer_attachment *att)
Brian Paulf0bbbf62005-02-09 03:50:30 +0000832{
833 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
834
835 /* assume complete */
836 att->Complete = GL_TRUE;
837
Brian Paulf0bbbf62005-02-09 03:50:30 +0000838 /* Look for reasons why the attachment might be incomplete */
839 if (att->Type == GL_TEXTURE) {
Brian Paule4b23562005-05-04 20:11:35 +0000840 const struct gl_texture_object *texObj = att->Texture;
Brian Paulb2c3fd92017-12-04 21:27:54 -0700841 const struct gl_texture_image *texImage;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600842 GLenum baseFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000843
Brian Paule4b23562005-05-04 20:11:35 +0000844 if (!texObj) {
Brian Paul9f731c82009-02-17 16:47:54 -0700845 att_incomplete("no texobj");
Brian Paule4b23562005-05-04 20:11:35 +0000846 att->Complete = GL_FALSE;
847 return;
848 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000849
850 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
851 if (!texImage) {
Brian Paul9f731c82009-02-17 16:47:54 -0700852 att_incomplete("no teximage");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000853 att->Complete = GL_FALSE;
854 return;
855 }
856 if (texImage->Width < 1 || texImage->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700857 att_incomplete("teximage width/height=0");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000858 att->Complete = GL_FALSE;
859 return;
860 }
Ian Romanick25281fe2013-07-27 12:27:45 -0700861
862 switch (texObj->Target) {
863 case GL_TEXTURE_3D:
864 if (att->Zoffset >= texImage->Depth) {
865 att_incomplete("bad z offset");
866 att->Complete = GL_FALSE;
867 return;
868 }
869 break;
870 case GL_TEXTURE_1D_ARRAY:
871 if (att->Zoffset >= texImage->Height) {
872 att_incomplete("bad 1D-array layer");
873 att->Complete = GL_FALSE;
874 return;
875 }
876 break;
877 case GL_TEXTURE_2D_ARRAY:
878 if (att->Zoffset >= texImage->Depth) {
879 att_incomplete("bad 2D-array layer");
880 att->Complete = GL_FALSE;
881 return;
882 }
883 break;
884 case GL_TEXTURE_CUBE_MAP_ARRAY:
885 if (att->Zoffset >= texImage->Depth) {
886 att_incomplete("bad cube-array layer");
887 att->Complete = GL_FALSE;
888 return;
889 }
890 break;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000891 }
892
Ilia Mirkin68c4af12016-02-17 20:31:38 -0500893 baseFormat = texImage->_BaseFormat;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600894
Brian Paulf0bbbf62005-02-09 03:50:30 +0000895 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800896 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700897 att_incomplete("bad format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000898 att->Complete = GL_FALSE;
899 return;
900 }
Brian Paul1f7c9142009-09-30 20:28:45 -0600901 if (_mesa_is_format_compressed(texImage->TexFormat)) {
Eric Anholt957f3c82009-05-15 16:24:59 -0700902 att_incomplete("compressed internalformat");
903 att->Complete = GL_FALSE;
904 return;
905 }
Tapani Pällie3330352015-02-12 14:33:53 +0200906
907 /* OES_texture_float allows creation and use of floating point
908 * textures with GL_FLOAT, GL_HALF_FLOAT but it does not allow
909 * these textures to be used as a render target, this is done via
910 * GL_EXT_color_buffer(_half)_float with set of new sized types.
911 */
Brian Paulc7a81dc2017-10-13 16:16:48 -0600912 if (_mesa_is_gles(ctx) && (texObj->_IsFloat || texObj->_IsHalfFloat)) {
Tapani Pällie3330352015-02-12 14:33:53 +0200913 att_incomplete("bad internal format");
914 att->Complete = GL_FALSE;
915 return;
916 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000917 }
918 else if (format == GL_DEPTH) {
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600919 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000920 /* OK */
921 }
Ian Romanicka92b9e62013-11-13 14:10:34 -0800922 else if (ctx->Extensions.ARB_depth_texture &&
Ian Romanick49493222013-11-13 14:15:11 -0800923 baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000924 /* OK */
925 }
926 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000927 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700928 att_incomplete("bad depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000929 return;
930 }
931 }
932 else {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800933 assert(format == GL_STENCIL);
Ian Romanicka92b9e62013-11-13 14:10:34 -0800934 if (ctx->Extensions.ARB_depth_texture &&
Ian Romanick49493222013-11-13 14:15:11 -0800935 baseFormat == GL_DEPTH_STENCIL) {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600936 /* OK */
Dave Airlie782e71c2015-04-05 13:19:18 +1000937 } else if (ctx->Extensions.ARB_texture_stencil8 &&
938 baseFormat == GL_STENCIL_INDEX) {
939 /* OK */
940 } else {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600941 /* no such thing as stencil-only textures */
942 att_incomplete("illegal stencil texture");
943 att->Complete = GL_FALSE;
944 return;
945 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000946 }
947 }
Brian Paule4b23562005-05-04 20:11:35 +0000948 else if (att->Type == GL_RENDERBUFFER_EXT) {
Ilia Mirkin68c4af12016-02-17 20:31:38 -0500949 const GLenum baseFormat = att->Renderbuffer->_BaseFormat;
Brian Paul45e76d22009-10-08 20:27:27 -0600950
Matt Turnerbfcdb842015-02-20 20:18:47 -0800951 assert(att->Renderbuffer);
Brian Paul49918882006-03-20 15:27:55 +0000952 if (!att->Renderbuffer->InternalFormat ||
953 att->Renderbuffer->Width < 1 ||
954 att->Renderbuffer->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700955 att_incomplete("0x0 renderbuffer");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000956 att->Complete = GL_FALSE;
957 return;
958 }
959 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800960 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700961 att_incomplete("bad renderbuffer color format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000962 att->Complete = GL_FALSE;
963 return;
964 }
965 }
966 else if (format == GL_DEPTH) {
Brian Paul45e76d22009-10-08 20:27:27 -0600967 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000968 /* OK */
969 }
Ian Romanick49493222013-11-13 14:15:11 -0800970 else if (baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000971 /* OK */
972 }
973 else {
Brian Paul9f731c82009-02-17 16:47:54 -0700974 att_incomplete("bad renderbuffer depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000975 att->Complete = GL_FALSE;
976 return;
977 }
978 }
979 else {
980 assert(format == GL_STENCIL);
Ian Romanick49493222013-11-13 14:15:11 -0800981 if (baseFormat == GL_STENCIL_INDEX ||
982 baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000983 /* OK */
984 }
985 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000986 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700987 att_incomplete("bad renderbuffer stencil format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000988 return;
989 }
990 }
991 }
Brian Paule4b23562005-05-04 20:11:35 +0000992 else {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800993 assert(att->Type == GL_NONE);
Brian Paule4b23562005-05-04 20:11:35 +0000994 /* complete */
995 return;
996 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000997}
998
999
1000/**
1001 * Test if the given framebuffer object is complete and update its
1002 * Status field with the results.
Brian Paul3528f692009-01-22 15:13:18 -07001003 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
1004 * driver to make hardware-specific validation/completeness checks.
Brian Paule4b23562005-05-04 20:11:35 +00001005 * Also update the framebuffer's Width and Height fields if the
1006 * framebuffer is complete.
Brian Paulf0bbbf62005-02-09 03:50:30 +00001007 */
Brian Paule4b23562005-05-04 20:11:35 +00001008void
Brian Paulf9288542010-10-22 11:25:14 -06001009_mesa_test_framebuffer_completeness(struct gl_context *ctx,
1010 struct gl_framebuffer *fb)
Brian Paulf0bbbf62005-02-09 03:50:30 +00001011{
Brian Paul989edea2009-01-22 15:05:13 -07001012 GLuint numImages;
1013 GLenum intFormat = GL_NONE; /* color buffers' internal format */
1014 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
Marek Olšák459f05c2018-06-11 18:30:34 -04001015 GLint numColorSamples = -1;
1016 GLint numColorStorageSamples = -1;
1017 GLint numDepthSamples = -1;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001018 GLint fixedSampleLocations = -1;
Brian Paule4b23562005-05-04 20:11:35 +00001019 GLint i;
Brian Paul28b014e2006-04-05 03:05:17 +00001020 GLuint j;
Paul Berry532b1fe2014-01-07 06:29:47 -08001021 /* Covers max_layer_count, is_layered, and layer_tex_target */
1022 bool layer_info_valid = false;
1023 GLuint max_layer_count = 0, att_layer_count;
Brian Paul5306ee72014-01-22 10:02:28 -08001024 bool is_layered = false;
Paul Berry28af1dc2013-11-19 19:01:37 -08001025 GLenum layer_tex_target = 0;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001026 bool has_depth_attachment = false;
1027 bool has_stencil_attachment = false;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001028
Brian Paul36ede892012-01-12 09:17:23 -07001029 assert(_mesa_is_user_fbo(fb));
Brian Paulc7264412005-06-01 00:50:23 +00001030
Marek Olšáke06d6162012-08-04 13:37:03 +02001031 /* we're changing framebuffer fields here */
1032 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1033
Brian Paulf0bbbf62005-02-09 03:50:30 +00001034 numImages = 0;
Brian Paule4b23562005-05-04 20:11:35 +00001035 fb->Width = 0;
1036 fb->Height = 0;
Marek Olšák21d407c2013-03-28 01:50:21 +01001037 fb->_AllColorBuffersFixedPoint = GL_TRUE;
Marek Olšák755648c2013-03-28 01:56:01 +01001038 fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
Kevin Rogovinda819992015-06-17 13:29:50 +03001039 fb->_HasAttachments = true;
Brian Paulff00ab72016-10-10 11:29:14 -06001040 fb->_IntegerBuffers = 0;
Kenneth Graunke5b51d752018-07-21 23:40:16 -07001041 fb->_RGBBuffers = 0;
Ilia Mirkin070a5e52019-02-12 21:32:27 -05001042 fb->_FP32Buffers = 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001043
Brian Paul989edea2009-01-22 15:05:13 -07001044 /* Start at -2 to more easily loop over all attachment points.
1045 * -2: depth buffer
1046 * -1: stencil buffer
1047 * >=0: color buffer
1048 */
Brian Paule4b23562005-05-04 20:11:35 +00001049 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001050 struct gl_renderbuffer_attachment *att;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001051 GLenum f;
Kenneth Graunke69215882019-02-22 01:16:41 -08001052 GLenum baseFormat;
Mark Mueller71fe9432014-01-04 14:11:43 -08001053 mesa_format attFormat;
Paul Berry95140742013-11-19 15:55:51 -08001054 GLenum att_tex_target = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001055
Brian Paul1bc59bf2009-01-22 15:07:34 -07001056 /*
1057 * XXX for ARB_fbo, only check color buffers that are named by
1058 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
1059 */
1060
Brian Paul989edea2009-01-22 15:05:13 -07001061 /* check for attachment completeness
1062 */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001063 if (i == -2) {
Brian Paule4b23562005-05-04 20:11:35 +00001064 att = &fb->Attachment[BUFFER_DEPTH];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001065 test_attachment_completeness(ctx, GL_DEPTH, att);
1066 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001067 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001068 fbo_incomplete(ctx, "depth attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001069 return;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001070 } else if (att->Type != GL_NONE) {
1071 has_depth_attachment = true;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001072 }
1073 }
1074 else if (i == -1) {
Brian Paule4b23562005-05-04 20:11:35 +00001075 att = &fb->Attachment[BUFFER_STENCIL];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001076 test_attachment_completeness(ctx, GL_STENCIL, att);
1077 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001078 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001079 fbo_incomplete(ctx, "stencil attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001080 return;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001081 } else if (att->Type != GL_NONE) {
1082 has_stencil_attachment = true;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001083 }
1084 }
1085 else {
Brian Paule4b23562005-05-04 20:11:35 +00001086 att = &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001087 test_attachment_completeness(ctx, GL_COLOR, att);
1088 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001089 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001090 fbo_incomplete(ctx, "color attachment incomplete", i);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001091 return;
1092 }
1093 }
1094
Brian Paul989edea2009-01-22 15:05:13 -07001095 /* get width, height, format of the renderbuffer/texture
1096 */
Marek Olšák459f05c2018-06-11 18:30:34 -04001097 unsigned attNumSamples, attNumStorageSamples;
1098
Brian Paulf0bbbf62005-02-09 03:50:30 +00001099 if (att->Type == GL_TEXTURE) {
Eric Anholte98c39c2013-05-10 11:51:01 -07001100 const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
Paul Berry95140742013-11-19 15:55:51 -08001101 att_tex_target = att->Texture->Target;
Brian Paul989edea2009-01-22 15:05:13 -07001102 minWidth = MIN2(minWidth, texImg->Width);
1103 maxWidth = MAX2(maxWidth, texImg->Width);
1104 minHeight = MIN2(minHeight, texImg->Height);
1105 maxHeight = MAX2(maxHeight, texImg->Height);
Brian Paula9fc8ba2005-10-05 01:48:07 +00001106 f = texImg->_BaseFormat;
Kenneth Graunke69215882019-02-22 01:16:41 -08001107 baseFormat = f;
Brian Paulca1b5512011-02-28 18:23:23 -07001108 attFormat = texImg->TexFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001109 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001110
Brian Paulc1377ed2014-03-22 10:31:58 -06001111 if (!is_format_color_renderable(ctx, attFormat,
1112 texImg->InternalFormat) &&
Dave Airlie782e71c2015-04-05 13:19:18 +10001113 !is_legal_depth_format(ctx, f) &&
1114 f != GL_STENCIL_INDEX) {
Iago Toral Quirogab6819cd2014-12-15 09:29:55 +01001115 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001116 fbo_incomplete(ctx, "texture attachment incomplete", -1);
Brian Pauled7f3ae2005-06-07 15:03:40 +00001117 return;
1118 }
Chris Forbes61d42ff2012-12-16 20:58:00 +13001119
Chris Forbes61d42ff2012-12-16 20:58:00 +13001120 if (fixedSampleLocations < 0)
1121 fixedSampleLocations = texImg->FixedSampleLocations;
1122 else if (fixedSampleLocations != texImg->FixedSampleLocations) {
1123 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001124 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
Chris Forbes61d42ff2012-12-16 20:58:00 +13001125 return;
1126 }
Marek Olšák459f05c2018-06-11 18:30:34 -04001127
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08001128 if (att->NumSamples > 0)
1129 attNumSamples = att->NumSamples;
1130 else
1131 attNumSamples = texImg->NumSamples;
1132 attNumStorageSamples = attNumSamples;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001133 }
1134 else if (att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul989edea2009-01-22 15:05:13 -07001135 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
1136 maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
1137 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
1138 maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001139 f = att->Renderbuffer->InternalFormat;
Kenneth Graunke69215882019-02-22 01:16:41 -08001140 baseFormat = att->Renderbuffer->_BaseFormat;
Brian Paulca1b5512011-02-28 18:23:23 -07001141 attFormat = att->Renderbuffer->Format;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001142 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001143
Chris Forbes61d42ff2012-12-16 20:58:00 +13001144 /* RENDERBUFFER has fixedSampleLocations implicitly true */
1145 if (fixedSampleLocations < 0)
1146 fixedSampleLocations = GL_TRUE;
1147 else if (fixedSampleLocations != GL_TRUE) {
1148 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001149 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
Chris Forbes61d42ff2012-12-16 20:58:00 +13001150 return;
1151 }
Marek Olšák459f05c2018-06-11 18:30:34 -04001152
1153 attNumSamples = att->Renderbuffer->NumSamples;
1154 attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001155 }
1156 else {
1157 assert(att->Type == GL_NONE);
1158 continue;
1159 }
1160
Marek Olšák459f05c2018-06-11 18:30:34 -04001161 if (i >= 0) {
1162 /* Color buffers. */
1163 if (numColorSamples < 0) {
1164 assert(numColorStorageSamples < 0);
1165 numColorSamples = attNumSamples;
1166 numColorStorageSamples = attNumStorageSamples;
1167 } else if (numColorSamples != attNumSamples ||
1168 numColorStorageSamples != attNumStorageSamples) {
1169 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1170 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1171 return;
1172 }
1173 } else {
1174 /* Depth/stencil buffers. */
1175 if (numDepthSamples < 0) {
1176 numDepthSamples = attNumSamples;
1177 } else if (numDepthSamples != attNumSamples) {
1178 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1179 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1180 return;
1181 }
1182 }
1183
Brian Paulff00ab72016-10-10 11:29:14 -06001184 /* Update flags describing color buffer datatypes */
Marek Olšák21d407c2013-03-28 01:50:21 +01001185 if (i >= 0) {
1186 GLenum type = _mesa_get_format_datatype(attFormat);
1187
Brian Paulff00ab72016-10-10 11:29:14 -06001188 /* check if integer color */
1189 if (_mesa_is_format_integer_color(attFormat))
1190 fb->_IntegerBuffers |= (1 << i);
1191
Kenneth Graunke69215882019-02-22 01:16:41 -08001192 if (baseFormat == GL_RGB)
Kenneth Graunke5b51d752018-07-21 23:40:16 -07001193 fb->_RGBBuffers |= (1 << i);
1194
Ilia Mirkin070a5e52019-02-12 21:32:27 -05001195 if (type == GL_FLOAT && _mesa_get_format_max_bits(attFormat) > 16)
1196 fb->_FP32Buffers |= (1 << i);
1197
Marek Olšák21d407c2013-03-28 01:50:21 +01001198 fb->_AllColorBuffersFixedPoint =
1199 fb->_AllColorBuffersFixedPoint &&
1200 (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
Marek Olšák755648c2013-03-28 01:56:01 +01001201
1202 fb->_HasSNormOrFloatColorBuffer =
1203 fb->_HasSNormOrFloatColorBuffer ||
1204 type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
Marek Olšák21d407c2013-03-28 01:50:21 +01001205 }
1206
Chris Forbes61d42ff2012-12-16 20:58:00 +13001207 /* Error-check width, height, format */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001208 if (numImages == 1) {
Chris Forbes61d42ff2012-12-16 20:58:00 +13001209 /* save format */
Brian Paul722d9762009-01-20 16:58:49 -07001210 if (i >= 0) {
Brian Paulf0bbbf62005-02-09 03:50:30 +00001211 intFormat = f;
Brian Paul722d9762009-01-20 16:58:49 -07001212 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001213 }
1214 else {
Brian Paul989edea2009-01-22 15:05:13 -07001215 if (!ctx->Extensions.ARB_framebuffer_object) {
1216 /* check that width, height, format are same */
1217 if (minWidth != maxWidth || minHeight != maxHeight) {
1218 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001219 fbo_incomplete(ctx, "width or height mismatch", -1);
Brian Paul989edea2009-01-22 15:05:13 -07001220 return;
1221 }
Brian Paul45bd5c42011-12-16 08:44:43 -07001222 /* check that all color buffers are the same format */
Brian Paul989edea2009-01-22 15:05:13 -07001223 if (intFormat != GL_NONE && f != intFormat) {
1224 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001225 fbo_incomplete(ctx, "format mismatch", -1);
Brian Paul989edea2009-01-22 15:05:13 -07001226 return;
1227 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001228 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001229 }
Marek Olšáka82227c2012-06-15 17:21:05 +02001230
1231 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1232 */
1233 if (att->Type == GL_RENDERBUFFER &&
1234 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1235 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001236 fbo_incomplete(ctx, "unsupported renderbuffer format", i);
Marek Olšáka82227c2012-06-15 17:21:05 +02001237 return;
1238 }
Jordan Justen5da82882013-04-18 10:20:05 -07001239
1240 /* Check that layered rendering is consistent. */
Paul Berry95140742013-11-19 15:55:51 -08001241 if (att->Layered) {
1242 if (att_tex_target == GL_TEXTURE_CUBE_MAP)
1243 att_layer_count = 6;
Kenneth Graunke5c399ca2014-05-07 14:35:42 -07001244 else if (att_tex_target == GL_TEXTURE_1D_ARRAY)
1245 att_layer_count = att->Renderbuffer->Height;
Paul Berry95140742013-11-19 15:55:51 -08001246 else
1247 att_layer_count = att->Renderbuffer->Depth;
1248 } else {
1249 att_layer_count = 0;
1250 }
Paul Berry28af1dc2013-11-19 19:01:37 -08001251 if (!layer_info_valid) {
Paul Berry532b1fe2014-01-07 06:29:47 -08001252 is_layered = att->Layered;
1253 max_layer_count = att_layer_count;
Paul Berry28af1dc2013-11-19 19:01:37 -08001254 layer_tex_target = att_tex_target;
1255 layer_info_valid = true;
Paul Berry532b1fe2014-01-07 06:29:47 -08001256 } else if (max_layer_count > 0 && layer_tex_target != att_tex_target) {
Paul Berry28af1dc2013-11-19 19:01:37 -08001257 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1258 fbo_incomplete(ctx, "layered framebuffer has mismatched targets", i);
1259 return;
Paul Berry532b1fe2014-01-07 06:29:47 -08001260 } else if (is_layered != att->Layered) {
1261 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
Brian Paulc1377ed2014-03-22 10:31:58 -06001262 fbo_incomplete(ctx,
1263 "framebuffer attachment layer mode is inconsistent",
1264 i);
Jordan Justen5da82882013-04-18 10:20:05 -07001265 return;
Paul Berry532b1fe2014-01-07 06:29:47 -08001266 } else if (att_layer_count > max_layer_count) {
1267 max_layer_count = att_layer_count;
Jordan Justen5da82882013-04-18 10:20:05 -07001268 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001269
1270 /*
1271 * The extension GL_ARB_framebuffer_no_attachments places additional
1272 * requirement on each attachment. Those additional requirements are
1273 * tighter that those of previous versions of GL. In interest of better
1274 * compatibility, we will not enforce these restrictions. For the record
1275 * those additional restrictions are quoted below:
1276 *
1277 * "The width and height of image are greater than zero and less than or
1278 * equal to the values of the implementation-dependent limits
1279 * MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively."
1280 *
1281 * "If <image> is a three-dimensional texture or a one- or two-dimensional
1282 * array texture and the attachment is layered, the depth or layer count
1283 * of the texture is less than or equal to the implementation-dependent
1284 * limit MAX_FRAMEBUFFER_LAYERS."
1285 *
1286 * "If image has multiple samples, its sample count is less than or equal
1287 * to the value of the implementation-dependent limit
1288 * MAX_FRAMEBUFFER_SAMPLES."
1289 *
1290 * The same requirements are also in place for GL 4.5,
1291 * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
1292 */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001293 }
1294
Marek Olšák459f05c2018-06-11 18:30:34 -04001295 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
1296 /* See if non-matching sample counts are supported. */
1297 if (numColorSamples >= 0 && numDepthSamples >= 0) {
1298 bool found = false;
1299
1300 assert(numColorStorageSamples != -1);
1301
1302 numColorSamples = MAX2(numColorSamples, 1);
1303 numColorStorageSamples = MAX2(numColorStorageSamples, 1);
1304 numDepthSamples = MAX2(numDepthSamples, 1);
1305
1306 if (numColorSamples == 1 && numColorStorageSamples == 1 &&
1307 numDepthSamples == 1) {
1308 found = true;
1309 } else {
1310 for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
1311 GLint *counts =
1312 &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
1313
1314 if (counts[0] == numColorSamples &&
1315 counts[1] == numColorStorageSamples &&
1316 counts[2] == numDepthSamples) {
1317 found = true;
1318 break;
1319 }
1320 }
1321 }
1322
1323 if (!found) {
1324 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1325 fbo_incomplete(ctx, "unsupported sample counts", -1);
1326 return;
1327 }
1328 }
1329 } else {
1330 /* If the extension is unsupported, all sample counts must be equal. */
1331 if (numColorSamples >= 0 &&
1332 (numColorSamples != numColorStorageSamples ||
1333 (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
1334 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1335 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1336 return;
1337 }
1338 }
1339
Paul Berry532b1fe2014-01-07 06:29:47 -08001340 fb->MaxNumLayers = max_layer_count;
Jordan Justen5da82882013-04-18 10:20:05 -07001341
Chris Forbesa419a1c2014-03-23 22:41:28 +13001342 if (numImages == 0) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001343 fb->_HasAttachments = false;
1344
1345 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1346 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1347 fbo_incomplete(ctx, "no attachments", -1);
1348 return;
1349 }
1350
1351 if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) {
1352 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1353 fbo_incomplete(ctx, "no attachments and default width or height is 0", -1);
1354 return;
1355 }
Chris Forbesa419a1c2014-03-23 22:41:28 +13001356 }
1357
Jordan Justen09714c02012-07-19 11:27:16 -07001358 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001359 /* Check that all DrawBuffers are present */
1360 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001361 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1362 const struct gl_renderbuffer_attachment *att
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02001363 = get_attachment(ctx, fb, fb->ColorDrawBuffer[j], NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001364 assert(att);
1365 if (att->Type == GL_NONE) {
1366 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1367 fbo_incomplete(ctx, "missing drawbuffer", j);
1368 return;
1369 }
1370 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001371 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001372
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001373 /* Check that the ReadBuffer is present */
1374 if (fb->ColorReadBuffer != GL_NONE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001375 const struct gl_renderbuffer_attachment *att
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02001376 = get_attachment(ctx, fb, fb->ColorReadBuffer, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001377 assert(att);
1378 if (att->Type == GL_NONE) {
1379 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001380 fbo_incomplete(ctx, "missing readbuffer", -1);
Martin Peres7bd8b482015-02-12 17:54:43 +02001381 return;
1382 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001383 }
1384 }
1385
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001386 /* The OpenGL ES3 spec, in chapter 9.4. FRAMEBUFFER COMPLETENESS, says:
1387 *
1388 * "Depth and stencil attachments, if present, are the same image."
1389 *
1390 * This restriction is not present in the OpenGL ES2 spec.
1391 */
1392 if (_mesa_is_gles3(ctx) &&
1393 has_stencil_attachment && has_depth_attachment &&
1394 !_mesa_has_depthstencil_combined(fb)) {
1395 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1396 fbo_incomplete(ctx, "Depth and stencil attachments must be the same image", -1);
1397 return;
1398 }
1399
Brian Paul3528f692009-01-22 15:13:18 -07001400 /* Provisionally set status = COMPLETE ... */
Brian Paule4b23562005-05-04 20:11:35 +00001401 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
Brian Paul3528f692009-01-22 15:13:18 -07001402
Brian Paul777a2ef2009-01-22 15:17:42 -07001403 /* ... but the driver may say the FB is incomplete.
1404 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1405 * if anything.
1406 */
Brian Paul3528f692009-01-22 15:13:18 -07001407 if (ctx->Driver.ValidateFramebuffer) {
1408 ctx->Driver.ValidateFramebuffer(ctx, fb);
Brian Paul1f32c412009-01-19 17:34:19 -07001409 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001410 fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001411 return;
Brian Paul1f32c412009-01-19 17:34:19 -07001412 }
Brian Paul3528f692009-01-22 15:13:18 -07001413 }
1414
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001415 /*
1416 * Note that if ARB_framebuffer_object is supported and the attached
1417 * renderbuffers/textures are different sizes, the framebuffer
1418 * width/height will be set to the smallest width/height.
1419 */
1420 if (numImages != 0) {
1421 fb->Width = minWidth;
1422 fb->Height = minHeight;
Brian Paul3528f692009-01-22 15:13:18 -07001423 }
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001424
1425 /* finally, update the visual info for the framebuffer */
1426 _mesa_update_framebuffer_visual(ctx, fb);
Brian Paule4b23562005-05-04 20:11:35 +00001427}
Brian Paulf0bbbf62005-02-09 03:50:30 +00001428
1429
Brian Paul1864c7d2005-02-08 03:46:37 +00001430GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001431_mesa_IsRenderbuffer(GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001432{
Samuel Pitoiset78392432017-04-06 18:05:36 +02001433 struct gl_renderbuffer *rb;
1434
Brian Paulddc82ee2005-02-05 19:56:45 +00001435 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoiset78392432017-04-06 18:05:36 +02001436
Brian Paulddc82ee2005-02-05 19:56:45 +00001437 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Samuel Pitoiset78392432017-04-06 18:05:36 +02001438
1439 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1440 return rb != NULL && rb != &DummyRenderbuffer;
Brian Paulddc82ee2005-02-05 19:56:45 +00001441}
1442
1443
Martin Peresa34669b2015-02-12 18:52:10 +02001444static struct gl_renderbuffer *
Matt Turner015f2202015-07-30 14:31:04 -07001445allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
1446 const char *func)
Martin Peresa34669b2015-02-12 18:52:10 +02001447{
1448 struct gl_renderbuffer *newRb;
1449
1450 /* create new renderbuffer object */
1451 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1452 if (!newRb) {
1453 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1454 return NULL;
1455 }
1456 assert(newRb->AllocStorage);
Matt Turner015f2202015-07-30 14:31:04 -07001457 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer, newRb);
Martin Peresa34669b2015-02-12 18:52:10 +02001458
1459 return newRb;
1460}
1461
1462
Ian Romanick97965e82013-07-18 17:38:16 -07001463static void
Timothy Arcerib54a2312018-09-08 14:20:17 +10001464bind_renderbuffer(GLenum target, GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001465{
Brian42aaa542007-03-25 10:39:36 -06001466 struct gl_renderbuffer *newRb;
Brian Paulddc82ee2005-02-05 19:56:45 +00001467 GET_CURRENT_CONTEXT(ctx);
1468
Brian Paul3deaa012005-02-07 05:08:24 +00001469 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul4de18fb2009-11-02 15:30:51 -07001470 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00001471 return;
1472 }
1473
Brian Paul800e5532009-11-02 15:39:39 -07001474 /* No need to flush here since the render buffer binding has no
1475 * effect on rendering state.
1476 */
Brian Paul474f28e2005-10-08 14:41:17 +00001477
Brian Paul3deaa012005-02-07 05:08:24 +00001478 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00001479 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001480 if (newRb == &DummyRenderbuffer) {
1481 /* ID was reserved, but no real renderbuffer object made yet */
1482 newRb = NULL;
1483 }
Timothy Arcerib54a2312018-09-08 14:20:17 +10001484 else if (!newRb && ctx->API == API_OPENGL_CORE) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07001485 /* All RB IDs must be Gen'd */
Timothy Arcerib54a2312018-09-08 14:20:17 +10001486 _mesa_error(ctx, GL_INVALID_OPERATION,
1487 "glBindRenderbuffer(non-gen name)");
Brian Paul1bc59bf2009-01-22 15:07:34 -07001488 return;
1489 }
1490
Brian Paul3deaa012005-02-07 05:08:24 +00001491 if (!newRb) {
Matt Turner015f2202015-07-30 14:31:04 -07001492 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1493 newRb = allocate_renderbuffer_locked(ctx, renderbuffer,
1494 "glBindRenderbufferEXT");
1495 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
Brian Paul3deaa012005-02-07 05:08:24 +00001496 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001497 }
Brian Paul463642c2005-02-08 02:06:00 +00001498 else {
1499 newRb = NULL;
1500 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001501
Matt Turnerbfcdb842015-02-20 20:18:47 -08001502 assert(newRb != &DummyRenderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001503
Brian42aaa542007-03-25 10:39:36 -06001504 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
Brian Paulddc82ee2005-02-05 19:56:45 +00001505}
1506
Ian Romanick97965e82013-07-18 17:38:16 -07001507void GLAPIENTRY
1508_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1509{
Ian Romanick97965e82013-07-18 17:38:16 -07001510 /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1511 * entry point, but they allow the use of user-generated names.
1512 */
Timothy Arcerib54a2312018-09-08 14:20:17 +10001513 bind_renderbuffer(target, renderbuffer);
Ian Romanick97965e82013-07-18 17:38:16 -07001514}
Brian Paulddc82ee2005-02-05 19:56:45 +00001515
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001516void GLAPIENTRY
1517_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1518{
Timothy Arcerib54a2312018-09-08 14:20:17 +10001519 bind_renderbuffer(target, renderbuffer);
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001520}
1521
Edward O'Callaghanb40375a2016-02-17 19:15:49 +11001522/**
Rhys Perry67f40da2018-06-14 19:56:28 -06001523 * ARB_framebuffer_no_attachment and ARB_sample_locations - Application passes
1524 * requested param's here. NOTE: NumSamples requested need not be _NumSamples
1525 * which is what the hw supports.
Edward O'Callaghanb40375a2016-02-17 19:15:49 +11001526 */
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001527static void
1528framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
1529 GLenum pname, GLint param, const char *func)
1530{
Rhys Perry67f40da2018-06-14 19:56:28 -06001531 bool cannot_be_winsys_fbo = false;
1532
1533 switch (pname) {
1534 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1535 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1536 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1537 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1538 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1539 if (!ctx->Extensions.ARB_framebuffer_no_attachments)
1540 goto invalid_pname_enum;
1541 cannot_be_winsys_fbo = true;
1542 break;
1543 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1544 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1545 if (!ctx->Extensions.ARB_sample_locations)
1546 goto invalid_pname_enum;
1547 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001548 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1549 if (!ctx->Extensions.MESA_framebuffer_flip_y)
1550 goto invalid_pname_enum;
1551 cannot_be_winsys_fbo = true;
Fritz Koenig60d0c0d2018-09-14 11:40:49 -07001552 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001553 default:
1554 goto invalid_pname_enum;
1555 }
1556
1557 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1558 _mesa_error(ctx, GL_INVALID_OPERATION,
1559 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1560 return;
1561 }
1562
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001563 switch (pname) {
1564 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1565 if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
1566 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1567 else
1568 fb->DefaultGeometry.Width = param;
1569 break;
1570 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1571 if (param < 0 || param > ctx->Const.MaxFramebufferHeight)
1572 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1573 else
1574 fb->DefaultGeometry.Height = param;
1575 break;
1576 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001577 /*
1578 * According to the OpenGL ES 3.1 specification section 9.2.1, the
1579 * GL_FRAMEBUFFER_DEFAULT_LAYERS parameter name is not supported.
1580 */
Ilia Mirkin82d756f2016-05-21 20:26:47 -04001581 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001582 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1583 break;
1584 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001585 if (param < 0 || param > ctx->Const.MaxFramebufferLayers)
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001586 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001587 else
1588 fb->DefaultGeometry.Layers = param;
1589 break;
1590 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1591 if (param < 0 || param > ctx->Const.MaxFramebufferSamples)
1592 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1593 else
1594 fb->DefaultGeometry.NumSamples = param;
1595 break;
1596 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1597 fb->DefaultGeometry.FixedSampleLocations = param;
1598 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001599 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1600 fb->ProgrammableSampleLocations = !!param;
1601 break;
1602 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1603 fb->SampleLocationPixelGrid = !!param;
1604 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001605 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1606 fb->FlipY = param;
1607 break;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001608 }
Ilia Mirkin095da3b2016-01-23 09:27:22 -05001609
Rhys Perry67f40da2018-06-14 19:56:28 -06001610 switch (pname) {
1611 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1612 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1613 if (fb == ctx->DrawBuffer)
1614 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
1615 break;
1616 default:
1617 invalidate_framebuffer(fb);
1618 ctx->NewState |= _NEW_BUFFERS;
1619 break;
1620 }
1621
1622 return;
1623
1624invalid_pname_enum:
1625 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001626}
1627
Fritz Koenig66937ab2019-07-30 14:53:30 -07001628static bool
1629validate_framebuffer_parameter_extensions(GLenum pname, const char *func)
1630{
1631 GET_CURRENT_CONTEXT(ctx);
1632
1633 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
1634 !ctx->Extensions.ARB_sample_locations &&
1635 !ctx->Extensions.MESA_framebuffer_flip_y) {
1636 _mesa_error(ctx, GL_INVALID_OPERATION,
1637 "%s not supported "
1638 "(none of ARB_framebuffer_no_attachments,"
1639 " ARB_sample_locations, or"
1640 " MESA_framebuffer_flip_y extensions are available)",
1641 func);
1642 return false;
1643 }
1644
1645 /*
1646 * If only the MESA_framebuffer_flip_y extension is enabled
1647 * pname can only be GL_FRAMEBUFFER_FLIP_Y_MESA
1648 */
1649 if (ctx->Extensions.MESA_framebuffer_flip_y &&
1650 pname != GL_FRAMEBUFFER_FLIP_Y_MESA &&
1651 !(ctx->Extensions.ARB_framebuffer_no_attachments ||
1652 ctx->Extensions.ARB_sample_locations)) {
1653 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1654 return false;
1655 }
1656
1657 return true;
1658}
1659
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001660void GLAPIENTRY
1661_mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
1662{
1663 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001664 struct gl_framebuffer *fb;
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001665
Fritz Koenig66937ab2019-07-30 14:53:30 -07001666 if (!validate_framebuffer_parameter_extensions(pname,
1667 "glFramebufferParameteri")) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001668 return;
1669 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001670
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001671 fb = get_framebuffer_target(ctx, target);
1672 if (!fb) {
1673 _mesa_error(ctx, GL_INVALID_ENUM,
1674 "glFramebufferParameteri(target=0x%x)", target);
1675 return;
1676 }
1677
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001678 framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
1679}
1680
Fritz Koenig66937ab2019-07-30 14:53:30 -07001681void GLAPIENTRY
1682_mesa_FramebufferParameteriMESA(GLenum target, GLenum pname, GLint param)
1683{
1684 _mesa_FramebufferParameteri(target, pname, param);
1685}
1686
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001687static bool
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001688validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
1689 struct gl_framebuffer *fb,
1690 GLuint pname, const char *func)
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001691{
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001692 bool cannot_be_winsys_fbo = true;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001693
1694 switch (pname) {
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001695 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1696 /*
1697 * According to the OpenGL ES 3.1 specification section 9.2.3, the
1698 * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
1699 */
1700 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1701 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1702 return false;
1703 }
1704 break;
1705 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1706 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1707 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1708 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1709 break;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001710 case GL_DOUBLEBUFFER:
1711 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1712 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1713 case GL_SAMPLES:
1714 case GL_SAMPLE_BUFFERS:
1715 case GL_STEREO:
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001716 /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
1717 *
1718 * "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
1719 * if the default framebuffer is bound to target and pname is not one
1720 * of the accepted values from table 23.73, other than
1721 * SAMPLE_POSITION."
1722 *
1723 * For OpenGL ES, using default framebuffer raises INVALID_OPERATION
1724 * for any pname.
1725 */
1726 cannot_be_winsys_fbo = !_mesa_is_desktop_gl(ctx);
1727 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001728 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1729 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1730 if (!ctx->Extensions.ARB_sample_locations)
1731 goto invalid_pname_enum;
1732 cannot_be_winsys_fbo = false;
1733 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001734 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1735 if (!ctx->Extensions.MESA_framebuffer_flip_y) {
1736 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1737 return false;
1738 }
1739 break;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001740 default:
Rhys Perry67f40da2018-06-14 19:56:28 -06001741 goto invalid_pname_enum;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001742 }
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001743
1744 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1745 _mesa_error(ctx, GL_INVALID_OPERATION,
1746 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1747 return false;
1748 }
1749
1750 return true;
Rhys Perry67f40da2018-06-14 19:56:28 -06001751
1752invalid_pname_enum:
1753 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1754 return false;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001755}
1756
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001757static void
1758get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
1759 GLenum pname, GLint *params, const char *func)
1760{
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001761 if (!validate_get_framebuffer_parameteriv_pname(ctx, fb, pname, func))
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001762 return;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001763
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001764 switch (pname) {
1765 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1766 *params = fb->DefaultGeometry.Width;
1767 break;
1768 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1769 *params = fb->DefaultGeometry.Height;
1770 break;
1771 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1772 *params = fb->DefaultGeometry.Layers;
1773 break;
1774 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1775 *params = fb->DefaultGeometry.NumSamples;
1776 break;
1777 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1778 *params = fb->DefaultGeometry.FixedSampleLocations;
1779 break;
Alejandro Piñeiro0fb0c572017-01-13 16:23:05 -02001780 case GL_DOUBLEBUFFER:
1781 *params = fb->Visual.doubleBufferMode;
1782 break;
1783 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1784 *params = _mesa_get_color_read_format(ctx, fb, func);
1785 break;
1786 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1787 *params = _mesa_get_color_read_type(ctx, fb, func);
1788 break;
1789 case GL_SAMPLES:
1790 *params = _mesa_geometric_samples(fb);
1791 break;
1792 case GL_SAMPLE_BUFFERS:
1793 *params = _mesa_geometric_samples(fb) > 0;
1794 break;
1795 case GL_STEREO:
1796 *params = fb->Visual.stereoMode;
1797 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001798 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1799 *params = fb->ProgrammableSampleLocations;
1800 break;
1801 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1802 *params = fb->SampleLocationPixelGrid;
1803 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001804 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1805 *params = fb->FlipY;
1806 break;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001807 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001808}
1809
1810void GLAPIENTRY
1811_mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
1812{
1813 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001814 struct gl_framebuffer *fb;
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001815
Fritz Koenig66937ab2019-07-30 14:53:30 -07001816 if (!validate_framebuffer_parameter_extensions(pname,
1817 "glGetFramebufferParameteriv")) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001818 return;
1819 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001820
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001821 fb = get_framebuffer_target(ctx, target);
1822 if (!fb) {
1823 _mesa_error(ctx, GL_INVALID_ENUM,
1824 "glGetFramebufferParameteriv(target=0x%x)", target);
1825 return;
1826 }
1827
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001828 get_framebuffer_parameteriv(ctx, fb, pname, params,
1829 "glGetFramebufferParameteriv");
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001830}
1831
Fritz Koenig66937ab2019-07-30 14:53:30 -07001832void GLAPIENTRY
1833_mesa_GetFramebufferParameterivMESA(GLenum target, GLenum pname, GLint *params)
1834{
1835 _mesa_GetFramebufferParameteriv(target, pname, params);
1836}
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001837
Brian Pauld0f13fa2009-01-21 11:17:45 -07001838/**
Ian Romanickef83bd22013-08-08 15:41:36 -07001839 * Remove the specified renderbuffer or texture from any attachment point in
1840 * the framebuffer.
Ian Romanick438cc6b2013-08-08 15:26:36 -07001841 *
1842 * \returns
1843 * \c true if the renderbuffer was detached from an attachment point. \c
1844 * false otherwise.
Brian Pauld0f13fa2009-01-21 11:17:45 -07001845 */
Ian Romanick438cc6b2013-08-08 15:26:36 -07001846bool
1847_mesa_detach_renderbuffer(struct gl_context *ctx,
1848 struct gl_framebuffer *fb,
1849 const void *att)
Brian Pauld0f13fa2009-01-21 11:17:45 -07001850{
Ian Romanick438cc6b2013-08-08 15:26:36 -07001851 unsigned i;
1852 bool progress = false;
1853
Brian Pauld0f13fa2009-01-21 11:17:45 -07001854 for (i = 0; i < BUFFER_COUNT; i++) {
Ian Romanickef83bd22013-08-08 15:41:36 -07001855 if (fb->Attachment[i].Texture == att
1856 || fb->Attachment[i].Renderbuffer == att) {
Brian Paul94512812014-02-01 08:58:43 -07001857 remove_attachment(ctx, &fb->Attachment[i]);
Ian Romanick438cc6b2013-08-08 15:26:36 -07001858 progress = true;
Brian Pauld0f13fa2009-01-21 11:17:45 -07001859 }
1860 }
Ian Romanick438cc6b2013-08-08 15:26:36 -07001861
1862 /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1863 * Completeness," of the OpenGL 3.1 spec says:
1864 *
1865 * "Performing any of the following actions may change whether the
1866 * framebuffer is considered complete or incomplete:
1867 *
1868 * ...
1869 *
1870 * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1871 * containing an image that is attached to a framebuffer object
1872 * that is bound to the framebuffer."
1873 */
1874 if (progress)
1875 invalidate_framebuffer(fb);
1876
1877 return progress;
Brian Pauld0f13fa2009-01-21 11:17:45 -07001878}
1879
1880
Brian Paul1864c7d2005-02-08 03:46:37 +00001881void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001882_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001883{
1884 GLint i;
1885 GET_CURRENT_CONTEXT(ctx);
1886
Eduardo Lima Mitev2012f622014-12-11 23:34:18 +01001887 if (n < 0) {
1888 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteRenderbuffers(n < 0)");
1889 return;
1890 }
1891
Brian Paul474f28e2005-10-08 14:41:17 +00001892 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00001893
1894 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001895 if (renderbuffers[i] > 0) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001896 struct gl_renderbuffer *rb;
1897 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
1898 if (rb) {
Brian Paul91802fd2005-10-04 16:01:02 +00001899 /* check if deleting currently bound renderbuffer object */
1900 if (rb == ctx->CurrentRenderbuffer) {
1901 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08001902 assert(rb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001903 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
Brian Paul91802fd2005-10-04 16:01:02 +00001904 }
1905
Ian Romanickef83bd22013-08-08 15:41:36 -07001906 /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
Brian Paulc1377ed2014-03-22 10:31:58 -06001907 * subsection "Attaching Renderbuffer Images to a Framebuffer,"
1908 * of the OpenGL 3.1 spec says:
Ian Romanickef83bd22013-08-08 15:41:36 -07001909 *
1910 * "If a renderbuffer object is deleted while its image is
1911 * attached to one or more attachment points in the currently
1912 * bound framebuffer, then it is as if FramebufferRenderbuffer
1913 * had been called, with a renderbuffer of 0, for each
1914 * attachment point to which this image was attached in the
1915 * currently bound framebuffer. In other words, this
1916 * renderbuffer image is first detached from all attachment
1917 * points in the currently bound framebuffer. Note that the
1918 * renderbuffer image is specifically not detached from any
1919 * non-bound framebuffers. Detaching the image from any
1920 * non-bound framebuffers is the responsibility of the
1921 * application.
1922 */
Brian Paul36ede892012-01-12 09:17:23 -07001923 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
Ian Romanick438cc6b2013-08-08 15:26:36 -07001924 _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07001925 }
Brian Paul36ede892012-01-12 09:17:23 -07001926 if (_mesa_is_user_fbo(ctx->ReadBuffer)
Brian Paulfc8c4a32011-06-16 07:31:58 -06001927 && ctx->ReadBuffer != ctx->DrawBuffer) {
Ian Romanick438cc6b2013-08-08 15:26:36 -07001928 _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07001929 }
1930
Martin Peres7bd8b482015-02-12 17:54:43 +02001931 /* Remove from hash table immediately, to free the ID.
Brian42aaa542007-03-25 10:39:36 -06001932 * But the object will not be freed until it's no longer
1933 * referenced anywhere else.
1934 */
Martin Peres7bd8b482015-02-12 17:54:43 +02001935 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00001936
Brian Paul1864c7d2005-02-08 03:46:37 +00001937 if (rb != &DummyRenderbuffer) {
Brian42aaa542007-03-25 10:39:36 -06001938 /* no longer referenced by hash table */
1939 _mesa_reference_renderbuffer(&rb, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001940 }
1941 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001942 }
1943 }
1944}
1945
Martin Peresa34669b2015-02-12 18:52:10 +02001946static void
1947create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
1948 bool dsa)
Brian Paulddc82ee2005-02-05 19:56:45 +00001949{
Martin Peresa34669b2015-02-12 18:52:10 +02001950 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
Brian Paulddc82ee2005-02-05 19:56:45 +00001951 GLuint first;
1952 GLint i;
1953
Brian Paulddc82ee2005-02-05 19:56:45 +00001954 if (!renderbuffers)
1955 return;
1956
Matt Turner015f2202015-07-30 14:31:04 -07001957 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1958
Brian Paulddc82ee2005-02-05 19:56:45 +00001959 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1960
1961 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001962 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001963 renderbuffers[i] = name;
Martin Peresa34669b2015-02-12 18:52:10 +02001964
1965 if (dsa) {
Matt Turner015f2202015-07-30 14:31:04 -07001966 allocate_renderbuffer_locked(ctx, name, func);
Martin Peresa34669b2015-02-12 18:52:10 +02001967 } else {
Martin Peresfa383212015-03-25 16:28:03 +02001968 /* insert a dummy renderbuffer into the hash table */
Matt Turner015f2202015-07-30 14:31:04 -07001969 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, name,
1970 &DummyRenderbuffer);
Martin Peresa34669b2015-02-12 18:52:10 +02001971 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001972 }
Matt Turner015f2202015-07-30 14:31:04 -07001973
1974 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
Brian Paulddc82ee2005-02-05 19:56:45 +00001975}
1976
1977
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02001978static void
1979create_render_buffers_err(struct gl_context *ctx, GLsizei n,
1980 GLuint *renderbuffers, bool dsa)
1981{
1982 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
1983
1984 if (n < 0) {
1985 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
1986 return;
1987 }
1988
1989 create_render_buffers(ctx, n, renderbuffers, dsa);
1990}
1991
1992
Martin Peresa34669b2015-02-12 18:52:10 +02001993void GLAPIENTRY
Samuel Pitoisetb87a2cb2017-06-26 18:27:49 +02001994_mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
1995{
1996 GET_CURRENT_CONTEXT(ctx);
1997 create_render_buffers(ctx, n, renderbuffers, false);
1998}
1999
2000
2001void GLAPIENTRY
Martin Peresa34669b2015-02-12 18:52:10 +02002002_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
2003{
2004 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02002005 create_render_buffers_err(ctx, n, renderbuffers, false);
Martin Peresa34669b2015-02-12 18:52:10 +02002006}
2007
2008
2009void GLAPIENTRY
Samuel Pitoisetb87a2cb2017-06-26 18:27:49 +02002010_mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
2011{
2012 GET_CURRENT_CONTEXT(ctx);
2013 create_render_buffers(ctx, n, renderbuffers, true);
2014}
2015
2016
2017void GLAPIENTRY
Martin Peresa34669b2015-02-12 18:52:10 +02002018_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
2019{
2020 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02002021 create_render_buffers_err(ctx, n, renderbuffers, true);
Martin Peresa34669b2015-02-12 18:52:10 +02002022}
2023
2024
Brian Pauld9468c92005-02-10 16:08:07 +00002025/**
Brian Paulf41bbc72011-01-24 19:38:52 -07002026 * Given an internal format token for a render buffer, return the
Brian Paul976ea9d2011-01-24 19:38:52 -07002027 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
2028 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
2029 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
Brian Paulf41bbc72011-01-24 19:38:52 -07002030 *
Brian Paul976ea9d2011-01-24 19:38:52 -07002031 * This is similar to _mesa_base_tex_format() but the set of valid
2032 * internal formats is different.
Brian Paulf41bbc72011-01-24 19:38:52 -07002033 *
Brian Paul976ea9d2011-01-24 19:38:52 -07002034 * Note that even if a format is determined to be legal here, validation
Brian Paulb3cfcdf2011-01-28 20:25:26 -07002035 * of the FBO may fail if the format is not supported by the driver/GPU.
Brian Paul976ea9d2011-01-24 19:38:52 -07002036 *
2037 * \param internalFormat as passed to glRenderbufferStorage()
2038 * \return the base internal format, or 0 if internalFormat is illegal
Brian Pauld9468c92005-02-10 16:08:07 +00002039 */
Brian Paul59e0faa2006-03-15 17:48:00 +00002040GLenum
Brian Paulca78b6b2017-12-05 12:05:18 -07002041_mesa_base_fbo_format(const struct gl_context *ctx, GLenum internalFormat)
Brian Paul463642c2005-02-08 02:06:00 +00002042{
Brian Paul976ea9d2011-01-24 19:38:52 -07002043 /*
2044 * Notes: some formats such as alpha, luminance, etc. were added
2045 * with GL_ARB_framebuffer_object.
2046 */
Brian Paul463642c2005-02-08 02:06:00 +00002047 switch (internalFormat) {
Brian Paulf41bbc72011-01-24 19:38:52 -07002048 case GL_ALPHA:
2049 case GL_ALPHA4:
2050 case GL_ALPHA8:
2051 case GL_ALPHA12:
2052 case GL_ALPHA16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002053 return (ctx->API == API_OPENGL_COMPAT &&
2054 ctx->Extensions.ARB_framebuffer_object) ? GL_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002055 case GL_LUMINANCE:
2056 case GL_LUMINANCE4:
2057 case GL_LUMINANCE8:
2058 case GL_LUMINANCE12:
2059 case GL_LUMINANCE16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002060 return (ctx->API == API_OPENGL_COMPAT &&
2061 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002062 case GL_LUMINANCE_ALPHA:
2063 case GL_LUMINANCE4_ALPHA4:
2064 case GL_LUMINANCE6_ALPHA2:
2065 case GL_LUMINANCE8_ALPHA8:
2066 case GL_LUMINANCE12_ALPHA4:
2067 case GL_LUMINANCE12_ALPHA12:
2068 case GL_LUMINANCE16_ALPHA16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002069 return (ctx->API == API_OPENGL_COMPAT &&
2070 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002071 case GL_INTENSITY:
2072 case GL_INTENSITY4:
2073 case GL_INTENSITY8:
2074 case GL_INTENSITY12:
2075 case GL_INTENSITY16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002076 return (ctx->API == API_OPENGL_COMPAT &&
2077 ctx->Extensions.ARB_framebuffer_object) ? GL_INTENSITY : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002078 case GL_RGB8:
2079 return GL_RGB;
Brian Paulf41bbc72011-01-24 19:38:52 -07002080 case GL_RGB:
2081 case GL_R3_G3_B2:
2082 case GL_RGB4:
2083 case GL_RGB5:
Brian Paulf41bbc72011-01-24 19:38:52 -07002084 case GL_RGB10:
2085 case GL_RGB12:
2086 case GL_RGB16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002087 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002088 case GL_SRGB8_EXT:
Matt Turnercbef5372012-11-20 13:45:03 -08002089 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002090 case GL_RGBA4:
2091 case GL_RGB5_A1:
2092 case GL_RGBA8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002093 return GL_RGBA;
2094 case GL_RGBA:
2095 case GL_RGBA2:
Brian Paulf41bbc72011-01-24 19:38:52 -07002096 case GL_RGBA12:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002097 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
Tapani Pällice80abb2018-07-24 08:58:20 +03002098 case GL_RGBA16:
2099 return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2100 ? GL_RGBA : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002101 case GL_RGB10_A2:
Brian Paulf41bbc72011-01-24 19:38:52 -07002102 case GL_SRGB8_ALPHA8_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002103 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00002104 case GL_STENCIL_INDEX:
2105 case GL_STENCIL_INDEX1_EXT:
2106 case GL_STENCIL_INDEX4_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002107 case GL_STENCIL_INDEX16_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002108 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
2109 * OpenGL ES, but Mesa does not currently support them.
2110 */
2111 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
2112 case GL_STENCIL_INDEX8_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002113 return GL_STENCIL_INDEX;
2114 case GL_DEPTH_COMPONENT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002115 case GL_DEPTH_COMPONENT32:
2116 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
Brian Paul2c6f9112005-02-24 05:47:06 +00002117 case GL_DEPTH_COMPONENT16:
2118 case GL_DEPTH_COMPONENT24:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002119 return GL_DEPTH_COMPONENT;
Ian Romanick49493222013-11-13 14:15:11 -08002120 case GL_DEPTH_STENCIL:
2121 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_STENCIL : 0;
2122 case GL_DEPTH24_STENCIL8:
2123 return GL_DEPTH_STENCIL;
Marek Olšák11652802011-06-01 15:48:51 +02002124 case GL_DEPTH_COMPONENT32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002125 return ctx->Version >= 30
Brian Paulc1377ed2014-03-22 10:31:58 -06002126 || (ctx->API == API_OPENGL_COMPAT &&
2127 ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002128 ? GL_DEPTH_COMPONENT : 0;
Marek Olšák11652802011-06-01 15:48:51 +02002129 case GL_DEPTH32F_STENCIL8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002130 return ctx->Version >= 30
Brian Paulc1377ed2014-03-22 10:31:58 -06002131 || (ctx->API == API_OPENGL_COMPAT &&
2132 ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002133 ? GL_DEPTH_STENCIL : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002134 case GL_RED:
Tapani Pällice80abb2018-07-24 08:58:20 +03002135 return _mesa_has_ARB_texture_rg(ctx) ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002136 case GL_R16:
Tapani Pällice80abb2018-07-24 08:58:20 +03002137 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002138 ? GL_RED : 0;
2139 case GL_R8:
2140 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2141 ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002142 case GL_RG:
Tapani Pällice80abb2018-07-24 08:58:20 +03002143 return _mesa_has_ARB_texture_rg(ctx) ? GL_RG : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002144 case GL_RG16:
Tapani Pällice80abb2018-07-24 08:58:20 +03002145 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002146 ? GL_RG : 0;
2147 case GL_RG8:
2148 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2149 ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002150 /* signed normalized texture formats */
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002151 case GL_R8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002152 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002153 ? GL_RED : 0;
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002154 case GL_RED_SNORM:
2155 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RED : 0;
2156 case GL_R16_SNORM:
2157 return _mesa_has_EXT_texture_snorm(ctx) ||
2158 (_mesa_has_EXT_render_snorm(ctx) &&
2159 _mesa_has_EXT_texture_norm16(ctx))
2160 ? GL_RED : 0;
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002161 case GL_RG8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002162 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2163 ? GL_RG : 0;
2164 case GL_RG_SNORM:
Danylo Piliaiev2b98a022018-09-06 17:01:07 +03002165 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002166 case GL_RG16_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002167 return _mesa_has_EXT_texture_snorm(ctx) ||
2168 (_mesa_has_EXT_render_snorm(ctx) &&
2169 _mesa_has_EXT_texture_norm16(ctx))
Ian Romanickf0c99d02012-07-27 08:31:12 -07002170 ? GL_RG : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002171 case GL_RGB_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002172 case GL_RGB8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01002173 case GL_RGB16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002174 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2175 ? GL_RGB : 0;
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002176 case GL_RGBA8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002177 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2178 ? GL_RGBA : 0;
2179 case GL_RGBA_SNORM:
2180 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002181 case GL_RGBA16_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002182 return _mesa_has_EXT_texture_snorm(ctx) ||
2183 (_mesa_has_EXT_render_snorm(ctx) &&
2184 _mesa_has_EXT_texture_norm16(ctx))
Ian Romanickf0c99d02012-07-27 08:31:12 -07002185 ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002186 case GL_ALPHA_SNORM:
2187 case GL_ALPHA8_SNORM:
2188 case GL_ALPHA16_SNORM:
Paul Berrydbd61352012-11-27 12:26:51 -08002189 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002190 ctx->Extensions.EXT_texture_snorm &&
Marek Olšák0be36992011-03-18 13:44:51 +01002191 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
Brian Paul513a3242014-01-08 09:05:29 -07002192 case GL_LUMINANCE_SNORM:
2193 case GL_LUMINANCE8_SNORM:
2194 case GL_LUMINANCE16_SNORM:
2195 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2196 ? GL_LUMINANCE : 0;
2197 case GL_LUMINANCE_ALPHA_SNORM:
2198 case GL_LUMINANCE8_ALPHA8_SNORM:
2199 case GL_LUMINANCE16_ALPHA16_SNORM:
2200 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2201 ? GL_LUMINANCE_ALPHA : 0;
2202 case GL_INTENSITY_SNORM:
2203 case GL_INTENSITY8_SNORM:
2204 case GL_INTENSITY16_SNORM:
2205 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2206 ? GL_INTENSITY : 0;
2207
Marek Olšák15f99d12011-02-16 00:35:44 +01002208 case GL_R16F:
2209 case GL_R32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002210 return ((_mesa_is_desktop_gl(ctx) &&
2211 ctx->Extensions.ARB_texture_rg &&
2212 ctx->Extensions.ARB_texture_float) ||
2213 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2214 ? GL_RED : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002215 case GL_RG16F:
2216 case GL_RG32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002217 return ((_mesa_is_desktop_gl(ctx) &&
2218 ctx->Extensions.ARB_texture_rg &&
2219 ctx->Extensions.ARB_texture_float) ||
2220 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2221 ? GL_RG : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002222 case GL_RGB16F:
2223 case GL_RGB32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002224 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002225 ? GL_RGB : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002226 case GL_RGBA16F:
2227 case GL_RGBA32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002228 return ((_mesa_is_desktop_gl(ctx) &&
2229 ctx->Extensions.ARB_texture_float) ||
2230 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Ian Romanickf0c99d02012-07-27 08:31:12 -07002231 ? GL_RGBA : 0;
Juan A. Suarez Romeroe1623b32018-01-15 10:58:50 +00002232 case GL_RGB9_E5:
2233 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_shared_exponent)
2234 ? GL_RGB: 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002235 case GL_ALPHA16F_ARB:
2236 case GL_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002237 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002238 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002239 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2240 case GL_LUMINANCE16F_ARB:
2241 case GL_LUMINANCE32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002242 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002243 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002244 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2245 case GL_LUMINANCE_ALPHA16F_ARB:
2246 case GL_LUMINANCE_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002247 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002248 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002249 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2250 case GL_INTENSITY16F_ARB:
2251 case GL_INTENSITY32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002252 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002253 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002254 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
Marek Olšák631d23d2011-04-26 02:27:25 +02002255 case GL_R11F_G11F_B10F:
Jordan Justen119002a2013-01-10 17:29:27 -08002256 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
2257 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Matt Turnercbef5372012-11-20 13:45:03 -08002258 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002259
2260 case GL_RGBA8UI_EXT:
2261 case GL_RGBA16UI_EXT:
2262 case GL_RGBA32UI_EXT:
2263 case GL_RGBA8I_EXT:
2264 case GL_RGBA16I_EXT:
2265 case GL_RGBA32I_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002266 return ctx->Version >= 30
2267 || (_mesa_is_desktop_gl(ctx) &&
2268 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002269
2270 case GL_RGB8UI_EXT:
2271 case GL_RGB16UI_EXT:
2272 case GL_RGB32UI_EXT:
2273 case GL_RGB8I_EXT:
2274 case GL_RGB16I_EXT:
2275 case GL_RGB32I_EXT:
Ian Romanicka86d6292012-12-03 11:55:12 -08002276 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
2277 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002278 case GL_R8UI:
2279 case GL_R8I:
2280 case GL_R16UI:
2281 case GL_R16I:
2282 case GL_R32UI:
2283 case GL_R32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002284 return ctx->Version >= 30
2285 || (_mesa_is_desktop_gl(ctx) &&
2286 ctx->Extensions.ARB_texture_rg &&
2287 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002288
2289 case GL_RG8UI:
2290 case GL_RG8I:
2291 case GL_RG16UI:
2292 case GL_RG16I:
2293 case GL_RG32UI:
2294 case GL_RG32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002295 return ctx->Version >= 30
2296 || (_mesa_is_desktop_gl(ctx) &&
2297 ctx->Extensions.ARB_texture_rg &&
2298 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
Brian Paul45bd5c42011-12-16 08:44:43 -07002299
Dave Airlie9c697a92011-10-04 20:59:40 +01002300 case GL_INTENSITY8I_EXT:
2301 case GL_INTENSITY8UI_EXT:
2302 case GL_INTENSITY16I_EXT:
2303 case GL_INTENSITY16UI_EXT:
2304 case GL_INTENSITY32I_EXT:
2305 case GL_INTENSITY32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002306 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002307 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002308 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2309
2310 case GL_LUMINANCE8I_EXT:
2311 case GL_LUMINANCE8UI_EXT:
2312 case GL_LUMINANCE16I_EXT:
2313 case GL_LUMINANCE16UI_EXT:
2314 case GL_LUMINANCE32I_EXT:
2315 case GL_LUMINANCE32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002316 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002317 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002318 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2319
2320 case GL_LUMINANCE_ALPHA8I_EXT:
2321 case GL_LUMINANCE_ALPHA8UI_EXT:
2322 case GL_LUMINANCE_ALPHA16I_EXT:
2323 case GL_LUMINANCE_ALPHA16UI_EXT:
2324 case GL_LUMINANCE_ALPHA32I_EXT:
2325 case GL_LUMINANCE_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002326 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002327 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002328 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
Dave Airlief449be62011-11-27 16:21:02 +00002329
Marek Olšák636802f2012-01-22 20:21:36 +01002330 case GL_ALPHA8I_EXT:
2331 case GL_ALPHA8UI_EXT:
2332 case GL_ALPHA16I_EXT:
2333 case GL_ALPHA16UI_EXT:
2334 case GL_ALPHA32I_EXT:
2335 case GL_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002336 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002337 ctx->Extensions.EXT_texture_integer &&
Marek Olšák636802f2012-01-22 20:21:36 +01002338 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2339
Dave Airlief449be62011-11-27 16:21:02 +00002340 case GL_RGB10_A2UI:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002341 return (_mesa_is_desktop_gl(ctx) &&
2342 ctx->Extensions.ARB_texture_rgb10_a2ui)
2343 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Marek Olšák1a06e842012-07-12 14:07:41 +02002344
2345 case GL_RGB565:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002346 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
2347 ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002348 default:
Eric Anholt65c41d52011-01-13 10:05:50 -08002349 return 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002350 }
Brian Paul463642c2005-02-08 02:06:00 +00002351}
2352
2353
Marek Olšákdf818d52011-03-06 05:26:12 +01002354/**
2355 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
2356 */
2357static void
2358invalidate_rb(GLuint key, void *data, void *userData)
2359{
2360 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2361 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
2362
2363 /* If this is a user-created FBO */
Brian Paul36ede892012-01-12 09:17:23 -07002364 if (_mesa_is_user_fbo(fb)) {
Marek Olšákdf818d52011-03-06 05:26:12 +01002365 GLuint i;
2366 for (i = 0; i < BUFFER_COUNT; i++) {
2367 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2368 if (att->Type == GL_RENDERBUFFER &&
2369 att->Renderbuffer == rb) {
2370 /* Mark fb status as indeterminate to force re-validation */
2371 fb->_Status = 0;
Marek Olšáka674ef72011-03-07 23:33:36 +01002372 return;
Marek Olšákdf818d52011-03-06 05:26:12 +01002373 }
2374 }
2375 }
2376}
2377
2378
Brian Paul4f3514e2009-01-22 15:19:56 -07002379/** sentinal value, see below */
2380#define NO_SAMPLES 1000
2381
Ian Romanickeb5bc622015-11-12 09:11:20 -08002382void
2383_mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2384 GLenum internalFormat, GLsizei width,
Marek Olšák2d115052018-06-11 15:26:41 -04002385 GLsizei height, GLsizei samples,
2386 GLsizei storageSamples)
Ian Romanickeb5bc622015-11-12 09:11:20 -08002387{
2388 const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2389
2390 assert(baseFormat != 0);
2391 assert(width >= 0 && width <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2392 assert(height >= 0 && height <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2393 assert(samples != NO_SAMPLES);
2394 if (samples != 0) {
2395 assert(samples > 0);
2396 assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
Marek Olšák2d115052018-06-11 15:26:41 -04002397 internalFormat, samples,
2398 storageSamples) == GL_NO_ERROR);
Ian Romanickeb5bc622015-11-12 09:11:20 -08002399 }
2400
2401 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2402
2403 if (rb->InternalFormat == internalFormat &&
2404 rb->Width == (GLuint) width &&
2405 rb->Height == (GLuint) height &&
Marek Olšák328c1c82018-06-11 17:24:16 -04002406 rb->NumSamples == samples &&
2407 rb->NumStorageSamples == storageSamples) {
Ian Romanickeb5bc622015-11-12 09:11:20 -08002408 /* no change in allocation needed */
2409 return;
2410 }
2411
2412 /* These MUST get set by the AllocStorage func */
2413 rb->Format = MESA_FORMAT_NONE;
2414 rb->NumSamples = samples;
Marek Olšák328c1c82018-06-11 17:24:16 -04002415 rb->NumStorageSamples = storageSamples;
Ian Romanickeb5bc622015-11-12 09:11:20 -08002416
2417 /* Now allocate the storage */
2418 assert(rb->AllocStorage);
2419 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
2420 /* No error - check/set fields now */
2421 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
2422 assert(rb->Width == (GLuint) width);
2423 assert(rb->Height == (GLuint) height);
2424 rb->InternalFormat = internalFormat;
2425 rb->_BaseFormat = baseFormat;
2426 assert(rb->_BaseFormat != 0);
2427 }
2428 else {
2429 /* Probably ran out of memory - clear the fields */
2430 rb->Width = 0;
2431 rb->Height = 0;
2432 rb->Format = MESA_FORMAT_NONE;
2433 rb->InternalFormat = GL_NONE;
2434 rb->_BaseFormat = GL_NONE;
2435 rb->NumSamples = 0;
Marek Olšák328c1c82018-06-11 17:24:16 -04002436 rb->NumStorageSamples = 0;
Ian Romanickeb5bc622015-11-12 09:11:20 -08002437 }
2438
2439 /* Invalidate the framebuffers the renderbuffer is attached in. */
2440 if (rb->AttachedAnytime) {
2441 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
2442 }
2443}
Brian Paul4f3514e2009-01-22 15:19:56 -07002444
2445/**
Martin Peresbf11c192015-02-13 15:35:48 +02002446 * Helper function used by renderbuffer_storage_direct() and
2447 * renderbuffer_storage_target().
2448 * samples will be NO_SAMPLES if called by a non-multisample function.
Brian Paul4f3514e2009-01-22 15:19:56 -07002449 */
2450static void
Martin Peresbf11c192015-02-13 15:35:48 +02002451renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2452 GLenum internalFormat, GLsizei width,
Marek Olšák2d115052018-06-11 15:26:41 -04002453 GLsizei height, GLsizei samples, GLsizei storageSamples,
2454 const char *func)
Brian Paulddc82ee2005-02-05 19:56:45 +00002455{
Brian Paul463642c2005-02-08 02:06:00 +00002456 GLenum baseFormat;
Chris Forbes90b5a242013-02-06 20:42:53 +13002457 GLenum sample_count_error;
Brian Paulddc82ee2005-02-05 19:56:45 +00002458
Brian Paul59e0faa2006-03-15 17:48:00 +00002459 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
Brian Paul463642c2005-02-08 02:06:00 +00002460 if (baseFormat == 0) {
Jordan Justen119002a2013-01-10 17:29:27 -08002461 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002462 func, _mesa_enum_to_string(internalFormat));
Brian Paulddc82ee2005-02-05 19:56:45 +00002463 return;
2464 }
2465
Yuanhan Liu49f84472011-10-25 15:36:59 +08002466 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Martin Peresbf11c192015-02-13 15:35:48 +02002467 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
2468 width);
Brian Paulddc82ee2005-02-05 19:56:45 +00002469 return;
2470 }
2471
Yuanhan Liu49f84472011-10-25 15:36:59 +08002472 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Martin Peresbf11c192015-02-13 15:35:48 +02002473 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
2474 height);
Brian Paul4f3514e2009-01-22 15:19:56 -07002475 return;
2476 }
2477
2478 if (samples == NO_SAMPLES) {
2479 /* NumSamples == 0 indicates non-multisampling */
2480 samples = 0;
Marek Olšák2d115052018-06-11 15:26:41 -04002481 storageSamples = 0;
Brian Paul4f3514e2009-01-22 15:19:56 -07002482 }
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002483 else {
2484 /* check the sample count;
2485 * note: driver may choose to use more samples than what's requested
2486 */
Martin Peresbf11c192015-02-13 15:35:48 +02002487 sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
Marek Olšák2d115052018-06-11 15:26:41 -04002488 internalFormat, samples, storageSamples);
Timothy Arceri46684d32015-08-13 18:44:51 +10002489
2490 /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
2491 *
2492 * "If a negative number is provided where an argument of type sizei or
2493 * sizeiptr is specified, the error INVALID VALUE is generated."
2494 */
Marek Olšák2d115052018-06-11 15:26:41 -04002495 if (samples < 0 || storageSamples < 0) {
Timothy Arceri46684d32015-08-13 18:44:51 +10002496 sample_count_error = GL_INVALID_VALUE;
2497 }
2498
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002499 if (sample_count_error != GL_NO_ERROR) {
Marek Olšák2d115052018-06-11 15:26:41 -04002500 _mesa_error(ctx, sample_count_error,
2501 "%s(samples=%d, storageSamples=%d)", func, samples,
2502 storageSamples);
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002503 return;
2504 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002505 }
2506
Marek Olšák2d115052018-06-11 15:26:41 -04002507 _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2508 storageSamples);
Brian Paulddc82ee2005-02-05 19:56:45 +00002509}
2510
Martin Peresbf11c192015-02-13 15:35:48 +02002511/**
2512 * Helper function used by _mesa_NamedRenderbufferStorage*().
2513 * samples will be NO_SAMPLES if called by a non-multisample function.
2514 */
2515static void
2516renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
2517 GLsizei width, GLsizei height, GLsizei samples,
Marek Olšák2d115052018-06-11 15:26:41 -04002518 GLsizei storageSamples, const char *func)
Martin Peresbf11c192015-02-13 15:35:48 +02002519{
2520 GET_CURRENT_CONTEXT(ctx);
2521
2522 if (MESA_VERBOSE & VERBOSE_API) {
2523 if (samples == NO_SAMPLES)
2524 _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
2525 func, renderbuffer,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002526 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002527 width, height);
2528 else
2529 _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
2530 func, renderbuffer,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002531 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002532 width, height, samples);
2533 }
2534
2535 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2536 if (!rb || rb == &DummyRenderbuffer) {
2537 /* ID was reserved, but no real renderbuffer object made yet */
2538 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
2539 func, renderbuffer);
2540 return;
2541 }
2542
Marek Olšák2d115052018-06-11 15:26:41 -04002543 renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2544 storageSamples, func);
Martin Peresbf11c192015-02-13 15:35:48 +02002545}
2546
2547/**
2548 * Helper function used by _mesa_RenderbufferStorage() and
2549 * _mesa_RenderbufferStorageMultisample().
2550 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
2551 */
2552static void
2553renderbuffer_storage_target(GLenum target, GLenum internalFormat,
2554 GLsizei width, GLsizei height, GLsizei samples,
Marek Olšák2d115052018-06-11 15:26:41 -04002555 GLsizei storageSamples, const char *func)
Martin Peresbf11c192015-02-13 15:35:48 +02002556{
2557 GET_CURRENT_CONTEXT(ctx);
2558
2559 if (MESA_VERBOSE & VERBOSE_API) {
2560 if (samples == NO_SAMPLES)
2561 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
2562 func,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002563 _mesa_enum_to_string(target),
2564 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002565 width, height);
2566 else
2567 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
2568 func,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002569 _mesa_enum_to_string(target),
2570 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002571 width, height, samples);
2572 }
2573
2574 if (target != GL_RENDERBUFFER_EXT) {
2575 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
2576 return;
2577 }
2578
2579 if (!ctx->CurrentRenderbuffer) {
2580 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
2581 func);
2582 return;
2583 }
2584
2585 renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
Marek Olšák2d115052018-06-11 15:26:41 -04002586 height, samples, storageSamples, func);
Martin Peresbf11c192015-02-13 15:35:48 +02002587}
2588
Brian Paul23c5b212010-05-28 13:33:03 -06002589
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002590void GLAPIENTRY
Brian Paul23c5b212010-05-28 13:33:03 -06002591_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002592{
Brian Paul51b79922010-02-24 11:57:26 -07002593 struct gl_renderbuffer *rb;
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002594 GET_CURRENT_CONTEXT(ctx);
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002595
Chia-I Wu2002e4d02010-04-06 17:46:17 +08002596 if (!ctx->Extensions.OES_EGL_image) {
2597 _mesa_error(ctx, GL_INVALID_OPERATION,
2598 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
2599 return;
2600 }
2601
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002602 if (target != GL_RENDERBUFFER) {
Brian Paul23c5b212010-05-28 13:33:03 -06002603 _mesa_error(ctx, GL_INVALID_ENUM,
2604 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002605 return;
2606 }
2607
2608 rb = ctx->CurrentRenderbuffer;
2609 if (!rb) {
Brian Paul23c5b212010-05-28 13:33:03 -06002610 _mesa_error(ctx, GL_INVALID_OPERATION,
2611 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002612 return;
2613 }
2614
2615 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2616
2617 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
2618}
Brian Paulddc82ee2005-02-05 19:56:45 +00002619
Brian Paul23c5b212010-05-28 13:33:03 -06002620
Brian Paul45e76d22009-10-08 20:27:27 -06002621/**
Paul Berry1a1db172012-11-06 08:57:59 -08002622 * Helper function for _mesa_GetRenderbufferParameteriv() and
2623 * _mesa_GetFramebufferAttachmentParameteriv()
Brian Paul45e76d22009-10-08 20:27:27 -06002624 * We have to be careful to respect the base format. For example, if a
2625 * renderbuffer/texture was created with internalFormat=GL_RGB but the
2626 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
2627 * we need to return zero.
2628 */
2629static GLint
Mark Mueller71fe9432014-01-04 14:11:43 -08002630get_component_bits(GLenum pname, GLenum baseFormat, mesa_format format)
Brian Paul45e76d22009-10-08 20:27:27 -06002631{
Brian Paulf0b6e9a2011-11-23 15:33:45 -07002632 if (_mesa_base_format_has_channel(baseFormat, pname))
2633 return _mesa_get_format_bits(format, pname);
2634 else
Brian Paul45e76d22009-10-08 20:27:27 -06002635 return 0;
Brian Paul45e76d22009-10-08 20:27:27 -06002636}
2637
2638
2639
Brian Paul1864c7d2005-02-08 03:46:37 +00002640void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002641_mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
Brian Paul4f3514e2009-01-22 15:19:56 -07002642 GLsizei width, GLsizei height)
2643{
Brian Paul722d9762009-01-20 16:58:49 -07002644 /* GL_ARB_fbo says calling this function is equivalent to calling
2645 * glRenderbufferStorageMultisample() with samples=0. We pass in
2646 * a token value here just for error reporting purposes.
2647 */
Martin Peresbf11c192015-02-13 15:35:48 +02002648 renderbuffer_storage_target(target, internalFormat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002649 NO_SAMPLES, 0, "glRenderbufferStorage");
Brian Paul4f3514e2009-01-22 15:19:56 -07002650}
2651
2652
2653void GLAPIENTRY
Brian Paul777a2ef2009-01-22 15:17:42 -07002654_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
Brian Paul4f3514e2009-01-22 15:19:56 -07002655 GLenum internalFormat,
Brian Paul777a2ef2009-01-22 15:17:42 -07002656 GLsizei width, GLsizei height)
2657{
Martin Peresbf11c192015-02-13 15:35:48 +02002658 renderbuffer_storage_target(target, internalFormat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002659 samples, samples,
2660 "glRenderbufferStorageMultisample");
Brian Paul777a2ef2009-01-22 15:17:42 -07002661}
2662
Brian Paul23c5b212010-05-28 13:33:03 -06002663
Marek Olšák3d6900d2018-06-28 02:05:12 -04002664void GLAPIENTRY
2665_mesa_RenderbufferStorageMultisampleAdvancedAMD(
2666 GLenum target, GLsizei samples, GLsizei storageSamples,
2667 GLenum internalFormat, GLsizei width, GLsizei height)
2668{
2669 renderbuffer_storage_target(target, internalFormat, width, height,
2670 samples, storageSamples,
2671 "glRenderbufferStorageMultisampleAdvancedAMD");
2672}
2673
2674
Brian Paul23c5b212010-05-28 13:33:03 -06002675/**
2676 * OpenGL ES version of glRenderBufferStorage.
2677 */
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002678void GLAPIENTRY
2679_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
Martin Peres7bd8b482015-02-12 17:54:43 +02002680 GLsizei width, GLsizei height)
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002681{
2682 switch (internalFormat) {
2683 case GL_RGB565:
2684 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
2685 /* choose a closest format */
2686 internalFormat = GL_RGB5;
2687 break;
2688 default:
2689 break;
2690 }
Brian Paul777a2ef2009-01-22 15:17:42 -07002691
Marek Olšák2d115052018-06-11 15:26:41 -04002692 renderbuffer_storage_target(target, internalFormat, width, height, 0, 0,
Martin Peresbf11c192015-02-13 15:35:48 +02002693 "glRenderbufferStorageEXT");
2694}
2695
2696void GLAPIENTRY
2697_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
2698 GLsizei width, GLsizei height)
2699{
2700 /* GL_ARB_fbo says calling this function is equivalent to calling
2701 * glRenderbufferStorageMultisample() with samples=0. We pass in
2702 * a token value here just for error reporting purposes.
2703 */
2704 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002705 NO_SAMPLES, 0, "glNamedRenderbufferStorage");
Martin Peresbf11c192015-02-13 15:35:48 +02002706}
2707
2708void GLAPIENTRY
2709_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
2710 GLenum internalformat,
2711 GLsizei width, GLsizei height)
2712{
2713 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002714 samples, samples,
Martin Peresbf11c192015-02-13 15:35:48 +02002715 "glNamedRenderbufferStorageMultisample");
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002716}
Brian Paul777a2ef2009-01-22 15:17:42 -07002717
Brian Paul23c5b212010-05-28 13:33:03 -06002718
Marek Olšák3d6900d2018-06-28 02:05:12 -04002719void GLAPIENTRY
2720_mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
2721 GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
2722 GLenum internalformat, GLsizei width, GLsizei height)
2723{
2724 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2725 samples, storageSamples,
2726 "glNamedRenderbufferStorageMultisampleAdvancedAMD");
2727}
2728
2729
Martin Peres245e5c42015-02-13 15:46:55 +02002730static void
2731get_render_buffer_parameteriv(struct gl_context *ctx,
2732 struct gl_renderbuffer *rb, GLenum pname,
2733 GLint *params, const char *func)
Brian Paulddc82ee2005-02-05 19:56:45 +00002734{
Brian Paul800e5532009-11-02 15:39:39 -07002735 /* No need to flush here since we're just quering state which is
2736 * not effected by rendering.
2737 */
Brian Paul474f28e2005-10-08 14:41:17 +00002738
Brian Paul463642c2005-02-08 02:06:00 +00002739 switch (pname) {
2740 case GL_RENDERBUFFER_WIDTH_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002741 *params = rb->Width;
Brian Paul463642c2005-02-08 02:06:00 +00002742 return;
2743 case GL_RENDERBUFFER_HEIGHT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002744 *params = rb->Height;
Brian Paul463642c2005-02-08 02:06:00 +00002745 return;
2746 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002747 *params = rb->InternalFormat;
Brian Paul463642c2005-02-08 02:06:00 +00002748 return;
Brian Paul1b939532005-05-31 23:55:21 +00002749 case GL_RENDERBUFFER_RED_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002750 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002751 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002752 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002753 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002754 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
Brian Paul45e76d22009-10-08 20:27:27 -06002755 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
Marek Olšák328c1c82018-06-11 17:24:16 -04002756 return;
Brian Paul722d9762009-01-20 16:58:49 -07002757 case GL_RENDERBUFFER_SAMPLES:
Ian Romanickae86ebf2012-07-27 07:49:49 -07002758 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
2759 || _mesa_is_gles3(ctx)) {
Brian Paul722d9762009-01-20 16:58:49 -07002760 *params = rb->NumSamples;
Marek Olšák328c1c82018-06-11 17:24:16 -04002761 return;
Brian Paul722d9762009-01-20 16:58:49 -07002762 }
Marek Olšák328c1c82018-06-11 17:24:16 -04002763 break;
2764 case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
2765 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
2766 *params = rb->NumStorageSamples;
2767 return;
2768 }
2769 break;
Martin Peres245e5c42015-02-13 15:46:55 +02002770 }
Marek Olšák328c1c82018-06-11 17:24:16 -04002771
2772 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
2773 _mesa_enum_to_string(pname));
Martin Peres245e5c42015-02-13 15:46:55 +02002774}
2775
2776
2777void GLAPIENTRY
2778_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
2779{
2780 GET_CURRENT_CONTEXT(ctx);
2781
2782 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul463642c2005-02-08 02:06:00 +00002783 _mesa_error(ctx, GL_INVALID_ENUM,
2784 "glGetRenderbufferParameterivEXT(target)");
2785 return;
2786 }
Martin Peres245e5c42015-02-13 15:46:55 +02002787
2788 if (!ctx->CurrentRenderbuffer) {
2789 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
2790 "(no renderbuffer bound)");
2791 return;
2792 }
2793
2794 get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
2795 params, "glGetRenderbufferParameteriv");
2796}
2797
2798
2799void GLAPIENTRY
2800_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
2801 GLint *params)
2802{
2803 GET_CURRENT_CONTEXT(ctx);
2804
2805 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2806 if (!rb || rb == &DummyRenderbuffer) {
2807 /* ID was reserved, but no real renderbuffer object made yet */
2808 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
2809 "(invalid renderbuffer %i)", renderbuffer);
2810 return;
2811 }
2812
2813 get_render_buffer_parameteriv(ctx, rb, pname, params,
2814 "glGetNamedRenderbufferParameteriv");
Brian Paulddc82ee2005-02-05 19:56:45 +00002815}
2816
2817
Brian Paul1864c7d2005-02-08 03:46:37 +00002818GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002819_mesa_IsFramebuffer(GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00002820{
Brian Paulddc82ee2005-02-05 19:56:45 +00002821 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +00002822 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Brian Paulbc6cced2005-10-04 15:01:27 +00002823 if (framebuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00002824 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
Brian Paulbc6cced2005-10-04 15:01:27 +00002825 if (rb != NULL && rb != &DummyFramebuffer)
2826 return GL_TRUE;
2827 }
2828 return GL_FALSE;
Brian Paulddc82ee2005-02-05 19:56:45 +00002829}
2830
2831
briana492ab72009-11-10 15:33:31 -07002832/**
2833 * Check if any of the attachments of the given framebuffer are textures
2834 * (render to texture). Call ctx->Driver.RenderTexture() for such
2835 * attachments.
2836 */
Brian Paulea4fe662006-03-26 05:22:17 +00002837static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002838check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paulea4fe662006-03-26 05:22:17 +00002839{
2840 GLuint i;
Matt Turnerbfcdb842015-02-20 20:18:47 -08002841 assert(ctx->Driver.RenderTexture);
briana65b84d2009-11-10 18:02:03 -07002842
Brian Paul36ede892012-01-12 09:17:23 -07002843 if (_mesa_is_winsys_fbo(fb))
briana65b84d2009-11-10 18:02:03 -07002844 return; /* can't render to texture with winsys framebuffers */
2845
Brian Paulea4fe662006-03-26 05:22:17 +00002846 for (i = 0; i < BUFFER_COUNT; i++) {
2847 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Ian Romanickfb497132013-07-27 12:04:20 -07002848 if (att->Texture && att->Renderbuffer->TexImage
2849 && driver_RenderTexture_is_safe(att)) {
Brian Paulea4fe662006-03-26 05:22:17 +00002850 ctx->Driver.RenderTexture(ctx, fb, att);
2851 }
2852 }
2853}
2854
2855
Brian Paul0e31e022005-12-01 00:25:00 +00002856/**
2857 * Examine all the framebuffer's attachments to see if any are textures.
2858 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
2859 * notify the device driver that the texture image may have changed.
2860 */
2861static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002862check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paul0e31e022005-12-01 00:25:00 +00002863{
Eric Anholt7ccb26f2014-03-03 09:16:48 -08002864 /* Skip if we know NeedsFinishRenderTexture won't be set. */
2865 if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
2866 return;
briana65b84d2009-11-10 18:02:03 -07002867
Brian Paul0e31e022005-12-01 00:25:00 +00002868 if (ctx->Driver.FinishRenderTexture) {
2869 GLuint i;
2870 for (i = 0; i < BUFFER_COUNT; i++) {
2871 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Eric Anholtc810e672013-05-10 12:36:43 -07002872 struct gl_renderbuffer *rb = att->Renderbuffer;
2873 if (rb && rb->NeedsFinishRenderTexture) {
Eric Anholta5b04522013-05-10 12:17:52 -07002874 ctx->Driver.FinishRenderTexture(ctx, rb);
Brian Paul0e31e022005-12-01 00:25:00 +00002875 }
2876 }
2877 }
2878}
2879
2880
Ian Romanick4a9522a2013-07-18 17:39:22 -07002881static void
Timothy Arcerib54a2312018-09-08 14:20:17 +10002882bind_framebuffer(GLenum target, GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00002883{
briane6f60d32009-11-10 15:47:34 -07002884 struct gl_framebuffer *newDrawFb, *newReadFb;
Brian Paul0bffb112005-11-08 14:45:48 +00002885 GLboolean bindReadBuf, bindDrawBuf;
Brian Paulddc82ee2005-02-05 19:56:45 +00002886 GET_CURRENT_CONTEXT(ctx);
2887
Brian Paul0bffb112005-11-08 14:45:48 +00002888 switch (target) {
Brian Paul0bffb112005-11-08 14:45:48 +00002889 case GL_DRAW_FRAMEBUFFER_EXT:
Brian Paul0bffb112005-11-08 14:45:48 +00002890 bindDrawBuf = GL_TRUE;
2891 bindReadBuf = GL_FALSE;
2892 break;
2893 case GL_READ_FRAMEBUFFER_EXT:
Brian Paul0bffb112005-11-08 14:45:48 +00002894 bindDrawBuf = GL_FALSE;
2895 bindReadBuf = GL_TRUE;
2896 break;
Brian Paul0bffb112005-11-08 14:45:48 +00002897 case GL_FRAMEBUFFER_EXT:
2898 bindDrawBuf = GL_TRUE;
2899 bindReadBuf = GL_TRUE;
2900 break;
2901 default:
Brian Pauleba4ff62005-09-06 21:22:16 +00002902 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00002903 return;
2904 }
2905
Brian Paul3deaa012005-02-07 05:08:24 +00002906 if (framebuffer) {
Brian Paule4b23562005-05-04 20:11:35 +00002907 /* Binding a user-created framebuffer object */
briane6f60d32009-11-10 15:47:34 -07002908 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
2909 if (newDrawFb == &DummyFramebuffer) {
Brian Paul923b6fc2005-02-08 04:08:56 +00002910 /* ID was reserved, but no real framebuffer object made yet */
briane6f60d32009-11-10 15:47:34 -07002911 newDrawFb = NULL;
Brian Paul1864c7d2005-02-08 03:46:37 +00002912 }
Timothy Arcerib54a2312018-09-08 14:20:17 +10002913 else if (!newDrawFb && ctx->API == API_OPENGL_CORE) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07002914 /* All FBO IDs must be Gen'd */
Timothy Arcerib54a2312018-09-08 14:20:17 +10002915 _mesa_error(ctx, GL_INVALID_OPERATION,
2916 "glBindFramebuffer(non-gen name)");
Brian Paul1bc59bf2009-01-22 15:07:34 -07002917 return;
2918 }
2919
briane6f60d32009-11-10 15:47:34 -07002920 if (!newDrawFb) {
Martin Peres7bd8b482015-02-12 17:54:43 +02002921 /* create new framebuffer object */
2922 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
2923 if (!newDrawFb) {
2924 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
2925 return;
2926 }
briane6f60d32009-11-10 15:47:34 -07002927 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
Brian Paul3deaa012005-02-07 05:08:24 +00002928 }
briane6f60d32009-11-10 15:47:34 -07002929 newReadFb = newDrawFb;
Brian Paul3deaa012005-02-07 05:08:24 +00002930 }
Brian Paul463642c2005-02-08 02:06:00 +00002931 else {
Brian Paule4b23562005-05-04 20:11:35 +00002932 /* Binding the window system framebuffer (which was originally set
2933 * with MakeCurrent).
2934 */
briane6f60d32009-11-10 15:47:34 -07002935 newDrawFb = ctx->WinSysDrawBuffer;
2936 newReadFb = ctx->WinSysReadBuffer;
Brian Paul3deaa012005-02-07 05:08:24 +00002937 }
2938
Ian Romanickfed9b0e2015-11-13 10:46:40 -08002939 _mesa_bind_framebuffers(ctx,
2940 bindDrawBuf ? newDrawFb : ctx->DrawBuffer,
2941 bindReadBuf ? newReadFb : ctx->ReadBuffer);
2942}
2943
2944void
2945_mesa_bind_framebuffers(struct gl_context *ctx,
2946 struct gl_framebuffer *newDrawFb,
2947 struct gl_framebuffer *newReadFb)
2948{
2949 struct gl_framebuffer *const oldDrawFb = ctx->DrawBuffer;
2950 struct gl_framebuffer *const oldReadFb = ctx->ReadBuffer;
2951 const bool bindDrawBuf = oldDrawFb != newDrawFb;
2952 const bool bindReadBuf = oldReadFb != newReadFb;
2953
Matt Turnerbfcdb842015-02-20 20:18:47 -08002954 assert(newDrawFb);
2955 assert(newDrawFb != &DummyFramebuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00002956
Brian Paulea4fe662006-03-26 05:22:17 +00002957 /*
Brian Paul16144632009-02-26 14:49:24 -07002958 * OK, now bind the new Draw/Read framebuffers, if they're changing.
briana65b84d2009-11-10 18:02:03 -07002959 *
2960 * We also check if we're beginning and/or ending render-to-texture.
2961 * When a framebuffer with texture attachments is unbound, call
2962 * ctx->Driver.FinishRenderTexture().
2963 * When a framebuffer with texture attachments is bound, call
2964 * ctx->Driver.RenderTexture().
2965 *
2966 * Note that if the ReadBuffer has texture attachments we don't consider
2967 * that a render-to-texture case.
Brian Paulea4fe662006-03-26 05:22:17 +00002968 */
Brian Paul0bffb112005-11-08 14:45:48 +00002969 if (bindReadBuf) {
briana65b84d2009-11-10 18:02:03 -07002970 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
brianbc569cd2009-11-10 16:00:35 -07002971
briana65b84d2009-11-10 18:02:03 -07002972 /* check if old readbuffer was render-to-texture */
2973 check_end_texture_render(ctx, oldReadFb);
2974
2975 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
Brian Paul0bffb112005-11-08 14:45:48 +00002976 }
2977
2978 if (bindDrawBuf) {
briana65b84d2009-11-10 18:02:03 -07002979 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Rhys Perry67f40da2018-06-14 19:56:28 -06002980 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
Brian32d86eb2007-08-16 18:52:48 +01002981
Eric Anholta1fd13f2012-02-10 12:05:16 -08002982 /* check if old framebuffer had any texture attachments */
2983 if (oldDrawFb)
briana65b84d2009-11-10 18:02:03 -07002984 check_end_texture_render(ctx, oldDrawFb);
brianbc569cd2009-11-10 16:00:35 -07002985
briana65b84d2009-11-10 18:02:03 -07002986 /* check if newly bound framebuffer has any texture attachments */
2987 check_begin_texture_render(ctx, newDrawFb);
2988
2989 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
Brian Paul0bffb112005-11-08 14:45:48 +00002990 }
Brian Paul59e0faa2006-03-15 17:48:00 +00002991
Brian Paul16144632009-02-26 14:49:24 -07002992 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
Ian Romanickfed9b0e2015-11-13 10:46:40 -08002993 /* The few classic drivers that actually hook this function really only
2994 * want to know if the draw framebuffer changed.
2995 */
2996 ctx->Driver.BindFramebuffer(ctx,
2997 bindDrawBuf ? GL_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
2998 newDrawFb, newReadFb);
Brian Paul59e0faa2006-03-15 17:48:00 +00002999 }
Brian Paulddc82ee2005-02-05 19:56:45 +00003000}
3001
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003002void GLAPIENTRY
Ian Romanick4a9522a2013-07-18 17:39:22 -07003003_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003004{
Ian Romanick4a9522a2013-07-18 17:39:22 -07003005 /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
3006 * point, but they allow the use of user-generated names.
3007 */
Timothy Arcerib54a2312018-09-08 14:20:17 +10003008 bind_framebuffer(target, framebuffer);
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003009}
3010
Brian Paulc1377ed2014-03-22 10:31:58 -06003011
Ian Romanick4a9522a2013-07-18 17:39:22 -07003012void GLAPIENTRY
3013_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
3014{
Timothy Arcerib54a2312018-09-08 14:20:17 +10003015 bind_framebuffer(target, framebuffer);
Ian Romanick4a9522a2013-07-18 17:39:22 -07003016}
Brian Paulddc82ee2005-02-05 19:56:45 +00003017
Brian Paulc1377ed2014-03-22 10:31:58 -06003018
Brian Paul1864c7d2005-02-08 03:46:37 +00003019void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003020_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00003021{
3022 GLint i;
3023 GET_CURRENT_CONTEXT(ctx);
3024
Eduardo Lima Mitevf77a4732014-12-11 23:34:17 +01003025 if (n < 0) {
3026 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
3027 return;
3028 }
3029
Brian Paul800e5532009-11-02 15:39:39 -07003030 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00003031
3032 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00003033 if (framebuffers[i] > 0) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003034 struct gl_framebuffer *fb;
3035 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
3036 if (fb) {
Matt Turnerbfcdb842015-02-20 20:18:47 -08003037 assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
Brian Paul91802fd2005-10-04 16:01:02 +00003038
3039 /* check if deleting currently bound framebuffer object */
Ian Romanick764be9f2013-11-13 14:00:06 -08003040 if (fb == ctx->DrawBuffer) {
3041 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08003042 assert(fb->RefCount >= 2);
Ian Romanick764be9f2013-11-13 14:00:06 -08003043 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3044 }
3045 if (fb == ctx->ReadBuffer) {
3046 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08003047 assert(fb->RefCount >= 2);
Ian Romanick764be9f2013-11-13 14:00:06 -08003048 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
3049 }
Brian Paul91802fd2005-10-04 16:01:02 +00003050
Martin Peres7bd8b482015-02-12 17:54:43 +02003051 /* remove from hash table immediately, to free the ID */
3052 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00003053
Brian Paul1864c7d2005-02-08 03:46:37 +00003054 if (fb != &DummyFramebuffer) {
3055 /* But the object will not be freed until it's no longer
3056 * bound in any context.
3057 */
Brian Pauld5229442009-02-09 08:30:55 -07003058 _mesa_reference_framebuffer(&fb, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02003059 }
3060 }
Brian Paulddc82ee2005-02-05 19:56:45 +00003061 }
3062 }
3063}
3064
3065
Laura Ekstrandf868de72015-01-23 14:54:48 -08003066/**
3067 * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
3068 * It is not exposed to the rest of Mesa to encourage the use of
3069 * nameless buffers in driver internals.
3070 */
3071static void
3072create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
Brian Paulddc82ee2005-02-05 19:56:45 +00003073{
3074 GET_CURRENT_CONTEXT(ctx);
3075 GLuint first;
3076 GLint i;
Laura Ekstrandf868de72015-01-23 14:54:48 -08003077 struct gl_framebuffer *fb;
3078
3079 const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
Brian Paulddc82ee2005-02-05 19:56:45 +00003080
Brian Paulddc82ee2005-02-05 19:56:45 +00003081 if (n < 0) {
Laura Ekstrandf868de72015-01-23 14:54:48 -08003082 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00003083 return;
3084 }
3085
3086 if (!framebuffers)
3087 return;
3088
Matt Turner015f2202015-07-30 14:31:04 -07003089 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
3090
Brian Paulddc82ee2005-02-05 19:56:45 +00003091 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
3092
3093 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00003094 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00003095 framebuffers[i] = name;
Laura Ekstrandf868de72015-01-23 14:54:48 -08003096
3097 if (dsa) {
3098 fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
3099 if (!fb) {
Matt Turnerbdc9c202016-05-22 07:00:34 -07003100 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
Laura Ekstrandf868de72015-01-23 14:54:48 -08003101 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
3102 return;
3103 }
3104 }
3105 else
3106 fb = &DummyFramebuffer;
3107
Matt Turner015f2202015-07-30 14:31:04 -07003108 _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, name, fb);
Brian Paulddc82ee2005-02-05 19:56:45 +00003109 }
Matt Turner015f2202015-07-30 14:31:04 -07003110
3111 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
Brian Paulddc82ee2005-02-05 19:56:45 +00003112}
3113
3114
Laura Ekstrandf868de72015-01-23 14:54:48 -08003115void GLAPIENTRY
3116_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
3117{
3118 create_framebuffers(n, framebuffers, false);
3119}
3120
3121
3122void GLAPIENTRY
3123_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
3124{
3125 create_framebuffers(n, framebuffers, true);
3126}
3127
3128
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003129GLenum
3130_mesa_check_framebuffer_status(struct gl_context *ctx,
3131 struct gl_framebuffer *buffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00003132{
Brian Paule4b23562005-05-04 20:11:35 +00003133 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00003134
Brian Paul36ede892012-01-12 09:17:23 -07003135 if (_mesa_is_winsys_fbo(buffer)) {
Matt Turner8dd15e62013-07-26 16:36:19 -07003136 /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
3137 if (buffer != &IncompleteFramebuffer) {
3138 return GL_FRAMEBUFFER_COMPLETE_EXT;
3139 } else {
3140 return GL_FRAMEBUFFER_UNDEFINED;
3141 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00003142 }
3143
Brian Paul800e5532009-11-02 15:39:39 -07003144 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00003145
Brian Paul72966362009-01-21 16:28:38 -07003146 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
3147 _mesa_test_framebuffer_completeness(ctx, buffer);
3148 }
3149
Brian Paul0bffb112005-11-08 14:45:48 +00003150 return buffer->_Status;
Brian Paulddc82ee2005-02-05 19:56:45 +00003151}
3152
Brian Paul45bd5c42011-12-16 08:44:43 -07003153
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003154GLenum GLAPIENTRY
Samuel Pitoiset78d35102017-06-26 14:16:41 +02003155_mesa_CheckFramebufferStatus_no_error(GLenum target)
3156{
3157 GET_CURRENT_CONTEXT(ctx);
3158
3159 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3160 return _mesa_check_framebuffer_status(ctx, fb);
3161}
3162
3163
3164GLenum GLAPIENTRY
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003165_mesa_CheckFramebufferStatus(GLenum target)
3166{
3167 struct gl_framebuffer *fb;
3168 GET_CURRENT_CONTEXT(ctx);
3169
3170 if (MESA_VERBOSE & VERBOSE_API)
3171 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003172 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003173
3174 fb = get_framebuffer_target(ctx, target);
3175 if (!fb) {
3176 _mesa_error(ctx, GL_INVALID_ENUM,
3177 "glCheckFramebufferStatus(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003178 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003179 return 0;
3180 }
3181
3182 return _mesa_check_framebuffer_status(ctx, fb);
3183}
3184
3185
3186GLenum GLAPIENTRY
3187_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
3188{
3189 struct gl_framebuffer *fb;
3190 GET_CURRENT_CONTEXT(ctx);
3191
3192 /* Validate the target (for conformance's sake) and grab a reference to the
3193 * default framebuffer in case framebuffer = 0.
3194 * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
3195 * (30.10.2014, PDF page 336) says:
3196 * "If framebuffer is zero, then the status of the default read or
3197 * draw framebuffer (as determined by target) is returned."
3198 */
3199 switch (target) {
3200 case GL_DRAW_FRAMEBUFFER:
3201 case GL_FRAMEBUFFER:
3202 fb = ctx->WinSysDrawBuffer;
3203 break;
3204 case GL_READ_FRAMEBUFFER:
3205 fb = ctx->WinSysReadBuffer;
3206 break;
3207 default:
3208 _mesa_error(ctx, GL_INVALID_ENUM,
3209 "glCheckNamedFramebufferStatus(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003210 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003211 return 0;
3212 }
3213
3214 if (framebuffer) {
3215 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
3216 "glCheckNamedFramebufferStatus");
3217 if (!fb)
3218 return 0;
3219 }
3220
3221 return _mesa_check_framebuffer_status(ctx, fb);
3222}
3223
3224
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003225GLenum GLAPIENTRY
3226_mesa_CheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target)
3227{
3228 struct gl_framebuffer *fb;
3229 GET_CURRENT_CONTEXT(ctx);
3230
3231 switch (target) {
3232 case GL_DRAW_FRAMEBUFFER:
3233 case GL_FRAMEBUFFER:
3234 case GL_READ_FRAMEBUFFER:
3235 break;
3236 default:
3237 _mesa_error(ctx, GL_INVALID_ENUM,
3238 "glCheckNamedFramebufferStatusEXT(invalid target %s)",
3239 _mesa_enum_to_string(target));
3240 return 0;
3241 }
3242
3243 if (framebuffer == 0) {
3244 return _mesa_CheckNamedFramebufferStatus(0, target);
3245 }
3246
3247 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
3248 "glCheckNamedFramebufferStatusEXT");
3249 if (!fb)
3250 return 0;
3251
3252 return _mesa_check_framebuffer_status(ctx, fb);
3253}
3254
3255
Chad Versacebf8ad172011-11-10 10:19:20 -08003256/**
3257 * Replicate the src attachment point. Used by framebuffer_texture() when
3258 * the same texture is attached at GL_DEPTH_ATTACHMENT and
3259 * GL_STENCIL_ATTACHMENT.
3260 */
3261static void
3262reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
3263 gl_buffer_index dst,
3264 gl_buffer_index src)
3265{
3266 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
3267 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
Brian Paulddc82ee2005-02-05 19:56:45 +00003268
Chad Versacebf8ad172011-11-10 10:19:20 -08003269 assert(src_att->Texture != NULL);
Brian Paul45bd5c42011-12-16 08:44:43 -07003270 assert(src_att->Renderbuffer != NULL);
Chad Versacebf8ad172011-11-10 10:19:20 -08003271
3272 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
3273 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
3274 dst_att->Type = src_att->Type;
3275 dst_att->Complete = src_att->Complete;
3276 dst_att->TextureLevel = src_att->TextureLevel;
Nanley Chery63318d32016-11-15 16:42:23 -08003277 dst_att->CubeMapFace = src_att->CubeMapFace;
Chad Versacebf8ad172011-11-10 10:19:20 -08003278 dst_att->Zoffset = src_att->Zoffset;
Dave Airlie35859d52016-02-29 17:16:10 +10003279 dst_att->Layered = src_att->Layered;
Chad Versacebf8ad172011-11-10 10:19:20 -08003280}
Brian Paulddc82ee2005-02-05 19:56:45 +00003281
Brian Paul45bd5c42011-12-16 08:44:43 -07003282
Timothy Arceri304058a2017-05-05 16:25:11 +10003283static struct gl_texture_object *
3284get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
3285{
3286 if (!texture)
3287 return NULL;
3288
3289 return _mesa_lookup_texture(ctx, texture);
3290}
3291
3292
Brian Paulddc82ee2005-02-05 19:56:45 +00003293/**
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003294 * Common code called by gl*FramebufferTexture*() to retrieve the correct
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003295 * texture object pointer.
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003296 *
3297 * \param texObj where the pointer to the texture object is returned. Note
3298 * that a successful call may return texObj = NULL.
3299 *
3300 * \return true if no errors, false if errors
Brian Paulddc82ee2005-02-05 19:56:45 +00003301 */
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003302static bool
Timothy Arceri304058a2017-05-05 16:25:11 +10003303get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
3304 bool layered, const char *caller,
3305 struct gl_texture_object **texObj)
Brian Paulddc82ee2005-02-05 19:56:45 +00003306{
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003307 *texObj = NULL; /* This will get returned if texture = 0. */
Brian Paulea4fe662006-03-26 05:22:17 +00003308
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003309 if (!texture)
3310 return true;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003311
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003312 *texObj = _mesa_lookup_texture(ctx, texture);
3313 if (*texObj == NULL || (*texObj)->Target == 0) {
3314 /* Can't render to a non-existent texture object.
3315 *
3316 * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
3317 * Managing Framebuffer Objects specifies a different error
3318 * depending upon the calling function (PDF pages 325-328).
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003319 * *FramebufferTexture (where layered = GL_TRUE) throws invalid
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003320 * value, while the other commands throw invalid operation (where
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003321 * layered = GL_FALSE).
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003322 */
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003323 const GLenum error = layered ? GL_INVALID_VALUE :
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003324 GL_INVALID_OPERATION;
3325 _mesa_error(ctx, error,
3326 "%s(non-existent texture %u)", caller, texture);
3327 return false;
3328 }
3329
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003330 return true;
3331}
3332
3333
3334/**
3335 * Common code called by gl*FramebufferTexture() to verify the texture target
3336 * and decide whether or not the attachment should truly be considered
3337 * layered.
3338 *
3339 * \param layered true if attachment should be considered layered, false if
3340 * not
3341 *
3342 * \return true if no errors, false if errors
3343 */
3344static bool
3345check_layered_texture_target(struct gl_context *ctx, GLenum target,
3346 const char *caller, GLboolean *layered)
3347{
3348 *layered = GL_TRUE;
3349
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003350 switch (target) {
3351 case GL_TEXTURE_3D:
3352 case GL_TEXTURE_1D_ARRAY_EXT:
3353 case GL_TEXTURE_2D_ARRAY_EXT:
3354 case GL_TEXTURE_CUBE_MAP:
3355 case GL_TEXTURE_CUBE_MAP_ARRAY:
3356 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3357 return true;
3358 case GL_TEXTURE_1D:
3359 case GL_TEXTURE_2D:
3360 case GL_TEXTURE_RECTANGLE:
3361 case GL_TEXTURE_2D_MULTISAMPLE:
3362 /* These texture types are valid to pass to
3363 * glFramebufferTexture(), but since they aren't layered, it
3364 * is equivalent to calling glFramebufferTexture{1D,2D}().
3365 */
3366 *layered = GL_FALSE;
3367 return true;
3368 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003369
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003370 _mesa_error(ctx, GL_INVALID_OPERATION,
3371 "%s(invalid texture target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003372 _mesa_enum_to_string(target));
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003373 return false;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003374}
3375
3376
3377/**
3378 * Common code called by gl*FramebufferTextureLayer() to verify the texture
3379 * target.
3380 *
3381 * \return true if no errors, false if errors
3382 */
3383static bool
3384check_texture_target(struct gl_context *ctx, GLenum target,
3385 const char *caller)
3386{
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003387 /* We're being called by glFramebufferTextureLayer().
3388 * The only legal texture types for that function are 3D,
3389 * cube-map, and 1D/2D/cube-map array textures.
Ian Romanick832ea232015-05-20 17:19:29 -07003390 *
3391 * We don't need to check for GL_ARB_texture_cube_map_array because the
3392 * application wouldn't have been able to create a texture with a
3393 * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003394 */
3395 switch (target) {
3396 case GL_TEXTURE_3D:
3397 case GL_TEXTURE_1D_ARRAY:
3398 case GL_TEXTURE_2D_ARRAY:
3399 case GL_TEXTURE_CUBE_MAP_ARRAY:
3400 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3401 return true;
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003402 case GL_TEXTURE_CUBE_MAP:
Timothy Arceri781a7892018-08-29 12:40:12 +10003403 /* GL_TEXTURE_CUBE_MAP is only allowed by OpenGL 4.5 here, which
3404 * includes the DSA API.
3405 *
3406 * Because DSA is only enabled for GL 3.1+ and this can be called
3407 * from _mesa_FramebufferTextureLayer in compatibility profile,
3408 * we need to check the version.
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003409 */
Timothy Arceri781a7892018-08-29 12:40:12 +10003410 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003411 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003412
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003413 _mesa_error(ctx, GL_INVALID_OPERATION,
3414 "%s(invalid texture target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003415 _mesa_enum_to_string(target));
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003416 return false;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003417}
3418
3419
3420/**
3421 * Common code called by glFramebufferTexture*D() to verify the texture
3422 * target.
3423 *
3424 * \return true if no errors, false if errors
3425 */
3426static bool
3427check_textarget(struct gl_context *ctx, int dims, GLenum target,
3428 GLenum textarget, const char *caller)
3429{
3430 bool err = false;
3431
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003432 switch (textarget) {
3433 case GL_TEXTURE_1D:
3434 err = dims != 1;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003435 break;
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003436 case GL_TEXTURE_1D_ARRAY:
3437 err = dims != 1 || !ctx->Extensions.EXT_texture_array;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003438 break;
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003439 case GL_TEXTURE_2D:
3440 err = dims != 2;
3441 break;
3442 case GL_TEXTURE_2D_ARRAY:
3443 err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
3444 (_mesa_is_gles(ctx) && ctx->Version < 30);
3445 break;
3446 case GL_TEXTURE_2D_MULTISAMPLE:
3447 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3448 err = dims != 2 ||
3449 !ctx->Extensions.ARB_texture_multisample ||
3450 (_mesa_is_gles(ctx) && ctx->Version < 31);
3451 break;
3452 case GL_TEXTURE_RECTANGLE:
3453 err = dims != 2 || _mesa_is_gles(ctx) ||
3454 !ctx->Extensions.NV_texture_rectangle;
3455 break;
3456 case GL_TEXTURE_CUBE_MAP:
3457 case GL_TEXTURE_CUBE_MAP_ARRAY:
3458 err = true;
3459 break;
3460 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3461 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3462 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3463 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3464 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3465 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3466 err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
3467 break;
3468 case GL_TEXTURE_3D:
3469 err = dims != 3;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003470 break;
3471 default:
Kenneth Graunkea40640f2016-10-03 16:37:26 -07003472 _mesa_error(ctx, GL_INVALID_ENUM,
3473 "%s(unknown textarget 0x%x)", caller, textarget);
3474 return false;
Laura Ekstranda602b212015-03-02 13:43:09 -08003475 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003476
Laura Ekstranda602b212015-03-02 13:43:09 -08003477 if (err) {
3478 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003479 "%s(invalid textarget %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003480 caller, _mesa_enum_to_string(textarget));
Laura Ekstranda602b212015-03-02 13:43:09 -08003481 return false;
3482 }
3483
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003484 /* Make sure textarget is consistent with the texture's type */
3485 err = (target == GL_TEXTURE_CUBE_MAP) ?
3486 !_mesa_is_cube_face(textarget): (target != textarget);
3487
3488 if (err) {
3489 _mesa_error(ctx, GL_INVALID_OPERATION,
3490 "%s(mismatched texture target)", caller);
3491 return false;
3492 }
3493
3494 return true;
3495}
3496
3497
3498/**
3499 * Common code called by gl*FramebufferTextureLayer() and
3500 * glFramebufferTexture3D() to validate the layer.
3501 *
3502 * \return true if no errors, false if errors
3503 */
3504static bool
3505check_layer(struct gl_context *ctx, GLenum target, GLint layer,
3506 const char *caller)
3507{
Laura Ekstranda602b212015-03-02 13:43:09 -08003508 /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
3509 * spec says:
3510 *
3511 * "An INVALID_VALUE error is generated if texture is non-zero
3512 * and layer is negative."
3513 */
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003514 if (layer < 0) {
Brian Paul08ba4a12017-12-05 09:57:23 -07003515 _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
Laura Ekstranda602b212015-03-02 13:43:09 -08003516 return false;
3517 }
3518
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003519 if (target == GL_TEXTURE_3D) {
Laura Ekstranda602b212015-03-02 13:43:09 -08003520 const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003521 if (layer >= maxSize) {
Fredrik Höglund8ba7ad82015-05-09 15:31:45 +02003522 _mesa_error(ctx, GL_INVALID_VALUE,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003523 "%s(invalid layer %u)", caller, layer);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003524 return false;
Fredrik Höglund8ba7ad82015-05-09 15:31:45 +02003525 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003526 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003527 else if ((target == GL_TEXTURE_1D_ARRAY) ||
3528 (target == GL_TEXTURE_2D_ARRAY) ||
3529 (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
3530 (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
3531 if (layer >= ctx->Const.MaxArrayTextureLayers) {
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003532 _mesa_error(ctx, GL_INVALID_VALUE,
Laura Ekstranda602b212015-03-02 13:43:09 -08003533 "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003534 caller, layer);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003535 return false;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003536 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003537 }
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003538 else if (target == GL_TEXTURE_CUBE_MAP) {
3539 if (layer >= 6) {
3540 _mesa_error(ctx, GL_INVALID_VALUE,
3541 "%s(layer %u >= 6)", caller, layer);
3542 return false;
3543 }
3544 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003545
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003546 return true;
3547}
3548
3549
3550/**
3551 * Common code called by all gl*FramebufferTexture*() entry points to verify
3552 * the level.
3553 *
3554 * \return true if no errors, false if errors
3555 */
3556static bool
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003557check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
3558 GLenum target, GLint level, const char *caller)
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003559{
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003560 /* Section 9.2.8 of the OpenGL 4.6 specification says:
3561 *
3562 * "If texture refers to an immutable-format texture, level must be
3563 * greater than or equal to zero and smaller than the value of
3564 * TEXTURE_VIEW_NUM_LEVELS for texture."
3565 */
3566 const int max_levels = texObj->Immutable ? texObj->ImmutableLevels :
3567 _mesa_max_texture_levels(ctx, target);
3568
3569 if (level < 0 || level >= max_levels) {
Laura Ekstranda602b212015-03-02 13:43:09 -08003570 _mesa_error(ctx, GL_INVALID_VALUE,
3571 "%s(invalid level %d)", caller, level);
3572 return false;
3573 }
Brian Paulea4fe662006-03-26 05:22:17 +00003574
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003575 return true;
3576}
3577
3578
Timothy Arcerid90ced42017-05-05 16:46:03 +10003579struct gl_renderbuffer_attachment *
3580_mesa_get_and_validate_attachment(struct gl_context *ctx,
3581 struct gl_framebuffer *fb,
3582 GLenum attachment, const char *caller)
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003583{
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003584 /* The window-system framebuffer object is immutable */
3585 if (_mesa_is_winsys_fbo(fb)) {
3586 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
3587 caller);
Timothy Arcerid90ced42017-05-05 16:46:03 +10003588 return NULL;
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003589 }
3590
3591 /* Not a hash lookup, so we can afford to get the attachment here. */
Timothy Arcerid90ced42017-05-05 16:46:03 +10003592 bool is_color_attachment;
3593 struct gl_renderbuffer_attachment *att =
3594 get_attachment(ctx, fb, attachment, &is_color_attachment);
Brian Paul3deaa012005-02-07 05:08:24 +00003595 if (att == NULL) {
Ilia Mirkin62b8f492017-01-24 00:26:29 -05003596 if (is_color_attachment) {
3597 _mesa_error(ctx, GL_INVALID_OPERATION,
3598 "%s(invalid color attachment %s)", caller,
3599 _mesa_enum_to_string(attachment));
3600 } else {
3601 _mesa_error(ctx, GL_INVALID_ENUM,
3602 "%s(invalid attachment %s)", caller,
3603 _mesa_enum_to_string(attachment));
3604 }
Timothy Arcerid90ced42017-05-05 16:46:03 +10003605 return NULL;
Brian Paul3deaa012005-02-07 05:08:24 +00003606 }
3607
Timothy Arcerid90ced42017-05-05 16:46:03 +10003608 return att;
3609}
3610
3611
3612void
3613_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
3614 GLenum attachment,
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003615 struct gl_renderbuffer_attachment *att,
Timothy Arcerid90ced42017-05-05 16:46:03 +10003616 struct gl_texture_object *texObj, GLenum textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003617 GLint level, GLsizei samples,
3618 GLuint layer, GLboolean layered)
Timothy Arcerid90ced42017-05-05 16:46:03 +10003619{
Brian Paul800e5532009-11-02 15:39:39 -07003620 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paul474f28e2005-10-08 14:41:17 +00003621
Timothy Arcerif0857fe2017-10-16 11:59:31 +11003622 simple_mtx_lock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +00003623 if (texObj) {
Chad Versacebf8ad172011-11-10 10:19:20 -08003624 if (attachment == GL_DEPTH_ATTACHMENT &&
Paul Berryb9819a02012-04-13 21:50:08 -07003625 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
3626 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
3627 _mesa_tex_target_to_face(textarget) ==
3628 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003629 samples == fb->Attachment[BUFFER_STENCIL].NumSamples &&
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003630 layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003631 /* The texture object is already attached to the stencil attachment
3632 * point. Don't create a new renderbuffer; just reuse the stencil
3633 * attachment's. This is required to prevent a GL error in
3634 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
3635 */
3636 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
3637 BUFFER_STENCIL);
Chad Versacebf8ad172011-11-10 10:19:20 -08003638 } else if (attachment == GL_STENCIL_ATTACHMENT &&
Martin Peres7bd8b482015-02-12 17:54:43 +02003639 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
Paul Berryb9819a02012-04-13 21:50:08 -07003640 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
3641 _mesa_tex_target_to_face(textarget) ==
3642 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003643 samples == fb->Attachment[BUFFER_DEPTH].NumSamples &&
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003644 layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003645 /* As above, but with depth and stencil transposed. */
3646 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
3647 BUFFER_DEPTH);
Chad Versacebf8ad172011-11-10 10:19:20 -08003648 } else {
Martin Peres7bd8b482015-02-12 17:54:43 +02003649 set_texture_attachment(ctx, fb, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003650 level, samples, layer, layered);
Laura Ekstrand8f78c682015-01-27 14:11:13 -08003651
Martin Peres7bd8b482015-02-12 17:54:43 +02003652 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3653 /* Above we created a new renderbuffer and attached it to the
3654 * depth attachment point. Now attach it to the stencil attachment
3655 * point too.
3656 */
3657 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3658 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
3659 BUFFER_DEPTH);
3660 }
Chad Versacebf8ad172011-11-10 10:19:20 -08003661 }
3662
Brian Paul2897cee2009-01-29 09:20:18 -07003663 /* Set the render-to-texture flag. We'll check this flag in
3664 * glTexImage() and friends to determine if we need to revalidate
3665 * any FBOs that might be rendering into this texture.
3666 * This flag never gets cleared since it's non-trivial to determine
3667 * when all FBOs might be done rendering to this texture. That's OK
3668 * though since it's uncommon to render to a texture then repeatedly
3669 * call glTexImage() to change images in the texture.
3670 */
3671 texObj->_RenderToTexture = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +00003672 }
3673 else {
Brian Paul94512812014-02-01 08:58:43 -07003674 remove_attachment(ctx, att);
Chad Versacebf8ad172011-11-10 10:19:20 -08003675 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003676 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3677 remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
Chad Versacebf8ad172011-11-10 10:19:20 -08003678 }
Brian Paul3deaa012005-02-07 05:08:24 +00003679 }
Brian Paul72966362009-01-21 16:28:38 -07003680
3681 invalidate_framebuffer(fb);
3682
Timothy Arcerif0857fe2017-10-16 11:59:31 +11003683 simple_mtx_unlock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +00003684}
3685
3686
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003687static void
Timothy Arceri20cabc22017-05-08 10:59:15 +10003688framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
3689 GLenum textarget, GLuint texture,
3690 GLint level, GLint layer)
3691{
3692 GET_CURRENT_CONTEXT(ctx);
3693
3694 /* Get the framebuffer object */
3695 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3696
3697 /* Get the texture object */
3698 struct gl_texture_object *texObj =
3699 get_texture_for_framebuffer(ctx, texture);
3700
3701 struct gl_renderbuffer_attachment *att =
3702 get_attachment(ctx, fb, attachment, NULL);
3703
3704 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003705 level, 0, layer, GL_FALSE);
Timothy Arceri20cabc22017-05-08 10:59:15 +10003706}
3707
3708
3709static void
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003710framebuffer_texture_with_dims(int dims, GLenum target, GLuint framebuffer,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003711 GLenum attachment, GLenum textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003712 GLuint texture, GLint level, GLsizei samples,
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003713 GLint layer, const char *caller, bool dsa)
Brian Paulea4fe662006-03-26 05:22:17 +00003714{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003715 GET_CURRENT_CONTEXT(ctx);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003716 struct gl_framebuffer *fb;
3717 struct gl_texture_object *texObj;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003718
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003719 /* Get the framebuffer object */
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003720 if (dsa) {
3721 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer, caller);
3722 } else {
3723 fb = get_framebuffer_target(ctx, target);
3724 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003725 if (!fb) {
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003726 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003727 _mesa_enum_to_string(target));
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003728 return;
3729 }
3730
3731 /* Get the texture object */
Timothy Arceri304058a2017-05-05 16:25:11 +10003732 if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003733 return;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003734
3735 if (texObj) {
3736 if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
3737 return;
3738
3739 if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
3740 return;
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003741
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003742 if (!check_level(ctx, texObj, textarget, level, caller))
Marek Olšák04a78062016-05-27 21:40:19 +02003743 return;
3744 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003745
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003746 struct gl_renderbuffer_attachment *att =
3747 _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
3748 if (!att)
3749 return;
3750
3751 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003752 level, samples, layer, GL_FALSE);
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003753}
3754
3755
3756void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003757_mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
3758 GLenum textarget, GLuint texture,
3759 GLint level)
3760{
3761 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3762 texture, level, 0);
3763}
3764
3765
3766void GLAPIENTRY
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003767_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
3768 GLenum textarget, GLuint texture, GLint level)
3769{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003770 framebuffer_texture_with_dims(1, target, 0, attachment, textarget, texture,
3771 level, 0, 0, "glFramebufferTexture1D", false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003772}
3773
3774
Brian Paul1864c7d2005-02-08 03:46:37 +00003775void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003776_mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
3777 GLenum textarget, GLuint texture,
3778 GLint level)
3779{
3780 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3781 texture, level, 0);
3782}
3783
3784
3785void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003786_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
Brian Paulc1377ed2014-03-22 10:31:58 -06003787 GLenum textarget, GLuint texture, GLint level)
Brian Paulddc82ee2005-02-05 19:56:45 +00003788{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003789 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3790 level, 0, 0, "glFramebufferTexture2D", false);
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003791}
3792
3793
3794void GLAPIENTRY
3795_mesa_FramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment,
3796 GLenum textarget, GLuint texture,
3797 GLint level, GLsizei samples)
3798{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003799 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3800 level, samples, 0,
3801 "glFramebufferTexture2DMultisampleEXT",
3802 false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003803}
3804
3805
Brian Paul1864c7d2005-02-08 03:46:37 +00003806void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003807_mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
3808 GLenum textarget, GLuint texture,
3809 GLint level, GLint layer)
3810{
3811 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3812 texture, level, layer);
3813}
3814
3815
3816void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003817_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
Brian Paulc1377ed2014-03-22 10:31:58 -06003818 GLenum textarget, GLuint texture,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003819 GLint level, GLint layer)
Brian Paulddc82ee2005-02-05 19:56:45 +00003820{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003821 framebuffer_texture_with_dims(3, target, 0, attachment, textarget, texture,
3822 level, 0, layer, "glFramebufferTexture3D", false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003823}
3824
3825
Timothy Arceri01081c62017-05-10 11:22:47 +10003826static ALWAYS_INLINE void
Timothy Arcerif6229282017-05-10 11:44:54 +10003827frame_buffer_texture(GLuint framebuffer, GLenum target,
3828 GLenum attachment, GLuint texture,
3829 GLint level, GLint layer, const char *func,
3830 bool dsa, bool no_error, bool check_layered)
Ian Romanickbb372f12007-05-16 15:34:22 -07003831{
3832 GET_CURRENT_CONTEXT(ctx);
Timothy Arcerif6229282017-05-10 11:44:54 +10003833 GLboolean layered = GL_FALSE;
3834
3835 if (!no_error && check_layered) {
3836 if (!_mesa_has_geometry_shaders(ctx)) {
3837 _mesa_error(ctx, GL_INVALID_OPERATION,
3838 "unsupported function (%s) called", func);
3839 return;
3840 }
3841 }
Ian Romanickbb372f12007-05-16 15:34:22 -07003842
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003843 /* Get the framebuffer object */
Timothy Arceri01081c62017-05-10 11:22:47 +10003844 struct gl_framebuffer *fb;
Timothy Arcerif6198e92017-05-11 15:43:44 +10003845 if (no_error) {
3846 if (dsa) {
3847 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
3848 } else {
3849 fb = get_framebuffer_target(ctx, target);
3850 }
Timothy Arceri01081c62017-05-10 11:22:47 +10003851 } else {
Timothy Arcerif6198e92017-05-11 15:43:44 +10003852 if (dsa) {
3853 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
3854 if (!fb)
3855 return;
3856 } else {
3857 fb = get_framebuffer_target(ctx, target);
3858 if (!fb) {
3859 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
3860 func, _mesa_enum_to_string(target));
3861 return;
3862 }
Timothy Arceri01081c62017-05-10 11:22:47 +10003863 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003864 }
3865
Timothy Arcerif6198e92017-05-11 15:43:44 +10003866 /* Get the texture object and framebuffer attachment*/
3867 struct gl_renderbuffer_attachment *att;
Timothy Arceri01081c62017-05-10 11:22:47 +10003868 struct gl_texture_object *texObj;
Timothy Arcerif6198e92017-05-11 15:43:44 +10003869 if (no_error) {
3870 texObj = get_texture_for_framebuffer(ctx, texture);
3871 att = get_attachment(ctx, fb, attachment, NULL);
3872 } else {
Timothy Arcerif6229282017-05-10 11:44:54 +10003873 if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
Timothy Arcerif6198e92017-05-11 15:43:44 +10003874 &texObj))
3875 return;
3876
3877 att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
3878 if (!att)
3879 return;
3880 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003881
Timothy Arceri01081c62017-05-10 11:22:47 +10003882 GLenum textarget = 0;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003883 if (texObj) {
Timothy Arcerif6229282017-05-10 11:44:54 +10003884 if (check_layered) {
3885 /* We do this regardless of no_error because this sets layered */
3886 if (!check_layered_texture_target(ctx, texObj->Target, func,
3887 &layered))
Timothy Arcerif6198e92017-05-11 15:43:44 +10003888 return;
Timothy Arcerif6229282017-05-10 11:44:54 +10003889 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003890
Timothy Arcerif6229282017-05-10 11:44:54 +10003891 if (!no_error) {
3892 if (!check_layered) {
3893 if (!check_texture_target(ctx, texObj->Target, func))
3894 return;
3895
3896 if (!check_layer(ctx, texObj->Target, layer, func))
3897 return;
3898 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003899
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003900 if (!check_level(ctx, texObj, texObj->Target, level, func))
Timothy Arcerif6198e92017-05-11 15:43:44 +10003901 return;
3902 }
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003903
Timothy Arcerif6229282017-05-10 11:44:54 +10003904 if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003905 assert(layer >= 0 && layer < 6);
3906 textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
3907 layer = 0;
3908 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003909 }
3910
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003911 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003912 level, 0, layer, layered);
Ian Romanickbb372f12007-05-16 15:34:22 -07003913}
3914
Timothy Arcerie75e8d62017-05-08 11:24:07 +10003915void GLAPIENTRY
3916_mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
3917 GLuint texture, GLint level,
3918 GLint layer)
3919{
Timothy Arcerif6229282017-05-10 11:44:54 +10003920 frame_buffer_texture(0, target, attachment, texture, level, layer,
3921 "glFramebufferTextureLayer", false, true, false);
Timothy Arcerie75e8d62017-05-08 11:24:07 +10003922}
3923
Ian Romanickbb372f12007-05-16 15:34:22 -07003924
3925void GLAPIENTRY
Timothy Arceri01081c62017-05-10 11:22:47 +10003926_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
3927 GLuint texture, GLint level, GLint layer)
3928{
Timothy Arcerif6229282017-05-10 11:44:54 +10003929 frame_buffer_texture(0, target, attachment, texture, level, layer,
3930 "glFramebufferTextureLayer", false, false, false);
Timothy Arceri01081c62017-05-10 11:22:47 +10003931}
3932
3933
3934void GLAPIENTRY
Timothy Arceri4e125c42017-05-08 11:37:33 +10003935_mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
3936 GLenum attachment,
3937 GLuint texture, GLint level,
3938 GLint layer)
3939{
Timothy Arcerif6229282017-05-10 11:44:54 +10003940 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3941 "glNamedFramebufferTextureLayer", true, true, false);
Timothy Arceri4e125c42017-05-08 11:37:33 +10003942}
3943
3944
3945void GLAPIENTRY
Laura Ekstrandd78c8312015-01-28 13:19:57 -08003946_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
3947 GLuint texture, GLint level, GLint layer)
3948{
Timothy Arcerif6229282017-05-10 11:44:54 +10003949 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3950 "glNamedFramebufferTextureLayer", true, false, false);
Laura Ekstrandd78c8312015-01-28 13:19:57 -08003951}
3952
3953
3954void GLAPIENTRY
Timothy Arceri4e8aa4b2017-05-08 11:52:45 +10003955_mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
3956 GLuint texture, GLint level)
3957{
3958 frame_buffer_texture(0, target, attachment, texture, level, 0,
3959 "glFramebufferTexture", false, true, true);
3960}
3961
3962
3963void GLAPIENTRY
Jordan Justen02f2bce2013-04-18 10:46:12 -07003964_mesa_FramebufferTexture(GLenum target, GLenum attachment,
3965 GLuint texture, GLint level)
3966{
Timothy Arcerif6229282017-05-10 11:44:54 +10003967 frame_buffer_texture(0, target, attachment, texture, level, 0,
3968 "glFramebufferTexture", false, false, true);
Jordan Justen02f2bce2013-04-18 10:46:12 -07003969}
3970
Timothy Arceri3336d242017-05-08 12:01:33 +10003971void GLAPIENTRY
3972_mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
3973 GLuint texture, GLint level)
3974{
3975 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
3976 "glNamedFramebufferTexture", true, true, true);
3977}
3978
Jordan Justen02f2bce2013-04-18 10:46:12 -07003979
Laura Ekstrandd78c8312015-01-28 13:19:57 -08003980void GLAPIENTRY
3981_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
3982 GLuint texture, GLint level)
3983{
Timothy Arcerif6229282017-05-10 11:44:54 +10003984 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
3985 "glNamedFramebufferTexture", true, false, true);
Laura Ekstrandd78c8312015-01-28 13:19:57 -08003986}
3987
3988
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003989void GLAPIENTRY
3990_mesa_NamedFramebufferTexture1DEXT(GLuint framebuffer, GLenum attachment,
3991 GLenum textarget, GLuint texture, GLint level)
3992{
3993 framebuffer_texture_with_dims(1, GL_FRAMEBUFFER, framebuffer, attachment,
3994 textarget, texture, level, 0, 0,
3995 "glNamedFramebufferTexture1DEXT", true);
3996}
3997
3998
3999void GLAPIENTRY
4000_mesa_NamedFramebufferTexture2DEXT(GLuint framebuffer, GLenum attachment,
4001 GLenum textarget, GLuint texture, GLint level)
4002{
4003 framebuffer_texture_with_dims(2, GL_FRAMEBUFFER, framebuffer, attachment,
4004 textarget, texture, level, 0, 0,
4005 "glNamedFramebufferTexture2DEXT", true);
4006}
4007
4008
4009void GLAPIENTRY
4010_mesa_NamedFramebufferTexture3DEXT(GLuint framebuffer, GLenum attachment,
4011 GLenum textarget, GLuint texture,
4012 GLint level, GLint zoffset)
4013{
4014 framebuffer_texture_with_dims(3, GL_FRAMEBUFFER, framebuffer, attachment,
4015 textarget, texture, level, 0, zoffset,
4016 "glNamedFramebufferTexture3DEXT", true);
4017}
4018
4019
Laura Ekstranda29318b2015-02-27 17:27:30 -08004020void
4021_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
4022 struct gl_framebuffer *fb,
4023 GLenum attachment,
Ian Romanick9ae42ab2015-11-11 16:30:41 -08004024 struct gl_renderbuffer *rb)
4025{
4026 assert(!_mesa_is_winsys_fbo(fb));
4027
4028 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
4029
4030 assert(ctx->Driver.FramebufferRenderbuffer);
4031 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
4032
4033 /* Some subsequent GL commands may depend on the framebuffer's visual
4034 * after the binding is updated. Update visual info now.
4035 */
4036 _mesa_update_framebuffer_visual(ctx, fb);
4037}
4038
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004039static ALWAYS_INLINE void
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004040framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
4041 GLenum attachment, GLenum renderbuffertarget,
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004042 GLuint renderbuffer, const char *func, bool no_error)
Brian Paulddc82ee2005-02-05 19:56:45 +00004043{
Brian Paul2c6f9112005-02-24 05:47:06 +00004044 struct gl_renderbuffer_attachment *att;
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004045 struct gl_renderbuffer *rb;
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004046 bool is_color_attachment;
Brian Paul3deaa012005-02-07 05:08:24 +00004047
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004048 if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004049 _mesa_error(ctx, GL_INVALID_ENUM,
4050 "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
4051 return;
4052 }
4053
4054 if (renderbuffer) {
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004055 if (!no_error) {
4056 rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
4057 if (!rb)
4058 return;
4059 } else {
4060 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
4061 }
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004062 } else {
4063 /* remove renderbuffer attachment */
4064 rb = NULL;
4065 }
4066
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004067 if (!no_error) {
4068 if (_mesa_is_winsys_fbo(fb)) {
4069 /* Can't attach new renderbuffers to a window system framebuffer */
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004070 _mesa_error(ctx, GL_INVALID_OPERATION,
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004071 "%s(window-system framebuffer)", func);
4072 return;
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004073 }
4074
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004075 att = get_attachment(ctx, fb, attachment, &is_color_attachment);
4076 if (att == NULL) {
4077 /*
4078 * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
4079 * to a Framebuffer":
4080 *
4081 * "An INVALID_OPERATION error is generated if attachment is
4082 * COLOR_- ATTACHMENTm where m is greater than or equal to the
4083 * value of MAX_COLOR_- ATTACHMENTS ."
4084 *
4085 * If we are at this point, is because the attachment is not valid, so
4086 * if is_color_attachment is true, is because of the previous reason.
4087 */
4088 if (is_color_attachment) {
4089 _mesa_error(ctx, GL_INVALID_OPERATION,
4090 "%s(invalid color attachment %s)", func,
4091 _mesa_enum_to_string(attachment));
4092 } else {
4093 _mesa_error(ctx, GL_INVALID_ENUM,
4094 "%s(invalid attachment %s)", func,
4095 _mesa_enum_to_string(attachment));
4096 }
Brian Paulddc82ee2005-02-05 19:56:45 +00004097
Brian Paul30590072009-01-21 11:06:11 -07004098 return;
4099 }
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004100
4101 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
4102 rb && rb->Format != MESA_FORMAT_NONE) {
4103 /* make sure the renderbuffer is a depth/stencil format */
4104 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
4105 if (baseFormat != GL_DEPTH_STENCIL) {
4106 _mesa_error(ctx, GL_INVALID_OPERATION,
4107 "%s(renderbuffer is not DEPTH_STENCIL format)", func);
4108 return;
4109 }
4110 }
Brian Paul30590072009-01-21 11:06:11 -07004111 }
4112
Ian Romanick9ae42ab2015-11-11 16:30:41 -08004113 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
Brian Paulddc82ee2005-02-05 19:56:45 +00004114}
4115
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004116static void
4117framebuffer_renderbuffer_error(struct gl_context *ctx,
4118 struct gl_framebuffer *fb, GLenum attachment,
4119 GLenum renderbuffertarget,
4120 GLuint renderbuffer, const char *func)
4121{
4122 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4123 renderbuffer, func, false);
4124}
4125
Samuel Pitoiset0a20e432017-07-19 12:28:21 +02004126static void
4127framebuffer_renderbuffer_no_error(struct gl_context *ctx,
4128 struct gl_framebuffer *fb, GLenum attachment,
4129 GLenum renderbuffertarget,
4130 GLuint renderbuffer, const char *func)
4131{
4132 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4133 renderbuffer, func, true);
4134}
4135
4136void GLAPIENTRY
4137_mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
4138 GLenum renderbuffertarget,
4139 GLuint renderbuffer)
4140{
4141 GET_CURRENT_CONTEXT(ctx);
4142
4143 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
4144 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4145 renderbuffer, "glFramebufferRenderbuffer");
4146}
4147
Brian Paul1864c7d2005-02-08 03:46:37 +00004148void GLAPIENTRY
Laura Ekstranda29318b2015-02-27 17:27:30 -08004149_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
4150 GLenum renderbuffertarget,
4151 GLuint renderbuffer)
4152{
4153 struct gl_framebuffer *fb;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004154 GET_CURRENT_CONTEXT(ctx);
4155
4156 fb = get_framebuffer_target(ctx, target);
4157 if (!fb) {
4158 _mesa_error(ctx, GL_INVALID_ENUM,
4159 "glFramebufferRenderbuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004160 _mesa_enum_to_string(target));
Laura Ekstranda29318b2015-02-27 17:27:30 -08004161 return;
4162 }
4163
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004164 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4165 renderbuffer, "glFramebufferRenderbuffer");
Laura Ekstranda29318b2015-02-27 17:27:30 -08004166}
4167
Samuel Pitoiset7bc50df2017-07-19 12:32:42 +02004168void GLAPIENTRY
4169_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
4170 GLenum attachment,
4171 GLenum renderbuffertarget,
4172 GLuint renderbuffer)
4173{
4174 GET_CURRENT_CONTEXT(ctx);
4175
4176 struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4177 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4178 renderbuffer,
4179 "glNamedFramebufferRenderbuffer");
4180}
Laura Ekstranda29318b2015-02-27 17:27:30 -08004181
4182void GLAPIENTRY
4183_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
4184 GLenum renderbuffertarget,
4185 GLuint renderbuffer)
4186{
4187 struct gl_framebuffer *fb;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004188 GET_CURRENT_CONTEXT(ctx);
4189
4190 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4191 "glNamedFramebufferRenderbuffer");
Fredrik Höglund5a55f682015-05-16 19:43:39 +02004192 if (!fb)
4193 return;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004194
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004195 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4196 renderbuffer,
4197 "glNamedFramebufferRenderbuffer");
Laura Ekstranda29318b2015-02-27 17:27:30 -08004198}
4199
4200
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004201void GLAPIENTRY
4202_mesa_NamedFramebufferRenderbufferEXT(GLuint framebuffer, GLenum attachment,
4203 GLenum renderbuffertarget,
4204 GLuint renderbuffer)
4205{
4206 struct gl_framebuffer *fb;
4207 GET_CURRENT_CONTEXT(ctx);
4208
4209 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4210 "glNamedFramebufferRenderbufferEXT");
4211 if (!fb)
4212 return;
4213
4214 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4215 renderbuffer,
4216 "glNamedFramebufferRenderbuffer");
4217}
4218
4219
Timothy Arceri8b006302017-05-05 15:21:22 +10004220static void
4221get_framebuffer_attachment_parameter(struct gl_context *ctx,
4222 struct gl_framebuffer *buffer,
4223 GLenum attachment, GLenum pname,
4224 GLint *params, const char *caller)
Brian Paulddc82ee2005-02-05 19:56:45 +00004225{
Brian Paul2c6f9112005-02-24 05:47:06 +00004226 const struct gl_renderbuffer_attachment *att;
Robert Foss88becf72017-03-01 19:14:39 -05004227 bool is_color_attachment = false;
Marek Olšák000896c2011-07-19 03:05:07 +02004228 GLenum err;
Brian Paulddc82ee2005-02-05 19:56:45 +00004229
Kenneth Graunke19f13b22016-03-07 16:43:35 -08004230 /* The error code for an attachment type of GL_NONE differs between APIs.
4231 *
4232 * From the ES 2.0.25 specification, page 127:
4233 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4234 * querying any other pname will generate INVALID_ENUM."
4235 *
4236 * From the OpenGL 3.0 specification, page 337, or identically,
4237 * the OpenGL ES 3.0.4 specification, page 240:
4238 *
4239 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no
4240 * framebuffer is bound to target. In this case querying pname
4241 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero, and all other
4242 * queries will generate an INVALID_OPERATION error."
4243 */
4244 err = ctx->API == API_OPENGLES2 && ctx->Version < 30 ?
4245 GL_INVALID_ENUM : GL_INVALID_OPERATION;
Marek Olšák000896c2011-07-19 03:05:07 +02004246
Brian Paul36ede892012-01-12 09:17:23 -07004247 if (_mesa_is_winsys_fbo(buffer)) {
Ian Romanickda2e41c2011-10-03 12:04:09 -07004248 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
4249 * says:
4250 *
4251 * "If the framebuffer currently bound to target is zero, then
4252 * INVALID_OPERATION is generated."
4253 *
4254 * The EXT_framebuffer_object spec has the same wording, and the
4255 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
4256 * spec.
4257 */
Brian Paulc1377ed2014-03-22 10:31:58 -06004258 if ((!_mesa_is_desktop_gl(ctx) ||
4259 !ctx->Extensions.ARB_framebuffer_object)
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004260 && !_mesa_is_gles3(ctx)) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004261 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004262 "%s(window-system framebuffer)", caller);
Martin Peres7bd8b482015-02-12 17:54:43 +02004263 return;
Ian Romanickda2e41c2011-10-03 12:04:09 -07004264 }
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004265
4266 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
4267 attachment != GL_DEPTH && attachment != GL_STENCIL) {
Samuel Iglesias Gonsalvez284bd1e2015-01-16 16:00:13 +01004268 _mesa_error(ctx, GL_INVALID_ENUM,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004269 "%s(invalid attachment %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004270 _mesa_enum_to_string(attachment));
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004271 return;
4272 }
Kenneth Graunke789e0962016-03-08 23:59:37 -08004273
4274 /* The specs are not clear about how to handle
4275 * GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME with the default framebuffer,
4276 * but dEQP-GLES3 expects an INVALID_ENUM error. This has also been
4277 * discussed in:
4278 *
4279 * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=12928#c1
4280 * and https://bugs.freedesktop.org/show_bug.cgi?id=31947
4281 */
4282 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4283 _mesa_error(ctx, GL_INVALID_ENUM,
4284 "%s(requesting GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME "
4285 "when GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
4286 "GL_FRAMEBUFFER_DEFAULT is not allowed)", caller);
4287 return;
4288 }
4289
Brian Paul61ec2052010-06-22 08:37:44 -06004290 /* the default / window-system FBO */
Timothy Arcerie6187612017-05-05 15:02:20 +10004291 att = get_fb0_attachment(ctx, buffer, attachment);
Brian Paul61ec2052010-06-22 08:37:44 -06004292 }
4293 else {
4294 /* user-created framebuffer FBO */
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004295 att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
Brian Paul61ec2052010-06-22 08:37:44 -06004296 }
4297
Brian Paul3deaa012005-02-07 05:08:24 +00004298 if (att == NULL) {
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004299 /*
4300 * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
4301 *
4302 * "An INVALID_OPERATION error is generated if a framebuffer object
4303 * is bound to target and attachment is COLOR_ATTACHMENTm where m is
4304 * greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
4305 *
4306 * If we are at this point, is because the attachment is not valid, so
4307 * if is_color_attachment is true, is because of the previous reason.
4308 */
4309 if (is_color_attachment) {
4310 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
4311 caller, _mesa_enum_to_string(attachment));
4312 } else {
4313 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
4314 _mesa_enum_to_string(attachment));
4315 }
Brian Paulddc82ee2005-02-05 19:56:45 +00004316 return;
4317 }
4318
Brian Paul30590072009-01-21 11:06:11 -07004319 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Brian Paule9592742014-04-21 13:24:25 -06004320 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
Anuj Phogatbd1880d2014-03-11 17:04:11 -07004321 if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
4322 /* This behavior is first specified in OpenGL 4.4 specification.
4323 *
4324 * From the OpenGL 4.4 spec page 275:
4325 * "This query cannot be performed for a combined depth+stencil
4326 * attachment, since it does not have a single format."
4327 */
4328 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004329 "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
4330 " is invalid for depth+stencil attachment)", caller);
Anuj Phogatbd1880d2014-03-11 17:04:11 -07004331 return;
4332 }
Brian Paul30590072009-01-21 11:06:11 -07004333 /* the depth and stencil attachments must point to the same buffer */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02004334 depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
4335 stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
Brian Paul30590072009-01-21 11:06:11 -07004336 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
4337 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004338 "%s(DEPTH/STENCIL attachments differ)", caller);
Brian Paul30590072009-01-21 11:06:11 -07004339 return;
4340 }
4341 }
4342
Brian Paul800e5532009-11-02 15:39:39 -07004343 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00004344
Brian Paulddc82ee2005-02-05 19:56:45 +00004345 switch (pname) {
4346 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
Iago Toral Quirogacf439952015-02-24 19:02:56 +01004347 /* From the OpenGL spec, 9.2. Binding and Managing Framebuffer Objects:
4348 *
4349 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4350 * either no framebuffer is bound to target; or the default framebuffer
4351 * is bound, attachment is DEPTH or STENCIL, and the number of depth or
4352 * stencil bits, respectively, is zero."
Alejandro Piñeiro90596142017-01-13 11:39:24 -02004353 *
4354 * Note that we don't need explicit checks on DEPTH and STENCIL, because
4355 * on the case the spec is pointing, att->Type is already NONE, so we
4356 * just need to check att->Type.
Iago Toral Quirogacf439952015-02-24 19:02:56 +01004357 */
Alejandro Piñeiro90596142017-01-13 11:39:24 -02004358 *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
4359 GL_FRAMEBUFFER_DEFAULT : att->Type;
Brian Paul3deaa012005-02-07 05:08:24 +00004360 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004361 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004362 if (att->Type == GL_RENDERBUFFER_EXT) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004363 *params = att->Renderbuffer->Name;
Brian Paul3deaa012005-02-07 05:08:24 +00004364 }
4365 else if (att->Type == GL_TEXTURE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004366 *params = att->Texture->Name;
Brian Paul3deaa012005-02-07 05:08:24 +00004367 }
4368 else {
Brian Paul20cf1852010-12-03 08:23:31 -07004369 assert(att->Type == GL_NONE);
Ian Romanick0cdaa472012-07-27 07:47:28 -07004370 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
Marek Olšák000896c2011-07-19 03:05:07 +02004371 *params = 0;
4372 } else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004373 goto invalid_pname_enum;
Marek Olšák000896c2011-07-19 03:05:07 +02004374 }
Brian Paul3deaa012005-02-07 05:08:24 +00004375 }
4376 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004377 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004378 if (att->Type == GL_TEXTURE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004379 *params = att->TextureLevel;
Brian Paul3deaa012005-02-07 05:08:24 +00004380 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004381 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004382 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004383 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004384 }
Brian Paul3deaa012005-02-07 05:08:24 +00004385 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004386 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004387 }
4388 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004389 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004390 if (att->Type == GL_TEXTURE) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06004391 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
4392 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
4393 }
4394 else {
4395 *params = 0;
4396 }
Brian Paul3deaa012005-02-07 05:08:24 +00004397 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004398 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004399 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004400 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004401 }
Brian Paul3deaa012005-02-07 05:08:24 +00004402 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004403 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004404 }
4405 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004406 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
Ian Romanick0cdaa472012-07-27 07:47:28 -07004407 if (ctx->API == API_OPENGLES) {
4408 goto invalid_pname_enum;
4409 } else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004410 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004411 _mesa_enum_to_string(pname));
Ian Romanick0cdaa472012-07-27 07:47:28 -07004412 } else if (att->Type == GL_TEXTURE) {
Samuel Iglesias Gonsalvez8e49a3e2014-12-11 23:34:13 +01004413 if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
4414 att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06004415 *params = att->Zoffset;
4416 }
4417 else {
4418 *params = 0;
4419 }
Brian Paul3deaa012005-02-07 05:08:24 +00004420 }
4421 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004422 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004423 }
4424 return;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004425 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Brian Paulc1377ed2014-03-22 10:31:58 -06004426 if ((!_mesa_is_desktop_gl(ctx) ||
4427 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004428 && !_mesa_is_gles3(ctx)) {
4429 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004430 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004431 else if (att->Type == GL_NONE) {
Kenneth Graunke713cd232016-12-09 16:16:53 -08004432 if (_mesa_is_winsys_fbo(buffer) &&
4433 (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
4434 *params = GL_LINEAR;
4435 } else {
4436 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4437 _mesa_enum_to_string(pname));
4438 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004439 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004440 else {
Gert Wollny76c3f6f2018-11-14 10:58:40 +01004441 if (ctx->Extensions.EXT_sRGB) {
Eric Anholt4d231572019-07-01 15:43:19 -07004442 *params = (_mesa_is_format_srgb(att->Renderbuffer->Format) ?
4443 GL_SRGB : GL_LINEAR);
Marek Olšák81ae8c62011-01-23 13:26:43 +01004444 }
4445 else {
4446 /* According to ARB_framebuffer_sRGB, we should return LINEAR
4447 * if the sRGB conversion is unsupported. */
4448 *params = GL_LINEAR;
4449 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004450 }
4451 return;
4452 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Brian Paulc1377ed2014-03-22 10:31:58 -06004453 if ((ctx->API != API_OPENGL_COMPAT ||
4454 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004455 && ctx->API != API_OPENGL_CORE
4456 && !_mesa_is_gles3(ctx)) {
4457 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004458 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004459 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004460 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004461 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004462 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004463 else {
Mark Mueller71fe9432014-01-04 14:11:43 -08004464 mesa_format format = att->Renderbuffer->Format;
Ian Romanickd7475c72013-01-18 17:25:57 -08004465
4466 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
4467 * 3.0.1 spec says:
4468 *
4469 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
4470 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
4471 * generate an INVALID_OPERATION error.
4472 */
Brian Paulc1377ed2014-03-22 10:31:58 -06004473 if (_mesa_is_gles3(ctx) &&
4474 attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Ian Romanickd7475c72013-01-18 17:25:57 -08004475 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004476 "%s(cannot query "
Ian Romanickd7475c72013-01-18 17:25:57 -08004477 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004478 "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
Ian Romanickd7475c72013-01-18 17:25:57 -08004479 return;
4480 }
4481
Mark Mueller50a01d22014-01-20 19:08:54 -08004482 if (format == MESA_FORMAT_S_UINT8) {
Brian Paul45e76d22009-10-08 20:27:27 -06004483 /* special cases */
4484 *params = GL_INDEX;
4485 }
Mark Muellereeed49f2014-01-26 15:12:56 -08004486 else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
Marek Olšák11652802011-06-01 15:48:51 +02004487 /* depends on the attachment parameter */
4488 if (attachment == GL_STENCIL_ATTACHMENT) {
4489 *params = GL_INDEX;
4490 }
4491 else {
4492 *params = GL_FLOAT;
4493 }
4494 }
Brian Paul45e76d22009-10-08 20:27:27 -06004495 else {
4496 *params = _mesa_get_format_datatype(format);
4497 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004498 }
4499 return;
4500 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004501 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004502 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004503 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004504 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004505 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Brian Paulc1377ed2014-03-22 10:31:58 -06004506 if ((!_mesa_is_desktop_gl(ctx) ||
4507 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004508 && !_mesa_is_gles3(ctx)) {
4509 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004510 }
Brian Paul45e76d22009-10-08 20:27:27 -06004511 else if (att->Texture) {
4512 const struct gl_texture_image *texImage =
Brian Paulf262ed62015-01-02 16:56:12 -07004513 _mesa_select_tex_image(att->Texture, att->Texture->Target,
Brian Paul45e76d22009-10-08 20:27:27 -06004514 att->TextureLevel);
4515 if (texImage) {
4516 *params = get_component_bits(pname, texImage->_BaseFormat,
4517 texImage->TexFormat);
4518 }
4519 else {
4520 *params = 0;
4521 }
4522 }
4523 else if (att->Renderbuffer) {
4524 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
4525 att->Renderbuffer->Format);
4526 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004527 else {
Timothy Arceri786b9ad2017-05-05 15:39:15 +10004528 assert(att->Type == GL_NONE);
4529 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4530 _mesa_enum_to_string(pname));
Brian Paul1bc59bf2009-01-22 15:07:34 -07004531 }
4532 return;
Paul Berryec79c052013-11-19 21:17:19 -08004533 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
4534 if (!_mesa_has_geometry_shaders(ctx)) {
4535 goto invalid_pname_enum;
4536 } else if (att->Type == GL_TEXTURE) {
4537 *params = att->Layered;
4538 } else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004539 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004540 _mesa_enum_to_string(pname));
Paul Berryec79c052013-11-19 21:17:19 -08004541 } else {
4542 goto invalid_pname_enum;
4543 }
4544 return;
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08004545 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4546 if (!ctx->Extensions.EXT_multisampled_render_to_texture) {
4547 goto invalid_pname_enum;
4548 } else if (att->Type == GL_TEXTURE) {
4549 *params = att->NumSamples;
4550 } else if (att->Type == GL_NONE) {
4551 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4552 _mesa_enum_to_string(pname));
4553 } else {
4554 goto invalid_pname_enum;
4555 }
4556 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004557 default:
Ian Romanick0cdaa472012-07-27 07:47:28 -07004558 goto invalid_pname_enum;
Brian Paulddc82ee2005-02-05 19:56:45 +00004559 }
Ian Romanick0cdaa472012-07-27 07:47:28 -07004560
4561 return;
4562
4563invalid_pname_enum:
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004564 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004565 _mesa_enum_to_string(pname));
Ian Romanick0cdaa472012-07-27 07:47:28 -07004566 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004567}
4568
4569
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004570void GLAPIENTRY
4571_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
4572 GLenum pname, GLint *params)
4573{
4574 GET_CURRENT_CONTEXT(ctx);
4575 struct gl_framebuffer *buffer;
4576
4577 buffer = get_framebuffer_target(ctx, target);
4578 if (!buffer) {
4579 _mesa_error(ctx, GL_INVALID_ENUM,
4580 "glGetFramebufferAttachmentParameteriv(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004581 _mesa_enum_to_string(target));
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004582 return;
4583 }
4584
Timothy Arceri8b006302017-05-05 15:21:22 +10004585 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4586 params,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004587 "glGetFramebufferAttachmentParameteriv");
4588}
4589
4590
4591void GLAPIENTRY
4592_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
4593 GLenum attachment,
4594 GLenum pname, GLint *params)
4595{
4596 GET_CURRENT_CONTEXT(ctx);
4597 struct gl_framebuffer *buffer;
4598
4599 if (framebuffer) {
4600 buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4601 "glGetNamedFramebufferAttachmentParameteriv");
4602 if (!buffer)
4603 return;
4604 }
4605 else {
4606 /*
4607 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4608 * 4.5 core spec (30.10.2014, PDF page 314):
4609 * "If framebuffer is zero, then the default draw framebuffer is
4610 * queried."
4611 */
4612 buffer = ctx->WinSysDrawBuffer;
4613 }
4614
Timothy Arceri8b006302017-05-05 15:21:22 +10004615 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4616 params,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004617 "glGetNamedFramebufferAttachmentParameteriv");
4618}
4619
4620
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004621void GLAPIENTRY
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004622_mesa_GetNamedFramebufferAttachmentParameterivEXT(GLuint framebuffer,
4623 GLenum attachment,
4624 GLenum pname, GLint *params)
4625{
4626 GET_CURRENT_CONTEXT(ctx);
4627 struct gl_framebuffer *buffer;
4628
4629 if (framebuffer) {
4630 buffer = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4631 "glGetNamedFramebufferAttachmentParameterivEXT");
4632 if (!buffer)
4633 return;
4634 }
4635 else {
4636 /*
4637 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4638 * 4.5 core spec (30.10.2014, PDF page 314):
4639 * "If framebuffer is zero, then the default draw framebuffer is
4640 * queried."
4641 */
4642 buffer = ctx->WinSysDrawBuffer;
4643 }
4644
4645 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4646 params,
4647 "glGetNamedFramebufferAttachmentParameterivEXT");
4648}
4649
4650
4651void GLAPIENTRY
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004652_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
4653 GLint param)
4654{
4655 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004656 struct gl_framebuffer *fb = NULL;
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004657
Rhys Perry67f40da2018-06-14 19:56:28 -06004658 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
4659 !ctx->Extensions.ARB_sample_locations) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004660 _mesa_error(ctx, GL_INVALID_OPERATION,
4661 "glNamedFramebufferParameteri("
Rhys Perry67f40da2018-06-14 19:56:28 -06004662 "neither ARB_framebuffer_no_attachments nor "
4663 "ARB_sample_locations is available)");
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004664 return;
4665 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004666
Rhys Perry67f40da2018-06-14 19:56:28 -06004667 if (framebuffer) {
4668 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4669 "glNamedFramebufferParameteri");
4670 } else {
4671 fb = ctx->WinSysDrawBuffer;
4672 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004673
4674 if (fb) {
4675 framebuffer_parameteri(ctx, fb, pname, param,
4676 "glNamedFramebufferParameteriv");
4677 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004678}
4679
4680
4681void GLAPIENTRY
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004682_mesa_GetFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4683 GLint *param)
4684{
4685 GET_CURRENT_CONTEXT(ctx);
4686 struct gl_framebuffer *fb;
4687
4688 if (framebuffer)
4689 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4690 "glGetFramebufferParameterivEXT");
4691 else
4692 fb = ctx->WinSysDrawBuffer;
4693
4694 if (fb) {
4695 /* The GL_EXT_direct_state_access says:
4696 *
4697 * The pname parameter must be one of framebuffer dependent values
4698 * listed in either table 4.nnn (namely DRAW_BUFFER, READ_BUFFER,
4699 * or DRAW_BUFFER0 through DRAW_BUFFER15).
4700 */
4701 if (pname == GL_DRAW_BUFFER) {
4702 *param = fb->ColorDrawBuffer[0];
4703
4704 }
4705 else if (pname == GL_READ_BUFFER) {
4706 *param = fb->ColorReadBuffer;
4707 }
4708 else if (GL_DRAW_BUFFER0 <= pname && pname <= GL_DRAW_BUFFER15) {
4709 *param = fb->ColorDrawBuffer[pname - GL_DRAW_BUFFER0];
4710 }
4711 else {
4712 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
4713 }
4714 }
4715}
4716
4717
4718void GLAPIENTRY
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004719_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
4720 GLint *param)
4721{
4722 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004723 struct gl_framebuffer *fb;
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004724
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004725 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4726 _mesa_error(ctx, GL_INVALID_OPERATION,
4727 "glNamedFramebufferParameteriv("
Rhys Perry67f40da2018-06-14 19:56:28 -06004728 "neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
4729 " is available)");
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004730 return;
4731 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004732
Rhys Perry67f40da2018-06-14 19:56:28 -06004733 if (framebuffer)
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004734 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4735 "glGetNamedFramebufferParameteriv");
Rhys Perry67f40da2018-06-14 19:56:28 -06004736 else
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004737 fb = ctx->WinSysDrawBuffer;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004738
4739 if (fb) {
4740 get_framebuffer_parameteriv(ctx, fb, pname, param,
4741 "glGetNamedFramebufferParameteriv");
4742 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004743}
4744
4745
Ian Romanick342be8a2012-08-13 09:27:00 -07004746static void
Laura Ekstrand65d4a202015-02-04 09:49:58 -08004747invalidate_framebuffer_storage(struct gl_context *ctx,
4748 struct gl_framebuffer *fb,
4749 GLsizei numAttachments,
Ian Romanick342be8a2012-08-13 09:27:00 -07004750 const GLenum *attachments, GLint x, GLint y,
4751 GLsizei width, GLsizei height, const char *name)
4752{
4753 int i;
Ian Romanick342be8a2012-08-13 09:27:00 -07004754
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08004755 /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
4756 * Spec (2.2.2015, PDF page 522) says:
4757 * "An INVALID_VALUE error is generated if numAttachments, width, or
4758 * height is negative."
4759 */
Ian Romanick342be8a2012-08-13 09:27:00 -07004760 if (numAttachments < 0) {
4761 _mesa_error(ctx, GL_INVALID_VALUE,
4762 "%s(numAttachments < 0)", name);
4763 return;
4764 }
4765
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08004766 if (width < 0) {
4767 _mesa_error(ctx, GL_INVALID_VALUE,
4768 "%s(width < 0)", name);
4769 return;
4770 }
4771
4772 if (height < 0) {
4773 _mesa_error(ctx, GL_INVALID_VALUE,
4774 "%s(height < 0)", name);
4775 return;
4776 }
4777
Ian Romanick342be8a2012-08-13 09:27:00 -07004778 /* The GL_ARB_invalidate_subdata spec says:
4779 *
4780 * "If an attachment is specified that does not exist in the
4781 * framebuffer bound to <target>, it is ignored."
4782 *
4783 * It also says:
4784 *
4785 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
4786 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
4787 * INVALID_OPERATION is generated."
4788 *
4789 * No mention is made of GL_AUXi being out of range. Therefore, we allow
4790 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
4791 * set of retrictions).
4792 */
4793 for (i = 0; i < numAttachments; i++) {
4794 if (_mesa_is_winsys_fbo(fb)) {
4795 switch (attachments[i]) {
4796 case GL_ACCUM:
4797 case GL_AUX0:
4798 case GL_AUX1:
4799 case GL_AUX2:
4800 case GL_AUX3:
4801 /* Accumulation buffers and auxilary buffers were removed in
4802 * OpenGL 3.1, and they never existed in OpenGL ES.
4803 */
Paul Berrydbd61352012-11-27 12:26:51 -08004804 if (ctx->API != API_OPENGL_COMPAT)
Ian Romanick342be8a2012-08-13 09:27:00 -07004805 goto invalid_enum;
4806 break;
4807 case GL_COLOR:
4808 case GL_DEPTH:
4809 case GL_STENCIL:
4810 break;
4811 case GL_BACK_LEFT:
4812 case GL_BACK_RIGHT:
4813 case GL_FRONT_LEFT:
4814 case GL_FRONT_RIGHT:
4815 if (!_mesa_is_desktop_gl(ctx))
4816 goto invalid_enum;
4817 break;
4818 default:
4819 goto invalid_enum;
4820 }
4821 } else {
4822 switch (attachments[i]) {
4823 case GL_DEPTH_ATTACHMENT:
4824 case GL_STENCIL_ATTACHMENT:
4825 break;
Eduardo Lima Mitev242ad322014-11-18 16:28:18 +01004826 case GL_DEPTH_STENCIL_ATTACHMENT:
4827 /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
4828 * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
4829 * extension does not make this attachment point valid on ES 2.0.
4830 */
4831 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
4832 break;
4833 /* fallthrough */
Ian Romanick342be8a2012-08-13 09:27:00 -07004834 case GL_COLOR_ATTACHMENT0:
4835 case GL_COLOR_ATTACHMENT1:
4836 case GL_COLOR_ATTACHMENT2:
4837 case GL_COLOR_ATTACHMENT3:
4838 case GL_COLOR_ATTACHMENT4:
4839 case GL_COLOR_ATTACHMENT5:
4840 case GL_COLOR_ATTACHMENT6:
4841 case GL_COLOR_ATTACHMENT7:
4842 case GL_COLOR_ATTACHMENT8:
4843 case GL_COLOR_ATTACHMENT9:
4844 case GL_COLOR_ATTACHMENT10:
4845 case GL_COLOR_ATTACHMENT11:
4846 case GL_COLOR_ATTACHMENT12:
4847 case GL_COLOR_ATTACHMENT13:
4848 case GL_COLOR_ATTACHMENT14:
4849 case GL_COLOR_ATTACHMENT15: {
Brian Paul859c3872012-11-04 16:43:44 -07004850 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
Ian Romanick342be8a2012-08-13 09:27:00 -07004851 if (k >= ctx->Const.MaxColorAttachments) {
4852 _mesa_error(ctx, GL_INVALID_OPERATION,
4853 "%s(attachment >= max. color attachments)", name);
4854 return;
4855 }
Constantin Baranov53904c62013-10-13 01:17:15 +03004856 break;
Ian Romanick342be8a2012-08-13 09:27:00 -07004857 }
4858 default:
4859 goto invalid_enum;
4860 }
4861 }
4862 }
4863
4864 /* We don't actually do anything for this yet. Just return after
4865 * validating the parameters and generating the required errors.
4866 */
4867 return;
4868
4869invalid_enum:
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08004870 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004871 _mesa_enum_to_string(attachments[i]));
Ian Romanick342be8a2012-08-13 09:27:00 -07004872 return;
4873}
4874
Rob Clark0c42b5f2018-11-01 11:10:46 -04004875static struct gl_renderbuffer_attachment *
4876get_fb_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
4877 const GLenum attachment)
4878{
4879 switch (attachment) {
4880 case GL_COLOR:
4881 return &fb->Attachment[BUFFER_BACK_LEFT];
4882 case GL_COLOR_ATTACHMENT0:
4883 case GL_COLOR_ATTACHMENT1:
4884 case GL_COLOR_ATTACHMENT2:
4885 case GL_COLOR_ATTACHMENT3:
4886 case GL_COLOR_ATTACHMENT4:
4887 case GL_COLOR_ATTACHMENT5:
4888 case GL_COLOR_ATTACHMENT6:
4889 case GL_COLOR_ATTACHMENT7:
4890 case GL_COLOR_ATTACHMENT8:
4891 case GL_COLOR_ATTACHMENT9:
4892 case GL_COLOR_ATTACHMENT10:
4893 case GL_COLOR_ATTACHMENT11:
4894 case GL_COLOR_ATTACHMENT12:
4895 case GL_COLOR_ATTACHMENT13:
4896 case GL_COLOR_ATTACHMENT14:
Tapani Pälli9762a9f2019-02-14 09:02:31 +02004897 case GL_COLOR_ATTACHMENT15: {
4898 const unsigned i = attachment - GL_COLOR_ATTACHMENT0;
4899 if (i >= ctx->Const.MaxColorAttachments)
4900 return NULL;
4901 return &fb->Attachment[BUFFER_COLOR0 + i];
4902 }
Rob Clark0c42b5f2018-11-01 11:10:46 -04004903 case GL_DEPTH:
4904 case GL_DEPTH_ATTACHMENT:
4905 case GL_DEPTH_STENCIL_ATTACHMENT:
4906 return &fb->Attachment[BUFFER_DEPTH];
4907 case GL_STENCIL:
4908 case GL_STENCIL_ATTACHMENT:
4909 return &fb->Attachment[BUFFER_STENCIL];
4910 default:
4911 return NULL;
4912 }
4913}
4914
4915static void
4916discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
4917 GLsizei numAttachments, const GLenum *attachments)
4918{
4919 if (!ctx->Driver.DiscardFramebuffer)
4920 return;
4921
4922 for (int i = 0; i < numAttachments; i++) {
4923 struct gl_renderbuffer_attachment *att =
4924 get_fb_attachment(ctx, fb, attachments[i]);
4925
4926 if (!att)
4927 continue;
4928
Eric Anholtdb2ae512019-01-30 09:33:53 -08004929 /* If we're asked to invalidate just depth or just stencil, but the
4930 * attachment is packed depth/stencil, then we can only use
4931 * Driver.DiscardFramebuffer if the attachments list includes both depth
4932 * and stencil and they both point at the same renderbuffer.
4933 */
4934 if ((attachments[i] == GL_DEPTH_ATTACHMENT ||
4935 attachments[i] == GL_STENCIL_ATTACHMENT) &&
4936 (!att->Renderbuffer ||
4937 att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL)) {
4938 GLenum other_format = (attachments[i] == GL_DEPTH_ATTACHMENT ?
4939 GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
4940 bool has_both = false;
4941 for (int j = 0; j < numAttachments; j++) {
4942 if (attachments[j] == other_format)
4943 has_both = true;
4944 break;
4945 }
4946
4947 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer !=
4948 fb->Attachment[BUFFER_STENCIL].Renderbuffer || !has_both)
4949 continue;
4950 }
4951
Rob Clark0c42b5f2018-11-01 11:10:46 -04004952 ctx->Driver.DiscardFramebuffer(ctx, fb, att);
4953 }
4954}
Brian Paulc1377ed2014-03-22 10:31:58 -06004955
Ian Romanick342be8a2012-08-13 09:27:00 -07004956void GLAPIENTRY
Samuel Pitoisetc8864922017-07-18 18:02:51 +02004957_mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
4958 const GLenum *attachments, GLint x,
4959 GLint y, GLsizei width, GLsizei height)
4960{
4961 /* no-op */
4962}
4963
4964
4965void GLAPIENTRY
Ian Romanick342be8a2012-08-13 09:27:00 -07004966_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
4967 const GLenum *attachments, GLint x, GLint y,
4968 GLsizei width, GLsizei height)
4969{
Laura Ekstrand65d4a202015-02-04 09:49:58 -08004970 struct gl_framebuffer *fb;
4971 GET_CURRENT_CONTEXT(ctx);
4972
4973 fb = get_framebuffer_target(ctx, target);
4974 if (!fb) {
4975 _mesa_error(ctx, GL_INVALID_ENUM,
4976 "glInvalidateSubFramebuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004977 _mesa_enum_to_string(target));
Laura Ekstrand65d4a202015-02-04 09:49:58 -08004978 return;
4979 }
4980
4981 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
Ian Romanick342be8a2012-08-13 09:27:00 -07004982 x, y, width, height,
4983 "glInvalidateSubFramebuffer");
4984}
4985
Brian Paulc1377ed2014-03-22 10:31:58 -06004986
Ian Romanick342be8a2012-08-13 09:27:00 -07004987void GLAPIENTRY
Laura Ekstrandd890fc72015-02-04 14:21:48 -08004988_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
4989 GLsizei numAttachments,
4990 const GLenum *attachments,
4991 GLint x, GLint y,
4992 GLsizei width, GLsizei height)
4993{
4994 struct gl_framebuffer *fb;
4995 GET_CURRENT_CONTEXT(ctx);
4996
4997 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
4998 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
4999 * default draw framebuffer is affected."
5000 */
5001 if (framebuffer) {
5002 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5003 "glInvalidateNamedFramebufferSubData");
5004 if (!fb)
5005 return;
5006 }
5007 else
5008 fb = ctx->WinSysDrawBuffer;
5009
5010 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5011 x, y, width, height,
5012 "glInvalidateNamedFramebufferSubData");
5013}
5014
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005015void GLAPIENTRY
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005016_mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5017 const GLenum *attachments)
5018{
Rob Clark0c42b5f2018-11-01 11:10:46 -04005019 struct gl_framebuffer *fb;
5020 GET_CURRENT_CONTEXT(ctx);
5021
5022 fb = get_framebuffer_target(ctx, target);
5023 if (!fb)
5024 return;
5025
5026 discard_framebuffer(ctx, fb, numAttachments, attachments);
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005027}
5028
5029
5030void GLAPIENTRY
Ian Romanick342be8a2012-08-13 09:27:00 -07005031_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
5032 const GLenum *attachments)
5033{
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005034 struct gl_framebuffer *fb;
5035 GET_CURRENT_CONTEXT(ctx);
5036
5037 fb = get_framebuffer_target(ctx, target);
5038 if (!fb) {
5039 _mesa_error(ctx, GL_INVALID_ENUM,
5040 "glInvalidateFramebuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005041 _mesa_enum_to_string(target));
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005042 return;
5043 }
5044
Ian Romanick342be8a2012-08-13 09:27:00 -07005045 /* The GL_ARB_invalidate_subdata spec says:
5046 *
5047 * "The command
5048 *
5049 * void InvalidateFramebuffer(enum target,
5050 * sizei numAttachments,
5051 * const enum *attachments);
5052 *
5053 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5054 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5055 * <MAX_VIEWPORT_DIMS[1]> respectively."
5056 */
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005057 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
Brian Paulc1377ed2014-03-22 10:31:58 -06005058 0, 0,
Samuel Iglesias Gonsálvezaa849d92016-03-01 12:02:27 +01005059 ctx->Const.MaxViewportWidth,
5060 ctx->Const.MaxViewportHeight,
Ian Romanick342be8a2012-08-13 09:27:00 -07005061 "glInvalidateFramebuffer");
Rob Clark0c42b5f2018-11-01 11:10:46 -04005062
5063 discard_framebuffer(ctx, fb, numAttachments, attachments);
Ian Romanick342be8a2012-08-13 09:27:00 -07005064}
Tapani Pälli413941e2013-02-18 09:12:27 +02005065
Brian Paulc1377ed2014-03-22 10:31:58 -06005066
Tapani Pälli413941e2013-02-18 09:12:27 +02005067void GLAPIENTRY
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005068_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
5069 GLsizei numAttachments,
5070 const GLenum *attachments)
5071{
5072 struct gl_framebuffer *fb;
5073 GET_CURRENT_CONTEXT(ctx);
5074
5075 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5076 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5077 * default draw framebuffer is affected."
5078 */
5079 if (framebuffer) {
5080 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5081 "glInvalidateNamedFramebufferData");
5082 if (!fb)
5083 return;
5084 }
5085 else
5086 fb = ctx->WinSysDrawBuffer;
5087
5088 /* The GL_ARB_invalidate_subdata spec says:
5089 *
5090 * "The command
5091 *
5092 * void InvalidateFramebuffer(enum target,
5093 * sizei numAttachments,
5094 * const enum *attachments);
5095 *
5096 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5097 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5098 * <MAX_VIEWPORT_DIMS[1]> respectively."
5099 */
5100 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5101 0, 0,
Samuel Iglesias Gonsálvezaa849d92016-03-01 12:02:27 +01005102 ctx->Const.MaxViewportWidth,
5103 ctx->Const.MaxViewportHeight,
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005104 "glInvalidateNamedFramebufferData");
5105}
5106
5107
5108void GLAPIENTRY
Tapani Pälli413941e2013-02-18 09:12:27 +02005109_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
5110 const GLenum *attachments)
5111{
5112 struct gl_framebuffer *fb;
5113 GLint i;
5114
5115 GET_CURRENT_CONTEXT(ctx);
5116
5117 fb = get_framebuffer_target(ctx, target);
5118 if (!fb) {
5119 _mesa_error(ctx, GL_INVALID_ENUM,
5120 "glDiscardFramebufferEXT(target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005121 _mesa_enum_to_string(target));
Tapani Pälli413941e2013-02-18 09:12:27 +02005122 return;
5123 }
5124
5125 if (numAttachments < 0) {
5126 _mesa_error(ctx, GL_INVALID_VALUE,
5127 "glDiscardFramebufferEXT(numAttachments < 0)");
5128 return;
5129 }
5130
5131 for (i = 0; i < numAttachments; i++) {
5132 switch (attachments[i]) {
5133 case GL_COLOR:
5134 case GL_DEPTH:
5135 case GL_STENCIL:
5136 if (_mesa_is_user_fbo(fb))
5137 goto invalid_enum;
5138 break;
5139 case GL_COLOR_ATTACHMENT0:
5140 case GL_DEPTH_ATTACHMENT:
5141 case GL_STENCIL_ATTACHMENT:
5142 if (_mesa_is_winsys_fbo(fb))
5143 goto invalid_enum;
5144 break;
5145 default:
5146 goto invalid_enum;
5147 }
5148 }
5149
Rob Clark0c42b5f2018-11-01 11:10:46 -04005150 discard_framebuffer(ctx, fb, numAttachments, attachments);
Tapani Pälli413941e2013-02-18 09:12:27 +02005151
5152 return;
5153
5154invalid_enum:
5155 _mesa_error(ctx, GL_INVALID_ENUM,
5156 "glDiscardFramebufferEXT(attachment %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005157 _mesa_enum_to_string(attachments[i]));
Tapani Pälli413941e2013-02-18 09:12:27 +02005158}
Rhys Perry67f40da2018-06-14 19:56:28 -06005159
5160static void
5161sample_locations(struct gl_context *ctx, struct gl_framebuffer *fb,
5162 GLuint start, GLsizei count, const GLfloat *v, bool no_error,
5163 const char *name)
5164{
5165 GLsizei i;
5166
5167 if (!no_error) {
5168 if (!ctx->Extensions.ARB_sample_locations) {
5169 _mesa_error(ctx, GL_INVALID_OPERATION,
5170 "%s not supported "
5171 "(ARB_sample_locations not available)", name);
5172 return;
5173 }
5174
5175 if (start + count > MAX_SAMPLE_LOCATION_TABLE_SIZE) {
5176 _mesa_error(ctx, GL_INVALID_VALUE,
5177 "%s(start+size > sample location table size)", name);
5178 return;
5179 }
5180 }
5181
5182 if (!fb->SampleLocationTable) {
5183 size_t size = MAX_SAMPLE_LOCATION_TABLE_SIZE * 2 * sizeof(GLfloat);
5184 fb->SampleLocationTable = malloc(size);
Eric Engestrom9a4bd6b2018-06-18 11:39:05 +01005185 if (!fb->SampleLocationTable) {
Rhys Perry67f40da2018-06-14 19:56:28 -06005186 _mesa_error(ctx, GL_OUT_OF_MEMORY,
5187 "Cannot allocate sample location table");
Eric Engestrom9a4bd6b2018-06-18 11:39:05 +01005188 return;
5189 }
Rhys Perry67f40da2018-06-14 19:56:28 -06005190 for (i = 0; i < MAX_SAMPLE_LOCATION_TABLE_SIZE * 2; i++)
5191 fb->SampleLocationTable[i] = 0.5f;
5192 }
5193
5194 for (i = 0; i < count * 2; i++) {
5195 /* The ARB_sample_locations spec says:
5196 *
5197 * Sample locations outside of [0,1] result in undefined
5198 * behavior.
5199 *
5200 * To simplify driver implementations, we choose to clamp to
5201 * [0,1] and change NaN into 0.5.
5202 */
5203 if (isnan(v[i]) || v[i] < 0.0f || v[i] > 1.0f) {
5204 static GLuint msg_id = 0;
5205 static const char* msg = "Invalid sample location specified";
5206 _mesa_debug_get_id(&msg_id);
5207
5208 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_UNDEFINED,
5209 msg_id, MESA_DEBUG_SEVERITY_HIGH, strlen(msg), msg);
5210 }
5211
5212 if (isnan(v[i]))
5213 fb->SampleLocationTable[start * 2 + i] = 0.5f;
5214 else
5215 fb->SampleLocationTable[start * 2 + i] = CLAMP(v[i], 0.0f, 1.0f);
5216 }
5217
5218 if (fb == ctx->DrawBuffer)
5219 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
5220}
5221
5222void GLAPIENTRY
5223_mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
5224 GLsizei count, const GLfloat *v)
5225{
5226 struct gl_framebuffer *fb;
5227
5228 GET_CURRENT_CONTEXT(ctx);
5229
5230 fb = get_framebuffer_target(ctx, target);
5231 if (!fb) {
5232 _mesa_error(ctx, GL_INVALID_ENUM,
5233 "glFramebufferSampleLocationsfvARB(target %s)",
5234 _mesa_enum_to_string(target));
5235 return;
5236 }
5237
5238 sample_locations(ctx, fb, start, count, v, false,
5239 "glFramebufferSampleLocationsfvARB");
5240}
5241
5242void GLAPIENTRY
5243_mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
5244 GLsizei count, const GLfloat *v)
5245{
5246 struct gl_framebuffer *fb;
5247
5248 GET_CURRENT_CONTEXT(ctx);
5249
5250 if (framebuffer) {
5251 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5252 "glNamedFramebufferSampleLocationsfvARB");
5253 if (!fb)
5254 return;
5255 }
5256 else
5257 fb = ctx->WinSysDrawBuffer;
5258
5259 sample_locations(ctx, fb, start, count, v, false,
5260 "glNamedFramebufferSampleLocationsfvARB");
5261}
5262
5263void GLAPIENTRY
5264_mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
5265 GLsizei count, const GLfloat *v)
5266{
5267 GET_CURRENT_CONTEXT(ctx);
5268 sample_locations(ctx, get_framebuffer_target(ctx, target), start,
5269 count, v, true, "glFramebufferSampleLocationsfvARB");
5270}
5271
5272void GLAPIENTRY
5273_mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
5274 GLuint start, GLsizei count,
5275 const GLfloat *v)
5276{
5277 GET_CURRENT_CONTEXT(ctx);
5278 sample_locations(ctx, _mesa_lookup_framebuffer(ctx, framebuffer), start,
5279 count, v, true, "glNamedFramebufferSampleLocationsfvARB");
5280}
5281
5282void GLAPIENTRY
5283_mesa_EvaluateDepthValuesARB(void)
5284{
5285 GET_CURRENT_CONTEXT(ctx);
5286
5287 if (!ctx->Extensions.ARB_sample_locations) {
5288 _mesa_error(ctx, GL_INVALID_OPERATION,
5289 "EvaluateDepthValuesARB not supported (neither "
5290 "ARB_sample_locations nor NV_sample_locations is available)");
5291 return;
5292 }
5293
5294 if (ctx->Driver.EvaluateDepthValues)
5295 ctx->Driver.EvaluateDepthValues(ctx);
5296}