blob: c8735d0459ac297f1b06273a5aa26562605cf8b3 [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);
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +0200177 _mesa_HashInsert(ctx->Shared->FrameBuffers, id, fb);
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +0200178 }
179 /* Name doesn't exist */
180 else if (!fb) {
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +0200181 fb = ctx->Driver.NewFramebuffer(ctx, id);
182 if (!fb) {
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +0200183 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
184 return NULL;
185 }
Danylo Piliaiev40255832020-05-22 13:36:31 +0300186 _mesa_HashInsert(ctx->Shared->FrameBuffers, id, fb);
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +0200187 }
Brian Paul463642c2005-02-08 02:06:00 +0000188 return fb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000189}
190
191
192/**
Laura Ekstrand6d8eff42015-01-22 10:23:35 -0800193 * A convenience function for direct state access that throws
194 * GL_INVALID_OPERATION if the framebuffer doesn't exist.
195 */
196struct gl_framebuffer *
197_mesa_lookup_framebuffer_err(struct gl_context *ctx, GLuint id,
198 const char *func)
199{
200 struct gl_framebuffer *fb;
201
202 fb = _mesa_lookup_framebuffer(ctx, id);
203 if (!fb || fb == &DummyFramebuffer) {
204 _mesa_error(ctx, GL_INVALID_OPERATION,
205 "%s(non-existent framebuffer %u)", func, id);
206 return NULL;
207 }
208
209 return fb;
210}
211
212
213/**
Brian Paul72966362009-01-21 16:28:38 -0700214 * Mark the given framebuffer as invalid. This will force the
215 * test for framebuffer completeness to be done before the framebuffer
216 * is used.
217 */
218static void
219invalidate_framebuffer(struct gl_framebuffer *fb)
220{
221 fb->_Status = 0; /* "indeterminate" */
222}
223
224
225/**
Brian Paulc6991432011-02-28 18:24:25 -0700226 * Return the gl_framebuffer object which corresponds to the given
227 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
228 * Check support for GL_EXT_framebuffer_blit to determine if certain
229 * targets are legal.
230 * \return gl_framebuffer pointer or NULL if target is illegal
231 */
232static struct gl_framebuffer *
233get_framebuffer_target(struct gl_context *ctx, GLenum target)
234{
Ian Romanicka6729732013-11-13 13:30:37 -0800235 bool have_fb_blit = _mesa_is_gles3(ctx) || _mesa_is_desktop_gl(ctx);
Brian Paulc6991432011-02-28 18:24:25 -0700236 switch (target) {
237 case GL_DRAW_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800238 return have_fb_blit ? ctx->DrawBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700239 case GL_READ_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800240 return have_fb_blit ? ctx->ReadBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700241 case GL_FRAMEBUFFER_EXT:
242 return ctx->DrawBuffer;
243 default:
244 return NULL;
245 }
246}
247
248
249/**
Brian Pauld9468c92005-02-10 16:08:07 +0000250 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
Brian Paul2c6f9112005-02-24 05:47:06 +0000251 * gl_renderbuffer_attachment object.
Brian Paul61ec2052010-06-22 08:37:44 -0600252 * This function is only used for user-created FB objects, not the
253 * default / window-system FB object.
Brian Paul30590072009-01-21 11:06:11 -0700254 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
255 * the depth buffer attachment point.
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200256 * Returns if the attachment is a GL_COLOR_ATTACHMENTm_EXT on
257 * is_color_attachment, because several callers would return different errors
258 * if they don't find the attachment.
Brian Pauld9468c92005-02-10 16:08:07 +0000259 */
Brian Paul94512812014-02-01 08:58:43 -0700260static struct gl_renderbuffer_attachment *
261get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200262 GLenum attachment, bool *is_color_attachment)
Brian Paul3deaa012005-02-07 05:08:24 +0000263{
264 GLuint i;
265
Brian Paul36ede892012-01-12 09:17:23 -0700266 assert(_mesa_is_user_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600267
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200268 if (is_color_attachment)
269 *is_color_attachment = false;
270
Brian Paul3deaa012005-02-07 05:08:24 +0000271 switch (attachment) {
272 case GL_COLOR_ATTACHMENT0_EXT:
273 case GL_COLOR_ATTACHMENT1_EXT:
274 case GL_COLOR_ATTACHMENT2_EXT:
275 case GL_COLOR_ATTACHMENT3_EXT:
276 case GL_COLOR_ATTACHMENT4_EXT:
277 case GL_COLOR_ATTACHMENT5_EXT:
278 case GL_COLOR_ATTACHMENT6_EXT:
279 case GL_COLOR_ATTACHMENT7_EXT:
280 case GL_COLOR_ATTACHMENT8_EXT:
281 case GL_COLOR_ATTACHMENT9_EXT:
282 case GL_COLOR_ATTACHMENT10_EXT:
283 case GL_COLOR_ATTACHMENT11_EXT:
284 case GL_COLOR_ATTACHMENT12_EXT:
285 case GL_COLOR_ATTACHMENT13_EXT:
286 case GL_COLOR_ATTACHMENT14_EXT:
287 case GL_COLOR_ATTACHMENT15_EXT:
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200288 if (is_color_attachment)
289 *is_color_attachment = true;
Ian Romanick2e3a4ab2011-10-02 15:03:07 -0700290 /* Only OpenGL ES 1.x forbids color attachments other than
291 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the
292 * hardware is used.
293 */
Brian Paul3deaa012005-02-07 05:08:24 +0000294 i = attachment - GL_COLOR_ATTACHMENT0_EXT;
Ian Romanick7e4cb322011-10-02 14:50:21 -0700295 if (i >= ctx->Const.MaxColorAttachments
Martin Peres7bd8b482015-02-12 17:54:43 +0200296 || (i > 0 && ctx->API == API_OPENGLES)) {
297 return NULL;
Brian Paul3deaa012005-02-07 05:08:24 +0000298 }
Marcin Ślusarzc3a251f2020-07-24 19:51:30 +0200299 assert(BUFFER_COLOR0 + i < ARRAY_SIZE(fb->Attachment));
Brian Paule4b23562005-05-04 20:11:35 +0000300 return &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paul30590072009-01-21 11:06:11 -0700301 case GL_DEPTH_STENCIL_ATTACHMENT:
Matt Turnerec8ee912012-11-15 22:13:48 -0800302 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
Martin Peres7bd8b482015-02-12 17:54:43 +0200303 return NULL;
Brian Paul30590072009-01-21 11:06:11 -0700304 /* fall-through */
Brian Paul3deaa012005-02-07 05:08:24 +0000305 case GL_DEPTH_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000306 return &fb->Attachment[BUFFER_DEPTH];
Brian Paul3deaa012005-02-07 05:08:24 +0000307 case GL_STENCIL_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000308 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul61ec2052010-06-22 08:37:44 -0600309 default:
310 return NULL;
311 }
312}
313
314
315/**
316 * As above, but only used for getting attachments of the default /
317 * window-system framebuffer (not user-created framebuffer objects).
318 */
319static struct gl_renderbuffer_attachment *
Timothy Arcerie6187612017-05-05 15:02:20 +1000320get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
321 GLenum attachment)
Brian Paul61ec2052010-06-22 08:37:44 -0600322{
Brian Paul36ede892012-01-12 09:17:23 -0700323 assert(_mesa_is_winsys_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600324
Kenneth Graunkee6ca6e52019-10-14 10:07:30 -0700325 attachment = _mesa_back_to_front_if_single_buffered(fb, attachment);
326
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800327 if (_mesa_is_gles3(ctx)) {
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800328 switch (attachment) {
329 case GL_BACK:
330 /* Since there is no stereo rendering in ES 3.0, only return the
331 * LEFT bits.
332 */
Kenneth Graunkee6ca6e52019-10-14 10:07:30 -0700333 return &fb->Attachment[BUFFER_BACK_LEFT];
334 case GL_FRONT:
335 /* We might get this if back_to_front triggers above */
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800336 return &fb->Attachment[BUFFER_FRONT_LEFT];
337 case GL_DEPTH:
Timothy Arceria754e4c2017-05-05 15:09:37 +1000338 return &fb->Attachment[BUFFER_DEPTH];
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800339 case GL_STENCIL:
340 return &fb->Attachment[BUFFER_STENCIL];
Kenneth Graunkee6ca6e52019-10-14 10:07:30 -0700341 default:
342 unreachable("invalid attachment");
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800343 }
344 }
345
Brian Paul61ec2052010-06-22 08:37:44 -0600346 switch (attachment) {
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400347 case GL_FRONT_LEFT:
Marek Olšákd58a3902016-09-08 21:02:29 +0200348 /* Front buffers can be allocated on the first use, but
349 * glGetFramebufferAttachmentParameteriv must work even if that
350 * allocation hasn't happened yet. In such case, use the back buffer,
351 * which should be the same.
352 */
353 if (fb->Attachment[BUFFER_FRONT_LEFT].Type == GL_NONE)
354 return &fb->Attachment[BUFFER_BACK_LEFT];
355 else
356 return &fb->Attachment[BUFFER_FRONT_LEFT];
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400357 case GL_FRONT_RIGHT:
Marek Olšákd58a3902016-09-08 21:02:29 +0200358 /* Same as above. */
359 if (fb->Attachment[BUFFER_FRONT_RIGHT].Type == GL_NONE)
360 return &fb->Attachment[BUFFER_BACK_RIGHT];
361 else
362 return &fb->Attachment[BUFFER_FRONT_RIGHT];
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400363 case GL_BACK_LEFT:
364 return &fb->Attachment[BUFFER_BACK_LEFT];
365 case GL_BACK_RIGHT:
366 return &fb->Attachment[BUFFER_BACK_RIGHT];
Kenneth Graunke4f538c32017-10-26 11:44:09 -0700367 case GL_BACK:
368 /* The ARB_ES3_1_compatibility spec says:
369 *
370 * "Since this command can only query a single framebuffer
371 * attachment, BACK is equivalent to BACK_LEFT."
372 */
373 if (ctx->Extensions.ARB_ES3_1_compatibility)
374 return &fb->Attachment[BUFFER_BACK_LEFT];
375 return NULL;
Brian Paul61ec2052010-06-22 08:37:44 -0600376 case GL_AUX0:
377 if (fb->Visual.numAuxBuffers == 1) {
378 return &fb->Attachment[BUFFER_AUX0];
379 }
380 return NULL;
Ian Romanicka8328cc2011-10-03 12:02:18 -0700381
382 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
383 *
384 * "If the default framebuffer is bound to target, then attachment must
385 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
386 * identifying a color buffer; DEPTH, identifying the depth buffer; or
387 * STENCIL, identifying the stencil buffer."
388 *
389 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
390 * language. However, revision #33 of the ARB_framebuffer_object spec
391 * says:
392 *
393 * "If the default framebuffer is bound to <target>, then <attachment>
394 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
395 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
396 * depth buffer, or the stencil buffer, and <pname> may be
397 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
398 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
399 *
400 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
401 * from glext.h, so shipping apps should not use those values.
402 *
403 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
404 * support queries of the window system FBO.
405 */
406 case GL_DEPTH:
Brian Paul61ec2052010-06-22 08:37:44 -0600407 return &fb->Attachment[BUFFER_DEPTH];
Ian Romanicka8328cc2011-10-03 12:02:18 -0700408 case GL_STENCIL:
Brian Paul61ec2052010-06-22 08:37:44 -0600409 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul3deaa012005-02-07 05:08:24 +0000410 default:
411 return NULL;
412 }
413}
414
415
Brian Paul61ec2052010-06-22 08:37:44 -0600416
Brian Pauld9468c92005-02-10 16:08:07 +0000417/**
418 * Remove any texture or renderbuffer attached to the given attachment
419 * point. Update reference counts, etc.
420 */
Brian Paul94512812014-02-01 08:58:43 -0700421static void
422remove_attachment(struct gl_context *ctx,
423 struct gl_renderbuffer_attachment *att)
Brian Paul3deaa012005-02-07 05:08:24 +0000424{
Eric Anholtc810e672013-05-10 12:36:43 -0700425 struct gl_renderbuffer *rb = att->Renderbuffer;
426
427 /* tell driver that we're done rendering to this texture. */
428 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700429 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700430
Brian Paul3deaa012005-02-07 05:08:24 +0000431 if (att->Type == GL_TEXTURE) {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800432 assert(att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100433 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800434 assert(!att->Texture);
Brian Paul3deaa012005-02-07 05:08:24 +0000435 }
Brian Paul0e31e022005-12-01 00:25:00 +0000436 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800437 assert(!att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100438 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800439 assert(!att->Renderbuffer);
Brian Paul3deaa012005-02-07 05:08:24 +0000440 }
441 att->Type = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000442 att->Complete = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +0000443}
444
Eric Anholt749a9272013-04-22 10:38:41 -0700445/**
Ian Romanickfb497132013-07-27 12:04:20 -0700446 * Verify a couple error conditions that will lead to an incomplete FBO and
447 * may cause problems for the driver's RenderTexture path.
448 */
449static bool
450driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
451{
452 const struct gl_texture_image *const texImage =
453 att->Texture->Image[att->CubeMapFace][att->TextureLevel];
454
Marek Olšák8a101922016-05-30 16:29:18 +0200455 if (!texImage ||
456 texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
Ian Romanickfb497132013-07-27 12:04:20 -0700457 return false;
458
Ian Romanick41485fe2013-07-27 12:16:56 -0700459 if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
460 && att->Zoffset >= texImage->Height)
461 || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
462 && att->Zoffset >= texImage->Depth))
463 return false;
464
Ian Romanickfb497132013-07-27 12:04:20 -0700465 return true;
466}
467
468/**
Eric Anholt749a9272013-04-22 10:38:41 -0700469 * Create a renderbuffer which will be set up by the driver to wrap the
470 * texture image slice.
471 *
472 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
473 * to share most of their framebuffer rendering code between winsys,
474 * renderbuffer, and texture attachments.
475 *
476 * The allocated renderbuffer uses a non-zero Name so that drivers can check
477 * it for determining vertical orientation, but we use ~0 to make it fairly
478 * unambiguous with actual user (non-texture) renderbuffers.
479 */
480void
481_mesa_update_texture_renderbuffer(struct gl_context *ctx,
482 struct gl_framebuffer *fb,
483 struct gl_renderbuffer_attachment *att)
484{
485 struct gl_texture_image *texImage;
486 struct gl_renderbuffer *rb;
487
Eric Anholte98c39c2013-05-10 11:51:01 -0700488 texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
Eric Anholt749a9272013-04-22 10:38:41 -0700489
490 rb = att->Renderbuffer;
491 if (!rb) {
492 rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
493 if (!rb) {
494 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
495 return;
496 }
Timothy Arceri8046a942017-04-07 07:55:17 +1000497 att->Renderbuffer = rb;
Eric Anholt749a9272013-04-22 10:38:41 -0700498
499 /* This can't get called on a texture renderbuffer, so set it to NULL
500 * for clarity compared to user renderbuffers.
501 */
502 rb->AllocStorage = NULL;
Eric Anholtc810e672013-05-10 12:36:43 -0700503
504 rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
Eric Anholt749a9272013-04-22 10:38:41 -0700505 }
506
Ian Romanick2f9fe2d2013-07-28 13:08:27 -0700507 if (!texImage)
508 return;
509
Eric Anholt77a405d2013-04-22 11:04:21 -0700510 rb->_BaseFormat = texImage->_BaseFormat;
511 rb->Format = texImage->TexFormat;
512 rb->InternalFormat = texImage->InternalFormat;
513 rb->Width = texImage->Width2;
514 rb->Height = texImage->Height2;
Marek Olšáka3969aa2013-11-20 01:47:36 +0100515 rb->Depth = texImage->Depth2;
Eric Anholt77a405d2013-04-22 11:04:21 -0700516 rb->NumSamples = texImage->NumSamples;
Marek Olšák328c1c82018-06-11 17:24:16 -0400517 rb->NumStorageSamples = texImage->NumSamples;
Eric Anholte98c39c2013-05-10 11:51:01 -0700518 rb->TexImage = texImage;
Eric Anholt77a405d2013-04-22 11:04:21 -0700519
Ian Romanickfb497132013-07-27 12:04:20 -0700520 if (driver_RenderTexture_is_safe(att))
521 ctx->Driver.RenderTexture(ctx, fb, att);
Eric Anholt749a9272013-04-22 10:38:41 -0700522}
Brian Paul3deaa012005-02-07 05:08:24 +0000523
Brian Pauld9468c92005-02-10 16:08:07 +0000524/**
525 * Bind a texture object to an attachment point.
526 * The previous binding, if any, will be removed first.
527 */
Brian Paul94512812014-02-01 08:58:43 -0700528static void
529set_texture_attachment(struct gl_context *ctx,
530 struct gl_framebuffer *fb,
531 struct gl_renderbuffer_attachment *att,
532 struct gl_texture_object *texObj,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -0800533 GLenum texTarget, GLuint level, GLsizei samples,
534 GLuint layer, GLboolean layered)
Brian Paul3deaa012005-02-07 05:08:24 +0000535{
Eric Anholtc810e672013-05-10 12:36:43 -0700536 struct gl_renderbuffer *rb = att->Renderbuffer;
537
538 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700539 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700540
Brian Paul0e31e022005-12-01 00:25:00 +0000541 if (att->Texture == texObj) {
542 /* re-attaching same texture */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800543 assert(att->Type == GL_TEXTURE);
Brian Paul0e31e022005-12-01 00:25:00 +0000544 }
545 else {
546 /* new attachment */
Brian Paul94512812014-02-01 08:58:43 -0700547 remove_attachment(ctx, att);
Brian Paul0e31e022005-12-01 00:25:00 +0000548 att->Type = GL_TEXTURE;
Brian9e01b912007-08-13 11:29:46 +0100549 assert(!att->Texture);
550 _mesa_reference_texobj(&att->Texture, texObj);
Brian Paul0e31e022005-12-01 00:25:00 +0000551 }
Eric Anholt749a9272013-04-22 10:38:41 -0700552 invalidate_framebuffer(fb);
Brian Paul0e31e022005-12-01 00:25:00 +0000553
554 /* always update these fields */
Brian Paul3deaa012005-02-07 05:08:24 +0000555 att->TextureLevel = level;
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -0800556 att->NumSamples = samples;
Brian Paul26f1ad62009-10-23 18:15:55 -0600557 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
Laura Ekstrand085c67d2015-03-02 16:48:59 -0800558 att->Zoffset = layer;
Jordan Justena6280802013-04-18 10:08:50 -0700559 att->Layered = layered;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000560 att->Complete = GL_FALSE;
Brian Paul519b23b2006-03-20 18:51:57 +0000561
Eric Anholt749a9272013-04-22 10:38:41 -0700562 _mesa_update_texture_renderbuffer(ctx, fb, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000563}
564
565
Brian Pauld9468c92005-02-10 16:08:07 +0000566/**
567 * Bind a renderbuffer to an attachment point.
568 * The previous binding, if any, will be removed first.
569 */
Brian Paul94512812014-02-01 08:58:43 -0700570static void
571set_renderbuffer_attachment(struct gl_context *ctx,
572 struct gl_renderbuffer_attachment *att,
573 struct gl_renderbuffer *rb)
Brian Paul3deaa012005-02-07 05:08:24 +0000574{
Brian Paulea4fe662006-03-26 05:22:17 +0000575 /* XXX check if re-doing same attachment, exit early */
Brian Paul94512812014-02-01 08:58:43 -0700576 remove_attachment(ctx, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000577 att->Type = GL_RENDERBUFFER_EXT;
Brian Paul2c6f9112005-02-24 05:47:06 +0000578 att->Texture = NULL; /* just to be safe */
James Legg1581e122015-02-07 23:33:15 +0000579 att->Layered = GL_FALSE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000580 att->Complete = GL_FALSE;
Briandccd9c42007-04-02 09:56:28 -0600581 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
Brian Paul3deaa012005-02-07 05:08:24 +0000582}
583
Brian Paulddc82ee2005-02-05 19:56:45 +0000584
Brian Paulf0bbbf62005-02-09 03:50:30 +0000585/**
Brian Paule4b23562005-05-04 20:11:35 +0000586 * Fallback for ctx->Driver.FramebufferRenderbuffer()
Brian Paul84716042005-11-16 04:05:54 +0000587 * Attach a renderbuffer object to a framebuffer object.
Brian Paule4b23562005-05-04 20:11:35 +0000588 */
589void
Laura Ekstrand3d100372015-02-27 17:23:59 -0800590_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
591 struct gl_framebuffer *fb,
592 GLenum attachment,
593 struct gl_renderbuffer *rb)
Brian Paule4b23562005-05-04 20:11:35 +0000594{
Brian Paul84716042005-11-16 04:05:54 +0000595 struct gl_renderbuffer_attachment *att;
596
Timothy Arcerif0857fe2017-10-16 11:59:31 +1100597 simple_mtx_lock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +0000598
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200599 att = get_attachment(ctx, fb, attachment, NULL);
Matt Turnerbfcdb842015-02-20 20:18:47 -0800600 assert(att);
Brian Paule4b23562005-05-04 20:11:35 +0000601 if (rb) {
Brian Paul94512812014-02-01 08:58:43 -0700602 set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700603 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
604 /* do stencil attachment here (depth already done above) */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200605 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
Brian Paul30590072009-01-21 11:06:11 -0700606 assert(att);
Brian Paul94512812014-02-01 08:58:43 -0700607 set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700608 }
Marek Olšákdf818d52011-03-06 05:26:12 +0100609 rb->AttachedAnytime = GL_TRUE;
Brian Paule4b23562005-05-04 20:11:35 +0000610 }
611 else {
Brian Paul94512812014-02-01 08:58:43 -0700612 remove_attachment(ctx, att);
James Legg846c7152014-05-23 12:25:37 +0100613 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
614 /* detach stencil (depth was detached above) */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200615 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
James Legg846c7152014-05-23 12:25:37 +0100616 assert(att);
617 remove_attachment(ctx, att);
618 }
Brian Paule4b23562005-05-04 20:11:35 +0000619 }
Brian Paulea4fe662006-03-26 05:22:17 +0000620
Brian Paul72966362009-01-21 16:28:38 -0700621 invalidate_framebuffer(fb);
622
Timothy Arcerif0857fe2017-10-16 11:59:31 +1100623 simple_mtx_unlock(&fb->Mutex);
Brian Paule4b23562005-05-04 20:11:35 +0000624}
625
626
627/**
Brian Paul62c66b32011-01-24 19:38:52 -0700628 * Fallback for ctx->Driver.ValidateFramebuffer()
629 * Check if the renderbuffer's formats are supported by the software
630 * renderer.
631 * Drivers should probably override this.
632 */
633void
634_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
635{
636 gl_buffer_index buf;
637 for (buf = 0; buf < BUFFER_COUNT; buf++) {
638 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
639 if (rb) {
640 switch (rb->_BaseFormat) {
641 case GL_ALPHA:
642 case GL_LUMINANCE_ALPHA:
643 case GL_LUMINANCE:
644 case GL_INTENSITY:
Brian Pauld3015652011-01-24 19:38:52 -0700645 case GL_RED:
646 case GL_RG:
Brian Paul62c66b32011-01-24 19:38:52 -0700647 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
648 return;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200649
650 default:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200651 switch (rb->Format) {
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200652 /* XXX This list is likely incomplete. */
Mark Muellereeed49f2014-01-26 15:12:56 -0800653 case MESA_FORMAT_R9G9B9E5_FLOAT:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200654 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
655 return;
656 default:;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200657 /* render buffer format is supported by software rendering */
Marek Olšák9d7698c2011-04-26 02:18:24 +0200658 }
Brian Paul62c66b32011-01-24 19:38:52 -0700659 }
660 }
661 }
662}
663
664
665/**
Marek Olšákf8855a42013-03-14 14:22:56 +0100666 * Return true if the framebuffer has a combined depth/stencil
667 * renderbuffer attached.
668 */
669GLboolean
670_mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
671{
672 const struct gl_renderbuffer_attachment *depth =
673 &fb->Attachment[BUFFER_DEPTH];
674 const struct gl_renderbuffer_attachment *stencil =
675 &fb->Attachment[BUFFER_STENCIL];
676
677 if (depth->Type == stencil->Type) {
678 if (depth->Type == GL_RENDERBUFFER_EXT &&
679 depth->Renderbuffer == stencil->Renderbuffer)
680 return GL_TRUE;
681
682 if (depth->Type == GL_TEXTURE &&
683 depth->Texture == stencil->Texture)
684 return GL_TRUE;
685 }
686
687 return GL_FALSE;
688}
689
690
691/**
Brian Paul9f731c82009-02-17 16:47:54 -0700692 * For debug only.
693 */
694static void
695att_incomplete(const char *msg)
696{
Brian Paul93bcf782012-05-09 12:09:21 -0600697 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
698 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
699 }
Brian Paul9f731c82009-02-17 16:47:54 -0700700}
701
702
703/**
Brian Paulc26c2002009-09-15 17:20:32 -0600704 * For debug only.
705 */
706static void
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700707fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
Brian Paulc26c2002009-09-15 17:20:32 -0600708{
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700709 static GLuint msg_id;
710
Mark Janesb8a1a322018-12-06 16:35:43 -0800711 _mesa_gl_debugf(ctx, &msg_id,
712 MESA_DEBUG_SOURCE_API,
713 MESA_DEBUG_TYPE_OTHER,
714 MESA_DEBUG_SEVERITY_MEDIUM,
715 "FBO incomplete: %s [%d]\n", msg, index);
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700716
Brian Paul93bcf782012-05-09 12:09:21 -0600717 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
718 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
719 }
Brian Paulc26c2002009-09-15 17:20:32 -0600720}
721
722
Brian Paule67f6ee2010-10-22 11:38:23 -0600723/**
724 * Is the given base format a legal format for a color renderbuffer?
725 */
Eric Anholt059cca92011-01-02 17:58:07 -0800726GLboolean
727_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
Brian Paule67f6ee2010-10-22 11:38:23 -0600728{
729 switch (baseFormat) {
730 case GL_RGB:
731 case GL_RGBA:
732 return GL_TRUE;
Marek Olšák6e618532010-10-02 21:53:03 +0200733 case GL_LUMINANCE:
734 case GL_LUMINANCE_ALPHA:
735 case GL_INTENSITY:
Brian Paule67f6ee2010-10-22 11:38:23 -0600736 case GL_ALPHA:
Jordan Justencf300ea2012-12-27 12:41:10 -0800737 return ctx->API == API_OPENGL_COMPAT &&
738 ctx->Extensions.ARB_framebuffer_object;
Brian Paule67f6ee2010-10-22 11:38:23 -0600739 case GL_RED:
740 case GL_RG:
741 return ctx->Extensions.ARB_texture_rg;
742 default:
743 return GL_FALSE;
744 }
745}
746
747
748/**
Jordan Justen6c7fa722012-12-27 13:34:44 -0800749 * Is the given base format a legal format for a color renderbuffer?
750 */
751static GLboolean
Brian Paulc1377ed2014-03-22 10:31:58 -0600752is_format_color_renderable(const struct gl_context *ctx, mesa_format format,
753 GLenum internalFormat)
Jordan Justen6c7fa722012-12-27 13:34:44 -0800754{
755 const GLenum baseFormat =
756 _mesa_get_format_base_format(format);
757 GLboolean valid;
758
759 valid = _mesa_is_legal_color_format(ctx, baseFormat);
760 if (!valid || _mesa_is_desktop_gl(ctx)) {
761 return valid;
762 }
763
764 /* Reject additional cases for GLES */
765 switch (internalFormat) {
Tapani Pälli0d356cf2018-05-24 14:05:27 +0300766 case GL_R8_SNORM:
767 case GL_RG8_SNORM:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800768 case GL_RGBA8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +0300769 return _mesa_has_EXT_render_snorm(ctx);
770 case GL_R16_SNORM:
771 case GL_RG16_SNORM:
772 case GL_RGBA16_SNORM:
773 return _mesa_has_EXT_texture_norm16(ctx) &&
774 _mesa_has_EXT_render_snorm(ctx);
Jordan Justen6c7fa722012-12-27 13:34:44 -0800775 case GL_RGB32F:
776 case GL_RGB32I:
777 case GL_RGB32UI:
778 case GL_RGB16F:
779 case GL_RGB16I:
780 case GL_RGB16UI:
781 case GL_RGB8_SNORM:
782 case GL_RGB8I:
783 case GL_RGB8UI:
784 case GL_SRGB8:
Eric Anholtc16a7442017-05-01 09:28:33 -0700785 case GL_RGB10:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800786 case GL_RGB9_E5:
Marek Olšák32a33472018-11-09 16:47:46 -0500787 case GL_SR8_EXT:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800788 return GL_FALSE;
789 default:
790 break;
791 }
792
Nicolai Hähnled2b60e42017-09-27 15:25:10 +0200793 if (internalFormat != GL_RGB10_A2 &&
794 (format == MESA_FORMAT_B10G10R10A2_UNORM ||
795 format == MESA_FORMAT_B10G10R10X2_UNORM ||
796 format == MESA_FORMAT_R10G10B10A2_UNORM ||
797 format == MESA_FORMAT_R10G10B10X2_UNORM)) {
Jordan Justen6c7fa722012-12-27 13:34:44 -0800798 return GL_FALSE;
799 }
800
801 return GL_TRUE;
802}
803
804
805/**
Brian Paule67f6ee2010-10-22 11:38:23 -0600806 * Is the given base format a legal format for a depth/stencil renderbuffer?
807 */
808static GLboolean
809is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
810{
811 switch (baseFormat) {
812 case GL_DEPTH_COMPONENT:
813 case GL_DEPTH_STENCIL_EXT:
814 return GL_TRUE;
815 default:
816 return GL_FALSE;
817 }
818}
Brian Paulc26c2002009-09-15 17:20:32 -0600819
820
821/**
Brian Paulf0bbbf62005-02-09 03:50:30 +0000822 * Test if an attachment point is complete and update its Complete field.
823 * \param format if GL_COLOR, this is a color attachment point,
824 * if GL_DEPTH, this is a depth component attachment point,
825 * if GL_STENCIL, this is a stencil component attachment point.
826 */
827static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400828test_attachment_completeness(const struct gl_context *ctx, GLenum format,
Brian Paul2c6f9112005-02-24 05:47:06 +0000829 struct gl_renderbuffer_attachment *att)
Brian Paulf0bbbf62005-02-09 03:50:30 +0000830{
831 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
832
833 /* assume complete */
834 att->Complete = GL_TRUE;
835
Brian Paulf0bbbf62005-02-09 03:50:30 +0000836 /* Look for reasons why the attachment might be incomplete */
837 if (att->Type == GL_TEXTURE) {
Brian Paule4b23562005-05-04 20:11:35 +0000838 const struct gl_texture_object *texObj = att->Texture;
Brian Paulb2c3fd92017-12-04 21:27:54 -0700839 const struct gl_texture_image *texImage;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600840 GLenum baseFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000841
Brian Paule4b23562005-05-04 20:11:35 +0000842 if (!texObj) {
Brian Paul9f731c82009-02-17 16:47:54 -0700843 att_incomplete("no texobj");
Brian Paule4b23562005-05-04 20:11:35 +0000844 att->Complete = GL_FALSE;
845 return;
846 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000847
848 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
849 if (!texImage) {
Brian Paul9f731c82009-02-17 16:47:54 -0700850 att_incomplete("no teximage");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000851 att->Complete = GL_FALSE;
852 return;
853 }
854 if (texImage->Width < 1 || texImage->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700855 att_incomplete("teximage width/height=0");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000856 att->Complete = GL_FALSE;
857 return;
858 }
Ian Romanick25281fe2013-07-27 12:27:45 -0700859
860 switch (texObj->Target) {
861 case GL_TEXTURE_3D:
862 if (att->Zoffset >= texImage->Depth) {
863 att_incomplete("bad z offset");
864 att->Complete = GL_FALSE;
865 return;
866 }
867 break;
868 case GL_TEXTURE_1D_ARRAY:
869 if (att->Zoffset >= texImage->Height) {
870 att_incomplete("bad 1D-array layer");
871 att->Complete = GL_FALSE;
872 return;
873 }
874 break;
875 case GL_TEXTURE_2D_ARRAY:
876 if (att->Zoffset >= texImage->Depth) {
877 att_incomplete("bad 2D-array layer");
878 att->Complete = GL_FALSE;
879 return;
880 }
881 break;
882 case GL_TEXTURE_CUBE_MAP_ARRAY:
883 if (att->Zoffset >= texImage->Depth) {
884 att_incomplete("bad cube-array layer");
885 att->Complete = GL_FALSE;
886 return;
887 }
888 break;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000889 }
890
Ilia Mirkin68c4af12016-02-17 20:31:38 -0500891 baseFormat = texImage->_BaseFormat;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600892
Brian Paulf0bbbf62005-02-09 03:50:30 +0000893 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800894 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700895 att_incomplete("bad format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000896 att->Complete = GL_FALSE;
897 return;
898 }
Brian Paul1f7c9142009-09-30 20:28:45 -0600899 if (_mesa_is_format_compressed(texImage->TexFormat)) {
Eric Anholt957f3c82009-05-15 16:24:59 -0700900 att_incomplete("compressed internalformat");
901 att->Complete = GL_FALSE;
902 return;
903 }
Tapani Pällie3330352015-02-12 14:33:53 +0200904
905 /* OES_texture_float allows creation and use of floating point
906 * textures with GL_FLOAT, GL_HALF_FLOAT but it does not allow
907 * these textures to be used as a render target, this is done via
908 * GL_EXT_color_buffer(_half)_float with set of new sized types.
909 */
Brian Paulc7a81dc2017-10-13 16:16:48 -0600910 if (_mesa_is_gles(ctx) && (texObj->_IsFloat || texObj->_IsHalfFloat)) {
Tapani Pällie3330352015-02-12 14:33:53 +0200911 att_incomplete("bad internal format");
912 att->Complete = GL_FALSE;
913 return;
914 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000915 }
916 else if (format == GL_DEPTH) {
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600917 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000918 /* OK */
919 }
Ian Romanicka92b9e62013-11-13 14:10:34 -0800920 else if (ctx->Extensions.ARB_depth_texture &&
Ian Romanick49493222013-11-13 14:15:11 -0800921 baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000922 /* OK */
923 }
924 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000925 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700926 att_incomplete("bad depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000927 return;
928 }
929 }
930 else {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800931 assert(format == GL_STENCIL);
Ian Romanicka92b9e62013-11-13 14:10:34 -0800932 if (ctx->Extensions.ARB_depth_texture &&
Ian Romanick49493222013-11-13 14:15:11 -0800933 baseFormat == GL_DEPTH_STENCIL) {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600934 /* OK */
Dave Airlie782e71c2015-04-05 13:19:18 +1000935 } else if (ctx->Extensions.ARB_texture_stencil8 &&
936 baseFormat == GL_STENCIL_INDEX) {
937 /* OK */
938 } else {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600939 /* no such thing as stencil-only textures */
940 att_incomplete("illegal stencil texture");
941 att->Complete = GL_FALSE;
942 return;
943 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000944 }
945 }
Brian Paule4b23562005-05-04 20:11:35 +0000946 else if (att->Type == GL_RENDERBUFFER_EXT) {
Ilia Mirkin68c4af12016-02-17 20:31:38 -0500947 const GLenum baseFormat = att->Renderbuffer->_BaseFormat;
Brian Paul45e76d22009-10-08 20:27:27 -0600948
Matt Turnerbfcdb842015-02-20 20:18:47 -0800949 assert(att->Renderbuffer);
Brian Paul49918882006-03-20 15:27:55 +0000950 if (!att->Renderbuffer->InternalFormat ||
951 att->Renderbuffer->Width < 1 ||
952 att->Renderbuffer->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700953 att_incomplete("0x0 renderbuffer");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000954 att->Complete = GL_FALSE;
955 return;
956 }
957 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800958 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700959 att_incomplete("bad renderbuffer color format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000960 att->Complete = GL_FALSE;
961 return;
962 }
963 }
964 else if (format == GL_DEPTH) {
Brian Paul45e76d22009-10-08 20:27:27 -0600965 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000966 /* OK */
967 }
Ian Romanick49493222013-11-13 14:15:11 -0800968 else if (baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000969 /* OK */
970 }
971 else {
Brian Paul9f731c82009-02-17 16:47:54 -0700972 att_incomplete("bad renderbuffer depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000973 att->Complete = GL_FALSE;
974 return;
975 }
976 }
977 else {
978 assert(format == GL_STENCIL);
Ian Romanick49493222013-11-13 14:15:11 -0800979 if (baseFormat == GL_STENCIL_INDEX ||
980 baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000981 /* OK */
982 }
983 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000984 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700985 att_incomplete("bad renderbuffer stencil format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000986 return;
987 }
988 }
989 }
Brian Paule4b23562005-05-04 20:11:35 +0000990 else {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800991 assert(att->Type == GL_NONE);
Brian Paule4b23562005-05-04 20:11:35 +0000992 /* complete */
993 return;
994 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000995}
996
997
998/**
999 * Test if the given framebuffer object is complete and update its
1000 * Status field with the results.
Brian Paul3528f692009-01-22 15:13:18 -07001001 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
1002 * driver to make hardware-specific validation/completeness checks.
Brian Paule4b23562005-05-04 20:11:35 +00001003 * Also update the framebuffer's Width and Height fields if the
1004 * framebuffer is complete.
Brian Paulf0bbbf62005-02-09 03:50:30 +00001005 */
Brian Paule4b23562005-05-04 20:11:35 +00001006void
Brian Paulf9288542010-10-22 11:25:14 -06001007_mesa_test_framebuffer_completeness(struct gl_context *ctx,
1008 struct gl_framebuffer *fb)
Brian Paulf0bbbf62005-02-09 03:50:30 +00001009{
Brian Paul989edea2009-01-22 15:05:13 -07001010 GLuint numImages;
1011 GLenum intFormat = GL_NONE; /* color buffers' internal format */
1012 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
Marek Olšák459f05c2018-06-11 18:30:34 -04001013 GLint numColorSamples = -1;
1014 GLint numColorStorageSamples = -1;
1015 GLint numDepthSamples = -1;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001016 GLint fixedSampleLocations = -1;
Brian Paule4b23562005-05-04 20:11:35 +00001017 GLint i;
Brian Paul28b014e2006-04-05 03:05:17 +00001018 GLuint j;
Paul Berry532b1fe2014-01-07 06:29:47 -08001019 /* Covers max_layer_count, is_layered, and layer_tex_target */
1020 bool layer_info_valid = false;
1021 GLuint max_layer_count = 0, att_layer_count;
Brian Paul5306ee72014-01-22 10:02:28 -08001022 bool is_layered = false;
Paul Berry28af1dc2013-11-19 19:01:37 -08001023 GLenum layer_tex_target = 0;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001024 bool has_depth_attachment = false;
1025 bool has_stencil_attachment = false;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001026
Brian Paul36ede892012-01-12 09:17:23 -07001027 assert(_mesa_is_user_fbo(fb));
Brian Paulc7264412005-06-01 00:50:23 +00001028
Marek Olšáke06d6162012-08-04 13:37:03 +02001029 /* we're changing framebuffer fields here */
1030 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1031
Brian Paulf0bbbf62005-02-09 03:50:30 +00001032 numImages = 0;
Brian Paule4b23562005-05-04 20:11:35 +00001033 fb->Width = 0;
1034 fb->Height = 0;
Marek Olšák21d407c2013-03-28 01:50:21 +01001035 fb->_AllColorBuffersFixedPoint = GL_TRUE;
Marek Olšák755648c2013-03-28 01:56:01 +01001036 fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
Kevin Rogovinda819992015-06-17 13:29:50 +03001037 fb->_HasAttachments = true;
Brian Paulff00ab72016-10-10 11:29:14 -06001038 fb->_IntegerBuffers = 0;
Kenneth Graunke5b51d752018-07-21 23:40:16 -07001039 fb->_RGBBuffers = 0;
Ilia Mirkin070a5e52019-02-12 21:32:27 -05001040 fb->_FP32Buffers = 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001041
Brian Paul989edea2009-01-22 15:05:13 -07001042 /* Start at -2 to more easily loop over all attachment points.
1043 * -2: depth buffer
1044 * -1: stencil buffer
1045 * >=0: color buffer
1046 */
Brian Paule4b23562005-05-04 20:11:35 +00001047 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001048 struct gl_renderbuffer_attachment *att;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001049 GLenum f;
Kenneth Graunke69215882019-02-22 01:16:41 -08001050 GLenum baseFormat;
Mark Mueller71fe9432014-01-04 14:11:43 -08001051 mesa_format attFormat;
Paul Berry95140742013-11-19 15:55:51 -08001052 GLenum att_tex_target = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001053
Brian Paul1bc59bf2009-01-22 15:07:34 -07001054 /*
1055 * XXX for ARB_fbo, only check color buffers that are named by
1056 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
1057 */
1058
Brian Paul989edea2009-01-22 15:05:13 -07001059 /* check for attachment completeness
1060 */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001061 if (i == -2) {
Brian Paule4b23562005-05-04 20:11:35 +00001062 att = &fb->Attachment[BUFFER_DEPTH];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001063 test_attachment_completeness(ctx, GL_DEPTH, att);
1064 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001065 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001066 fbo_incomplete(ctx, "depth attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001067 return;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001068 } else if (att->Type != GL_NONE) {
1069 has_depth_attachment = true;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001070 }
1071 }
1072 else if (i == -1) {
Brian Paule4b23562005-05-04 20:11:35 +00001073 att = &fb->Attachment[BUFFER_STENCIL];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001074 test_attachment_completeness(ctx, GL_STENCIL, att);
1075 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001076 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001077 fbo_incomplete(ctx, "stencil attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001078 return;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001079 } else if (att->Type != GL_NONE) {
1080 has_stencil_attachment = true;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001081 }
1082 }
1083 else {
Brian Paule4b23562005-05-04 20:11:35 +00001084 att = &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001085 test_attachment_completeness(ctx, GL_COLOR, att);
1086 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001087 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001088 fbo_incomplete(ctx, "color attachment incomplete", i);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001089 return;
1090 }
1091 }
1092
Brian Paul989edea2009-01-22 15:05:13 -07001093 /* get width, height, format of the renderbuffer/texture
1094 */
Marek Olšák459f05c2018-06-11 18:30:34 -04001095 unsigned attNumSamples, attNumStorageSamples;
1096
Brian Paulf0bbbf62005-02-09 03:50:30 +00001097 if (att->Type == GL_TEXTURE) {
Eric Anholte98c39c2013-05-10 11:51:01 -07001098 const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
Paul Berry95140742013-11-19 15:55:51 -08001099 att_tex_target = att->Texture->Target;
Brian Paul989edea2009-01-22 15:05:13 -07001100 minWidth = MIN2(minWidth, texImg->Width);
1101 maxWidth = MAX2(maxWidth, texImg->Width);
1102 minHeight = MIN2(minHeight, texImg->Height);
1103 maxHeight = MAX2(maxHeight, texImg->Height);
Brian Paula9fc8ba2005-10-05 01:48:07 +00001104 f = texImg->_BaseFormat;
Kenneth Graunke69215882019-02-22 01:16:41 -08001105 baseFormat = f;
Brian Paulca1b5512011-02-28 18:23:23 -07001106 attFormat = texImg->TexFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001107 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001108
Brian Paulc1377ed2014-03-22 10:31:58 -06001109 if (!is_format_color_renderable(ctx, attFormat,
1110 texImg->InternalFormat) &&
Dave Airlie782e71c2015-04-05 13:19:18 +10001111 !is_legal_depth_format(ctx, f) &&
1112 f != GL_STENCIL_INDEX) {
Iago Toral Quirogab6819cd2014-12-15 09:29:55 +01001113 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001114 fbo_incomplete(ctx, "texture attachment incomplete", -1);
Brian Pauled7f3ae2005-06-07 15:03:40 +00001115 return;
1116 }
Chris Forbes61d42ff2012-12-16 20:58:00 +13001117
Chris Forbes61d42ff2012-12-16 20:58:00 +13001118 if (fixedSampleLocations < 0)
1119 fixedSampleLocations = texImg->FixedSampleLocations;
1120 else if (fixedSampleLocations != texImg->FixedSampleLocations) {
1121 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001122 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
Chris Forbes61d42ff2012-12-16 20:58:00 +13001123 return;
1124 }
Marek Olšák459f05c2018-06-11 18:30:34 -04001125
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08001126 if (att->NumSamples > 0)
1127 attNumSamples = att->NumSamples;
1128 else
1129 attNumSamples = texImg->NumSamples;
1130 attNumStorageSamples = attNumSamples;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001131 }
1132 else if (att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul989edea2009-01-22 15:05:13 -07001133 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
1134 maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
1135 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
1136 maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001137 f = att->Renderbuffer->InternalFormat;
Kenneth Graunke69215882019-02-22 01:16:41 -08001138 baseFormat = att->Renderbuffer->_BaseFormat;
Brian Paulca1b5512011-02-28 18:23:23 -07001139 attFormat = att->Renderbuffer->Format;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001140 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001141
Chris Forbes61d42ff2012-12-16 20:58:00 +13001142 /* RENDERBUFFER has fixedSampleLocations implicitly true */
1143 if (fixedSampleLocations < 0)
1144 fixedSampleLocations = GL_TRUE;
1145 else if (fixedSampleLocations != GL_TRUE) {
1146 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001147 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
Chris Forbes61d42ff2012-12-16 20:58:00 +13001148 return;
1149 }
Marek Olšák459f05c2018-06-11 18:30:34 -04001150
1151 attNumSamples = att->Renderbuffer->NumSamples;
1152 attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001153 }
1154 else {
1155 assert(att->Type == GL_NONE);
1156 continue;
1157 }
1158
Marek Olšák459f05c2018-06-11 18:30:34 -04001159 if (i >= 0) {
1160 /* Color buffers. */
1161 if (numColorSamples < 0) {
1162 assert(numColorStorageSamples < 0);
1163 numColorSamples = attNumSamples;
1164 numColorStorageSamples = attNumStorageSamples;
1165 } else if (numColorSamples != attNumSamples ||
1166 numColorStorageSamples != attNumStorageSamples) {
1167 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1168 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1169 return;
1170 }
1171 } else {
1172 /* Depth/stencil buffers. */
1173 if (numDepthSamples < 0) {
1174 numDepthSamples = attNumSamples;
1175 } else if (numDepthSamples != attNumSamples) {
1176 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1177 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1178 return;
1179 }
1180 }
1181
Brian Paulff00ab72016-10-10 11:29:14 -06001182 /* Update flags describing color buffer datatypes */
Marek Olšák21d407c2013-03-28 01:50:21 +01001183 if (i >= 0) {
1184 GLenum type = _mesa_get_format_datatype(attFormat);
1185
Brian Paulff00ab72016-10-10 11:29:14 -06001186 /* check if integer color */
1187 if (_mesa_is_format_integer_color(attFormat))
1188 fb->_IntegerBuffers |= (1 << i);
1189
Kenneth Graunke69215882019-02-22 01:16:41 -08001190 if (baseFormat == GL_RGB)
Kenneth Graunke5b51d752018-07-21 23:40:16 -07001191 fb->_RGBBuffers |= (1 << i);
1192
Ilia Mirkin070a5e52019-02-12 21:32:27 -05001193 if (type == GL_FLOAT && _mesa_get_format_max_bits(attFormat) > 16)
1194 fb->_FP32Buffers |= (1 << i);
1195
Marek Olšák21d407c2013-03-28 01:50:21 +01001196 fb->_AllColorBuffersFixedPoint =
1197 fb->_AllColorBuffersFixedPoint &&
1198 (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
Marek Olšák755648c2013-03-28 01:56:01 +01001199
1200 fb->_HasSNormOrFloatColorBuffer =
1201 fb->_HasSNormOrFloatColorBuffer ||
1202 type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
Marek Olšák21d407c2013-03-28 01:50:21 +01001203 }
1204
Chris Forbes61d42ff2012-12-16 20:58:00 +13001205 /* Error-check width, height, format */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001206 if (numImages == 1) {
Chris Forbes61d42ff2012-12-16 20:58:00 +13001207 /* save format */
Brian Paul722d9762009-01-20 16:58:49 -07001208 if (i >= 0) {
Brian Paulf0bbbf62005-02-09 03:50:30 +00001209 intFormat = f;
Brian Paul722d9762009-01-20 16:58:49 -07001210 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001211 }
1212 else {
Brian Paul989edea2009-01-22 15:05:13 -07001213 if (!ctx->Extensions.ARB_framebuffer_object) {
1214 /* check that width, height, format are same */
1215 if (minWidth != maxWidth || minHeight != maxHeight) {
1216 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001217 fbo_incomplete(ctx, "width or height mismatch", -1);
Brian Paul989edea2009-01-22 15:05:13 -07001218 return;
1219 }
Brian Paul45bd5c42011-12-16 08:44:43 -07001220 /* check that all color buffers are the same format */
Brian Paul989edea2009-01-22 15:05:13 -07001221 if (intFormat != GL_NONE && f != intFormat) {
1222 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001223 fbo_incomplete(ctx, "format mismatch", -1);
Brian Paul989edea2009-01-22 15:05:13 -07001224 return;
1225 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001226 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001227 }
Marek Olšáka82227c2012-06-15 17:21:05 +02001228
1229 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1230 */
1231 if (att->Type == GL_RENDERBUFFER &&
1232 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1233 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001234 fbo_incomplete(ctx, "unsupported renderbuffer format", i);
Marek Olšáka82227c2012-06-15 17:21:05 +02001235 return;
1236 }
Jordan Justen5da82882013-04-18 10:20:05 -07001237
1238 /* Check that layered rendering is consistent. */
Paul Berry95140742013-11-19 15:55:51 -08001239 if (att->Layered) {
1240 if (att_tex_target == GL_TEXTURE_CUBE_MAP)
1241 att_layer_count = 6;
Kenneth Graunke5c399ca2014-05-07 14:35:42 -07001242 else if (att_tex_target == GL_TEXTURE_1D_ARRAY)
1243 att_layer_count = att->Renderbuffer->Height;
Paul Berry95140742013-11-19 15:55:51 -08001244 else
1245 att_layer_count = att->Renderbuffer->Depth;
1246 } else {
1247 att_layer_count = 0;
1248 }
Paul Berry28af1dc2013-11-19 19:01:37 -08001249 if (!layer_info_valid) {
Paul Berry532b1fe2014-01-07 06:29:47 -08001250 is_layered = att->Layered;
1251 max_layer_count = att_layer_count;
Paul Berry28af1dc2013-11-19 19:01:37 -08001252 layer_tex_target = att_tex_target;
1253 layer_info_valid = true;
Paul Berry532b1fe2014-01-07 06:29:47 -08001254 } else if (max_layer_count > 0 && layer_tex_target != att_tex_target) {
Paul Berry28af1dc2013-11-19 19:01:37 -08001255 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1256 fbo_incomplete(ctx, "layered framebuffer has mismatched targets", i);
1257 return;
Paul Berry532b1fe2014-01-07 06:29:47 -08001258 } else if (is_layered != att->Layered) {
1259 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
Brian Paulc1377ed2014-03-22 10:31:58 -06001260 fbo_incomplete(ctx,
1261 "framebuffer attachment layer mode is inconsistent",
1262 i);
Jordan Justen5da82882013-04-18 10:20:05 -07001263 return;
Paul Berry532b1fe2014-01-07 06:29:47 -08001264 } else if (att_layer_count > max_layer_count) {
1265 max_layer_count = att_layer_count;
Jordan Justen5da82882013-04-18 10:20:05 -07001266 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001267
1268 /*
1269 * The extension GL_ARB_framebuffer_no_attachments places additional
1270 * requirement on each attachment. Those additional requirements are
1271 * tighter that those of previous versions of GL. In interest of better
1272 * compatibility, we will not enforce these restrictions. For the record
1273 * those additional restrictions are quoted below:
1274 *
1275 * "The width and height of image are greater than zero and less than or
1276 * equal to the values of the implementation-dependent limits
1277 * MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively."
1278 *
1279 * "If <image> is a three-dimensional texture or a one- or two-dimensional
1280 * array texture and the attachment is layered, the depth or layer count
1281 * of the texture is less than or equal to the implementation-dependent
1282 * limit MAX_FRAMEBUFFER_LAYERS."
1283 *
1284 * "If image has multiple samples, its sample count is less than or equal
1285 * to the value of the implementation-dependent limit
1286 * MAX_FRAMEBUFFER_SAMPLES."
1287 *
1288 * The same requirements are also in place for GL 4.5,
1289 * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
1290 */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001291 }
1292
Marek Olšák459f05c2018-06-11 18:30:34 -04001293 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
1294 /* See if non-matching sample counts are supported. */
1295 if (numColorSamples >= 0 && numDepthSamples >= 0) {
1296 bool found = false;
1297
1298 assert(numColorStorageSamples != -1);
1299
1300 numColorSamples = MAX2(numColorSamples, 1);
1301 numColorStorageSamples = MAX2(numColorStorageSamples, 1);
1302 numDepthSamples = MAX2(numDepthSamples, 1);
1303
1304 if (numColorSamples == 1 && numColorStorageSamples == 1 &&
1305 numDepthSamples == 1) {
1306 found = true;
1307 } else {
1308 for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
1309 GLint *counts =
1310 &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
1311
1312 if (counts[0] == numColorSamples &&
1313 counts[1] == numColorStorageSamples &&
1314 counts[2] == numDepthSamples) {
1315 found = true;
1316 break;
1317 }
1318 }
1319 }
1320
1321 if (!found) {
1322 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1323 fbo_incomplete(ctx, "unsupported sample counts", -1);
1324 return;
1325 }
1326 }
1327 } else {
1328 /* If the extension is unsupported, all sample counts must be equal. */
1329 if (numColorSamples >= 0 &&
1330 (numColorSamples != numColorStorageSamples ||
1331 (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
1332 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1333 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1334 return;
1335 }
1336 }
1337
Paul Berry532b1fe2014-01-07 06:29:47 -08001338 fb->MaxNumLayers = max_layer_count;
Jordan Justen5da82882013-04-18 10:20:05 -07001339
Chris Forbesa419a1c2014-03-23 22:41:28 +13001340 if (numImages == 0) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001341 fb->_HasAttachments = false;
1342
1343 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1344 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1345 fbo_incomplete(ctx, "no attachments", -1);
1346 return;
1347 }
1348
1349 if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) {
1350 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1351 fbo_incomplete(ctx, "no attachments and default width or height is 0", -1);
1352 return;
1353 }
Chris Forbesa419a1c2014-03-23 22:41:28 +13001354 }
1355
Jordan Justen09714c02012-07-19 11:27:16 -07001356 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001357 /* Check that all DrawBuffers are present */
1358 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001359 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1360 const struct gl_renderbuffer_attachment *att
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02001361 = get_attachment(ctx, fb, fb->ColorDrawBuffer[j], NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001362 assert(att);
1363 if (att->Type == GL_NONE) {
1364 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1365 fbo_incomplete(ctx, "missing drawbuffer", j);
1366 return;
1367 }
1368 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001369 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001370
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001371 /* Check that the ReadBuffer is present */
1372 if (fb->ColorReadBuffer != GL_NONE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001373 const struct gl_renderbuffer_attachment *att
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02001374 = get_attachment(ctx, fb, fb->ColorReadBuffer, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001375 assert(att);
1376 if (att->Type == GL_NONE) {
1377 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001378 fbo_incomplete(ctx, "missing readbuffer", -1);
Martin Peres7bd8b482015-02-12 17:54:43 +02001379 return;
1380 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001381 }
1382 }
1383
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001384 /* The OpenGL ES3 spec, in chapter 9.4. FRAMEBUFFER COMPLETENESS, says:
1385 *
1386 * "Depth and stencil attachments, if present, are the same image."
1387 *
1388 * This restriction is not present in the OpenGL ES2 spec.
1389 */
1390 if (_mesa_is_gles3(ctx) &&
1391 has_stencil_attachment && has_depth_attachment &&
1392 !_mesa_has_depthstencil_combined(fb)) {
1393 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1394 fbo_incomplete(ctx, "Depth and stencil attachments must be the same image", -1);
1395 return;
1396 }
1397
Brian Paul3528f692009-01-22 15:13:18 -07001398 /* Provisionally set status = COMPLETE ... */
Brian Paule4b23562005-05-04 20:11:35 +00001399 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
Brian Paul3528f692009-01-22 15:13:18 -07001400
Brian Paul777a2ef2009-01-22 15:17:42 -07001401 /* ... but the driver may say the FB is incomplete.
1402 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1403 * if anything.
1404 */
Brian Paul3528f692009-01-22 15:13:18 -07001405 if (ctx->Driver.ValidateFramebuffer) {
1406 ctx->Driver.ValidateFramebuffer(ctx, fb);
Brian Paul1f32c412009-01-19 17:34:19 -07001407 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001408 fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001409 return;
Brian Paul1f32c412009-01-19 17:34:19 -07001410 }
Brian Paul3528f692009-01-22 15:13:18 -07001411 }
1412
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001413 /*
1414 * Note that if ARB_framebuffer_object is supported and the attached
1415 * renderbuffers/textures are different sizes, the framebuffer
1416 * width/height will be set to the smallest width/height.
1417 */
1418 if (numImages != 0) {
1419 fb->Width = minWidth;
1420 fb->Height = minHeight;
Brian Paul3528f692009-01-22 15:13:18 -07001421 }
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001422
1423 /* finally, update the visual info for the framebuffer */
1424 _mesa_update_framebuffer_visual(ctx, fb);
Brian Paule4b23562005-05-04 20:11:35 +00001425}
Brian Paulf0bbbf62005-02-09 03:50:30 +00001426
1427
Brian Paul1864c7d2005-02-08 03:46:37 +00001428GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001429_mesa_IsRenderbuffer(GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001430{
Samuel Pitoiset78392432017-04-06 18:05:36 +02001431 struct gl_renderbuffer *rb;
1432
Brian Paulddc82ee2005-02-05 19:56:45 +00001433 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoiset78392432017-04-06 18:05:36 +02001434
Brian Paulddc82ee2005-02-05 19:56:45 +00001435 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Samuel Pitoiset78392432017-04-06 18:05:36 +02001436
1437 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1438 return rb != NULL && rb != &DummyRenderbuffer;
Brian Paulddc82ee2005-02-05 19:56:45 +00001439}
1440
1441
Martin Peresa34669b2015-02-12 18:52:10 +02001442static struct gl_renderbuffer *
Matt Turner015f2202015-07-30 14:31:04 -07001443allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
1444 const char *func)
Martin Peresa34669b2015-02-12 18:52:10 +02001445{
1446 struct gl_renderbuffer *newRb;
1447
1448 /* create new renderbuffer object */
1449 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1450 if (!newRb) {
1451 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1452 return NULL;
1453 }
1454 assert(newRb->AllocStorage);
Matt Turner015f2202015-07-30 14:31:04 -07001455 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer, newRb);
Martin Peresa34669b2015-02-12 18:52:10 +02001456
1457 return newRb;
1458}
1459
1460
Ian Romanick97965e82013-07-18 17:38:16 -07001461static void
Timothy Arcerib54a2312018-09-08 14:20:17 +10001462bind_renderbuffer(GLenum target, GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001463{
Brian42aaa542007-03-25 10:39:36 -06001464 struct gl_renderbuffer *newRb;
Brian Paulddc82ee2005-02-05 19:56:45 +00001465 GET_CURRENT_CONTEXT(ctx);
1466
Brian Paul3deaa012005-02-07 05:08:24 +00001467 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul4de18fb2009-11-02 15:30:51 -07001468 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00001469 return;
1470 }
1471
Brian Paul800e5532009-11-02 15:39:39 -07001472 /* No need to flush here since the render buffer binding has no
1473 * effect on rendering state.
1474 */
Brian Paul474f28e2005-10-08 14:41:17 +00001475
Brian Paul3deaa012005-02-07 05:08:24 +00001476 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00001477 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001478 if (newRb == &DummyRenderbuffer) {
1479 /* ID was reserved, but no real renderbuffer object made yet */
1480 newRb = NULL;
1481 }
Timothy Arcerib54a2312018-09-08 14:20:17 +10001482 else if (!newRb && ctx->API == API_OPENGL_CORE) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07001483 /* All RB IDs must be Gen'd */
Timothy Arcerib54a2312018-09-08 14:20:17 +10001484 _mesa_error(ctx, GL_INVALID_OPERATION,
1485 "glBindRenderbuffer(non-gen name)");
Brian Paul1bc59bf2009-01-22 15:07:34 -07001486 return;
1487 }
1488
Brian Paul3deaa012005-02-07 05:08:24 +00001489 if (!newRb) {
Matt Turner015f2202015-07-30 14:31:04 -07001490 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1491 newRb = allocate_renderbuffer_locked(ctx, renderbuffer,
1492 "glBindRenderbufferEXT");
1493 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
Brian Paul3deaa012005-02-07 05:08:24 +00001494 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001495 }
Brian Paul463642c2005-02-08 02:06:00 +00001496 else {
1497 newRb = NULL;
1498 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001499
Matt Turnerbfcdb842015-02-20 20:18:47 -08001500 assert(newRb != &DummyRenderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001501
Brian42aaa542007-03-25 10:39:36 -06001502 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
Brian Paulddc82ee2005-02-05 19:56:45 +00001503}
1504
Ian Romanick97965e82013-07-18 17:38:16 -07001505void GLAPIENTRY
1506_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1507{
Ian Romanick97965e82013-07-18 17:38:16 -07001508 /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1509 * entry point, but they allow the use of user-generated names.
1510 */
Timothy Arcerib54a2312018-09-08 14:20:17 +10001511 bind_renderbuffer(target, renderbuffer);
Ian Romanick97965e82013-07-18 17:38:16 -07001512}
Brian Paulddc82ee2005-02-05 19:56:45 +00001513
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001514void GLAPIENTRY
1515_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1516{
Timothy Arcerib54a2312018-09-08 14:20:17 +10001517 bind_renderbuffer(target, renderbuffer);
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001518}
1519
Edward O'Callaghanb40375a2016-02-17 19:15:49 +11001520/**
Rhys Perry67f40da2018-06-14 19:56:28 -06001521 * ARB_framebuffer_no_attachment and ARB_sample_locations - Application passes
1522 * requested param's here. NOTE: NumSamples requested need not be _NumSamples
1523 * which is what the hw supports.
Edward O'Callaghanb40375a2016-02-17 19:15:49 +11001524 */
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001525static void
1526framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
1527 GLenum pname, GLint param, const char *func)
1528{
Rhys Perry67f40da2018-06-14 19:56:28 -06001529 bool cannot_be_winsys_fbo = false;
1530
1531 switch (pname) {
1532 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1533 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1534 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1535 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1536 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1537 if (!ctx->Extensions.ARB_framebuffer_no_attachments)
1538 goto invalid_pname_enum;
1539 cannot_be_winsys_fbo = true;
1540 break;
1541 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1542 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1543 if (!ctx->Extensions.ARB_sample_locations)
1544 goto invalid_pname_enum;
1545 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001546 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1547 if (!ctx->Extensions.MESA_framebuffer_flip_y)
1548 goto invalid_pname_enum;
1549 cannot_be_winsys_fbo = true;
Fritz Koenig60d0c0d2018-09-14 11:40:49 -07001550 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001551 default:
1552 goto invalid_pname_enum;
1553 }
1554
1555 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1556 _mesa_error(ctx, GL_INVALID_OPERATION,
1557 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1558 return;
1559 }
1560
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001561 switch (pname) {
1562 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1563 if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
1564 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1565 else
1566 fb->DefaultGeometry.Width = param;
1567 break;
1568 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1569 if (param < 0 || param > ctx->Const.MaxFramebufferHeight)
1570 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1571 else
1572 fb->DefaultGeometry.Height = param;
1573 break;
1574 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001575 /*
1576 * According to the OpenGL ES 3.1 specification section 9.2.1, the
1577 * GL_FRAMEBUFFER_DEFAULT_LAYERS parameter name is not supported.
1578 */
Ilia Mirkin82d756f2016-05-21 20:26:47 -04001579 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001580 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1581 break;
1582 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001583 if (param < 0 || param > ctx->Const.MaxFramebufferLayers)
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001584 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001585 else
1586 fb->DefaultGeometry.Layers = param;
1587 break;
1588 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1589 if (param < 0 || param > ctx->Const.MaxFramebufferSamples)
1590 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1591 else
1592 fb->DefaultGeometry.NumSamples = param;
1593 break;
1594 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1595 fb->DefaultGeometry.FixedSampleLocations = param;
1596 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001597 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1598 fb->ProgrammableSampleLocations = !!param;
1599 break;
1600 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1601 fb->SampleLocationPixelGrid = !!param;
1602 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001603 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1604 fb->FlipY = param;
1605 break;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001606 }
Ilia Mirkin095da3b2016-01-23 09:27:22 -05001607
Rhys Perry67f40da2018-06-14 19:56:28 -06001608 switch (pname) {
1609 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1610 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1611 if (fb == ctx->DrawBuffer)
1612 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
1613 break;
1614 default:
1615 invalidate_framebuffer(fb);
1616 ctx->NewState |= _NEW_BUFFERS;
1617 break;
1618 }
1619
1620 return;
1621
1622invalid_pname_enum:
1623 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001624}
1625
Fritz Koenig66937ab2019-07-30 14:53:30 -07001626static bool
1627validate_framebuffer_parameter_extensions(GLenum pname, const char *func)
1628{
1629 GET_CURRENT_CONTEXT(ctx);
1630
1631 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
1632 !ctx->Extensions.ARB_sample_locations &&
1633 !ctx->Extensions.MESA_framebuffer_flip_y) {
1634 _mesa_error(ctx, GL_INVALID_OPERATION,
1635 "%s not supported "
1636 "(none of ARB_framebuffer_no_attachments,"
1637 " ARB_sample_locations, or"
1638 " MESA_framebuffer_flip_y extensions are available)",
1639 func);
1640 return false;
1641 }
1642
1643 /*
1644 * If only the MESA_framebuffer_flip_y extension is enabled
1645 * pname can only be GL_FRAMEBUFFER_FLIP_Y_MESA
1646 */
1647 if (ctx->Extensions.MESA_framebuffer_flip_y &&
1648 pname != GL_FRAMEBUFFER_FLIP_Y_MESA &&
1649 !(ctx->Extensions.ARB_framebuffer_no_attachments ||
1650 ctx->Extensions.ARB_sample_locations)) {
1651 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1652 return false;
1653 }
1654
1655 return true;
1656}
1657
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001658void GLAPIENTRY
1659_mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
1660{
1661 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001662 struct gl_framebuffer *fb;
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001663
Fritz Koenig66937ab2019-07-30 14:53:30 -07001664 if (!validate_framebuffer_parameter_extensions(pname,
1665 "glFramebufferParameteri")) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001666 return;
1667 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001668
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001669 fb = get_framebuffer_target(ctx, target);
1670 if (!fb) {
1671 _mesa_error(ctx, GL_INVALID_ENUM,
1672 "glFramebufferParameteri(target=0x%x)", target);
1673 return;
1674 }
1675
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001676 framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
1677}
1678
Fritz Koenig66937ab2019-07-30 14:53:30 -07001679void GLAPIENTRY
1680_mesa_FramebufferParameteriMESA(GLenum target, GLenum pname, GLint param)
1681{
1682 _mesa_FramebufferParameteri(target, pname, param);
1683}
1684
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001685static bool
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001686validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
1687 struct gl_framebuffer *fb,
1688 GLuint pname, const char *func)
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001689{
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001690 bool cannot_be_winsys_fbo = true;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001691
1692 switch (pname) {
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001693 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1694 /*
1695 * According to the OpenGL ES 3.1 specification section 9.2.3, the
1696 * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
1697 */
1698 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1699 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1700 return false;
1701 }
1702 break;
1703 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1704 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1705 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1706 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1707 break;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001708 case GL_DOUBLEBUFFER:
1709 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1710 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1711 case GL_SAMPLES:
1712 case GL_SAMPLE_BUFFERS:
1713 case GL_STEREO:
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001714 /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
1715 *
1716 * "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
1717 * if the default framebuffer is bound to target and pname is not one
1718 * of the accepted values from table 23.73, other than
1719 * SAMPLE_POSITION."
1720 *
1721 * For OpenGL ES, using default framebuffer raises INVALID_OPERATION
1722 * for any pname.
1723 */
1724 cannot_be_winsys_fbo = !_mesa_is_desktop_gl(ctx);
1725 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001726 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1727 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1728 if (!ctx->Extensions.ARB_sample_locations)
1729 goto invalid_pname_enum;
1730 cannot_be_winsys_fbo = false;
1731 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001732 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1733 if (!ctx->Extensions.MESA_framebuffer_flip_y) {
1734 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1735 return false;
1736 }
1737 break;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001738 default:
Rhys Perry67f40da2018-06-14 19:56:28 -06001739 goto invalid_pname_enum;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001740 }
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001741
1742 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1743 _mesa_error(ctx, GL_INVALID_OPERATION,
1744 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1745 return false;
1746 }
1747
1748 return true;
Rhys Perry67f40da2018-06-14 19:56:28 -06001749
1750invalid_pname_enum:
1751 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1752 return false;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001753}
1754
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001755static void
1756get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
1757 GLenum pname, GLint *params, const char *func)
1758{
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001759 if (!validate_get_framebuffer_parameteriv_pname(ctx, fb, pname, func))
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001760 return;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001761
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001762 switch (pname) {
1763 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1764 *params = fb->DefaultGeometry.Width;
1765 break;
1766 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1767 *params = fb->DefaultGeometry.Height;
1768 break;
1769 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1770 *params = fb->DefaultGeometry.Layers;
1771 break;
1772 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1773 *params = fb->DefaultGeometry.NumSamples;
1774 break;
1775 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1776 *params = fb->DefaultGeometry.FixedSampleLocations;
1777 break;
Alejandro Piñeiro0fb0c572017-01-13 16:23:05 -02001778 case GL_DOUBLEBUFFER:
1779 *params = fb->Visual.doubleBufferMode;
1780 break;
1781 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1782 *params = _mesa_get_color_read_format(ctx, fb, func);
1783 break;
1784 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1785 *params = _mesa_get_color_read_type(ctx, fb, func);
1786 break;
1787 case GL_SAMPLES:
1788 *params = _mesa_geometric_samples(fb);
1789 break;
1790 case GL_SAMPLE_BUFFERS:
1791 *params = _mesa_geometric_samples(fb) > 0;
1792 break;
1793 case GL_STEREO:
1794 *params = fb->Visual.stereoMode;
1795 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001796 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1797 *params = fb->ProgrammableSampleLocations;
1798 break;
1799 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1800 *params = fb->SampleLocationPixelGrid;
1801 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001802 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1803 *params = fb->FlipY;
1804 break;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001805 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001806}
1807
1808void GLAPIENTRY
1809_mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
1810{
1811 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001812 struct gl_framebuffer *fb;
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001813
Fritz Koenig66937ab2019-07-30 14:53:30 -07001814 if (!validate_framebuffer_parameter_extensions(pname,
1815 "glGetFramebufferParameteriv")) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001816 return;
1817 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001818
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001819 fb = get_framebuffer_target(ctx, target);
1820 if (!fb) {
1821 _mesa_error(ctx, GL_INVALID_ENUM,
1822 "glGetFramebufferParameteriv(target=0x%x)", target);
1823 return;
1824 }
1825
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001826 get_framebuffer_parameteriv(ctx, fb, pname, params,
1827 "glGetFramebufferParameteriv");
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001828}
1829
Fritz Koenig66937ab2019-07-30 14:53:30 -07001830void GLAPIENTRY
1831_mesa_GetFramebufferParameterivMESA(GLenum target, GLenum pname, GLint *params)
1832{
1833 _mesa_GetFramebufferParameteriv(target, pname, params);
1834}
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001835
Brian Pauld0f13fa2009-01-21 11:17:45 -07001836/**
Ian Romanickef83bd22013-08-08 15:41:36 -07001837 * Remove the specified renderbuffer or texture from any attachment point in
1838 * the framebuffer.
Ian Romanick438cc6b2013-08-08 15:26:36 -07001839 *
1840 * \returns
1841 * \c true if the renderbuffer was detached from an attachment point. \c
1842 * false otherwise.
Brian Pauld0f13fa2009-01-21 11:17:45 -07001843 */
Ian Romanick438cc6b2013-08-08 15:26:36 -07001844bool
1845_mesa_detach_renderbuffer(struct gl_context *ctx,
1846 struct gl_framebuffer *fb,
1847 const void *att)
Brian Pauld0f13fa2009-01-21 11:17:45 -07001848{
Ian Romanick438cc6b2013-08-08 15:26:36 -07001849 unsigned i;
1850 bool progress = false;
1851
Brian Pauld0f13fa2009-01-21 11:17:45 -07001852 for (i = 0; i < BUFFER_COUNT; i++) {
Ian Romanickef83bd22013-08-08 15:41:36 -07001853 if (fb->Attachment[i].Texture == att
1854 || fb->Attachment[i].Renderbuffer == att) {
Brian Paul94512812014-02-01 08:58:43 -07001855 remove_attachment(ctx, &fb->Attachment[i]);
Ian Romanick438cc6b2013-08-08 15:26:36 -07001856 progress = true;
Brian Pauld0f13fa2009-01-21 11:17:45 -07001857 }
1858 }
Ian Romanick438cc6b2013-08-08 15:26:36 -07001859
1860 /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1861 * Completeness," of the OpenGL 3.1 spec says:
1862 *
1863 * "Performing any of the following actions may change whether the
1864 * framebuffer is considered complete or incomplete:
1865 *
1866 * ...
1867 *
1868 * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1869 * containing an image that is attached to a framebuffer object
1870 * that is bound to the framebuffer."
1871 */
1872 if (progress)
1873 invalidate_framebuffer(fb);
1874
1875 return progress;
Brian Pauld0f13fa2009-01-21 11:17:45 -07001876}
1877
1878
Brian Paul1864c7d2005-02-08 03:46:37 +00001879void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001880_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001881{
1882 GLint i;
1883 GET_CURRENT_CONTEXT(ctx);
1884
Eduardo Lima Mitev2012f622014-12-11 23:34:18 +01001885 if (n < 0) {
1886 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteRenderbuffers(n < 0)");
1887 return;
1888 }
1889
Brian Paul474f28e2005-10-08 14:41:17 +00001890 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00001891
1892 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001893 if (renderbuffers[i] > 0) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001894 struct gl_renderbuffer *rb;
1895 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
1896 if (rb) {
Brian Paul91802fd2005-10-04 16:01:02 +00001897 /* check if deleting currently bound renderbuffer object */
1898 if (rb == ctx->CurrentRenderbuffer) {
1899 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08001900 assert(rb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001901 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
Brian Paul91802fd2005-10-04 16:01:02 +00001902 }
1903
Ian Romanickef83bd22013-08-08 15:41:36 -07001904 /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
Brian Paulc1377ed2014-03-22 10:31:58 -06001905 * subsection "Attaching Renderbuffer Images to a Framebuffer,"
1906 * of the OpenGL 3.1 spec says:
Ian Romanickef83bd22013-08-08 15:41:36 -07001907 *
1908 * "If a renderbuffer object is deleted while its image is
1909 * attached to one or more attachment points in the currently
1910 * bound framebuffer, then it is as if FramebufferRenderbuffer
1911 * had been called, with a renderbuffer of 0, for each
1912 * attachment point to which this image was attached in the
1913 * currently bound framebuffer. In other words, this
1914 * renderbuffer image is first detached from all attachment
1915 * points in the currently bound framebuffer. Note that the
1916 * renderbuffer image is specifically not detached from any
1917 * non-bound framebuffers. Detaching the image from any
1918 * non-bound framebuffers is the responsibility of the
1919 * application.
1920 */
Brian Paul36ede892012-01-12 09:17:23 -07001921 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
Ian Romanick438cc6b2013-08-08 15:26:36 -07001922 _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07001923 }
Brian Paul36ede892012-01-12 09:17:23 -07001924 if (_mesa_is_user_fbo(ctx->ReadBuffer)
Brian Paulfc8c4a32011-06-16 07:31:58 -06001925 && ctx->ReadBuffer != ctx->DrawBuffer) {
Ian Romanick438cc6b2013-08-08 15:26:36 -07001926 _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07001927 }
1928
Martin Peres7bd8b482015-02-12 17:54:43 +02001929 /* Remove from hash table immediately, to free the ID.
Brian42aaa542007-03-25 10:39:36 -06001930 * But the object will not be freed until it's no longer
1931 * referenced anywhere else.
1932 */
Martin Peres7bd8b482015-02-12 17:54:43 +02001933 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00001934
Brian Paul1864c7d2005-02-08 03:46:37 +00001935 if (rb != &DummyRenderbuffer) {
Brian42aaa542007-03-25 10:39:36 -06001936 /* no longer referenced by hash table */
1937 _mesa_reference_renderbuffer(&rb, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001938 }
1939 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001940 }
1941 }
1942}
1943
Martin Peresa34669b2015-02-12 18:52:10 +02001944static void
1945create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
1946 bool dsa)
Brian Paulddc82ee2005-02-05 19:56:45 +00001947{
Martin Peresa34669b2015-02-12 18:52:10 +02001948 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
Brian Paulddc82ee2005-02-05 19:56:45 +00001949 GLuint first;
1950 GLint i;
1951
Brian Paulddc82ee2005-02-05 19:56:45 +00001952 if (!renderbuffers)
1953 return;
1954
Matt Turner015f2202015-07-30 14:31:04 -07001955 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1956
Brian Paulddc82ee2005-02-05 19:56:45 +00001957 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1958
1959 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001960 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001961 renderbuffers[i] = name;
Martin Peresa34669b2015-02-12 18:52:10 +02001962
1963 if (dsa) {
Matt Turner015f2202015-07-30 14:31:04 -07001964 allocate_renderbuffer_locked(ctx, name, func);
Martin Peresa34669b2015-02-12 18:52:10 +02001965 } else {
Martin Peresfa383212015-03-25 16:28:03 +02001966 /* insert a dummy renderbuffer into the hash table */
Matt Turner015f2202015-07-30 14:31:04 -07001967 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, name,
1968 &DummyRenderbuffer);
Martin Peresa34669b2015-02-12 18:52:10 +02001969 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001970 }
Matt Turner015f2202015-07-30 14:31:04 -07001971
1972 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
Brian Paulddc82ee2005-02-05 19:56:45 +00001973}
1974
1975
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02001976static void
1977create_render_buffers_err(struct gl_context *ctx, GLsizei n,
1978 GLuint *renderbuffers, bool dsa)
1979{
1980 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
1981
1982 if (n < 0) {
1983 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
1984 return;
1985 }
1986
1987 create_render_buffers(ctx, n, renderbuffers, dsa);
1988}
1989
1990
Martin Peresa34669b2015-02-12 18:52:10 +02001991void GLAPIENTRY
Samuel Pitoisetb87a2cb2017-06-26 18:27:49 +02001992_mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
1993{
1994 GET_CURRENT_CONTEXT(ctx);
1995 create_render_buffers(ctx, n, renderbuffers, false);
1996}
1997
1998
1999void GLAPIENTRY
Martin Peresa34669b2015-02-12 18:52:10 +02002000_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
2001{
2002 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02002003 create_render_buffers_err(ctx, n, renderbuffers, false);
Martin Peresa34669b2015-02-12 18:52:10 +02002004}
2005
2006
2007void GLAPIENTRY
Samuel Pitoisetb87a2cb2017-06-26 18:27:49 +02002008_mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
2009{
2010 GET_CURRENT_CONTEXT(ctx);
2011 create_render_buffers(ctx, n, renderbuffers, true);
2012}
2013
2014
2015void GLAPIENTRY
Martin Peresa34669b2015-02-12 18:52:10 +02002016_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
2017{
2018 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02002019 create_render_buffers_err(ctx, n, renderbuffers, true);
Martin Peresa34669b2015-02-12 18:52:10 +02002020}
2021
2022
Brian Pauld9468c92005-02-10 16:08:07 +00002023/**
Brian Paulf41bbc72011-01-24 19:38:52 -07002024 * Given an internal format token for a render buffer, return the
Brian Paul976ea9d2011-01-24 19:38:52 -07002025 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
2026 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
2027 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
Brian Paulf41bbc72011-01-24 19:38:52 -07002028 *
Brian Paul976ea9d2011-01-24 19:38:52 -07002029 * This is similar to _mesa_base_tex_format() but the set of valid
2030 * internal formats is different.
Brian Paulf41bbc72011-01-24 19:38:52 -07002031 *
Brian Paul976ea9d2011-01-24 19:38:52 -07002032 * Note that even if a format is determined to be legal here, validation
Brian Paulb3cfcdf2011-01-28 20:25:26 -07002033 * of the FBO may fail if the format is not supported by the driver/GPU.
Brian Paul976ea9d2011-01-24 19:38:52 -07002034 *
2035 * \param internalFormat as passed to glRenderbufferStorage()
2036 * \return the base internal format, or 0 if internalFormat is illegal
Brian Pauld9468c92005-02-10 16:08:07 +00002037 */
Brian Paul59e0faa2006-03-15 17:48:00 +00002038GLenum
Brian Paulca78b6b2017-12-05 12:05:18 -07002039_mesa_base_fbo_format(const struct gl_context *ctx, GLenum internalFormat)
Brian Paul463642c2005-02-08 02:06:00 +00002040{
Brian Paul976ea9d2011-01-24 19:38:52 -07002041 /*
2042 * Notes: some formats such as alpha, luminance, etc. were added
2043 * with GL_ARB_framebuffer_object.
2044 */
Brian Paul463642c2005-02-08 02:06:00 +00002045 switch (internalFormat) {
Brian Paulf41bbc72011-01-24 19:38:52 -07002046 case GL_ALPHA:
2047 case GL_ALPHA4:
2048 case GL_ALPHA8:
2049 case GL_ALPHA12:
2050 case GL_ALPHA16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002051 return (ctx->API == API_OPENGL_COMPAT &&
2052 ctx->Extensions.ARB_framebuffer_object) ? GL_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002053 case GL_LUMINANCE:
2054 case GL_LUMINANCE4:
2055 case GL_LUMINANCE8:
2056 case GL_LUMINANCE12:
2057 case GL_LUMINANCE16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002058 return (ctx->API == API_OPENGL_COMPAT &&
2059 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002060 case GL_LUMINANCE_ALPHA:
2061 case GL_LUMINANCE4_ALPHA4:
2062 case GL_LUMINANCE6_ALPHA2:
2063 case GL_LUMINANCE8_ALPHA8:
2064 case GL_LUMINANCE12_ALPHA4:
2065 case GL_LUMINANCE12_ALPHA12:
2066 case GL_LUMINANCE16_ALPHA16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002067 return (ctx->API == API_OPENGL_COMPAT &&
2068 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002069 case GL_INTENSITY:
2070 case GL_INTENSITY4:
2071 case GL_INTENSITY8:
2072 case GL_INTENSITY12:
2073 case GL_INTENSITY16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002074 return (ctx->API == API_OPENGL_COMPAT &&
2075 ctx->Extensions.ARB_framebuffer_object) ? GL_INTENSITY : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002076 case GL_RGB8:
2077 return GL_RGB;
Brian Paulf41bbc72011-01-24 19:38:52 -07002078 case GL_RGB:
2079 case GL_R3_G3_B2:
2080 case GL_RGB4:
2081 case GL_RGB5:
Brian Paulf41bbc72011-01-24 19:38:52 -07002082 case GL_RGB10:
2083 case GL_RGB12:
2084 case GL_RGB16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002085 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002086 case GL_SRGB8_EXT:
Matt Turnercbef5372012-11-20 13:45:03 -08002087 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002088 case GL_RGBA4:
2089 case GL_RGB5_A1:
2090 case GL_RGBA8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002091 return GL_RGBA;
2092 case GL_RGBA:
2093 case GL_RGBA2:
Brian Paulf41bbc72011-01-24 19:38:52 -07002094 case GL_RGBA12:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002095 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
Tapani Pällice80abb2018-07-24 08:58:20 +03002096 case GL_RGBA16:
2097 return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2098 ? GL_RGBA : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002099 case GL_RGB10_A2:
Brian Paulf41bbc72011-01-24 19:38:52 -07002100 case GL_SRGB8_ALPHA8_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002101 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00002102 case GL_STENCIL_INDEX:
2103 case GL_STENCIL_INDEX1_EXT:
2104 case GL_STENCIL_INDEX4_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002105 case GL_STENCIL_INDEX16_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002106 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
2107 * OpenGL ES, but Mesa does not currently support them.
2108 */
2109 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
2110 case GL_STENCIL_INDEX8_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002111 return GL_STENCIL_INDEX;
2112 case GL_DEPTH_COMPONENT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002113 case GL_DEPTH_COMPONENT32:
2114 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
Brian Paul2c6f9112005-02-24 05:47:06 +00002115 case GL_DEPTH_COMPONENT16:
2116 case GL_DEPTH_COMPONENT24:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002117 return GL_DEPTH_COMPONENT;
Ian Romanick49493222013-11-13 14:15:11 -08002118 case GL_DEPTH_STENCIL:
2119 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_STENCIL : 0;
2120 case GL_DEPTH24_STENCIL8:
2121 return GL_DEPTH_STENCIL;
Marek Olšák11652802011-06-01 15:48:51 +02002122 case GL_DEPTH_COMPONENT32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002123 return ctx->Version >= 30
Brian Paulc1377ed2014-03-22 10:31:58 -06002124 || (ctx->API == API_OPENGL_COMPAT &&
2125 ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002126 ? GL_DEPTH_COMPONENT : 0;
Marek Olšák11652802011-06-01 15:48:51 +02002127 case GL_DEPTH32F_STENCIL8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002128 return ctx->Version >= 30
Brian Paulc1377ed2014-03-22 10:31:58 -06002129 || (ctx->API == API_OPENGL_COMPAT &&
2130 ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002131 ? GL_DEPTH_STENCIL : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002132 case GL_RED:
Tapani Pällice80abb2018-07-24 08:58:20 +03002133 return _mesa_has_ARB_texture_rg(ctx) ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002134 case GL_R16:
Tapani Pällice80abb2018-07-24 08:58:20 +03002135 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002136 ? GL_RED : 0;
2137 case GL_R8:
2138 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2139 ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002140 case GL_RG:
Tapani Pällice80abb2018-07-24 08:58:20 +03002141 return _mesa_has_ARB_texture_rg(ctx) ? GL_RG : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002142 case GL_RG16:
Tapani Pällice80abb2018-07-24 08:58:20 +03002143 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002144 ? GL_RG : 0;
2145 case GL_RG8:
2146 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2147 ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002148 /* signed normalized texture formats */
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002149 case GL_R8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002150 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002151 ? GL_RED : 0;
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002152 case GL_RED_SNORM:
2153 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RED : 0;
2154 case GL_R16_SNORM:
2155 return _mesa_has_EXT_texture_snorm(ctx) ||
2156 (_mesa_has_EXT_render_snorm(ctx) &&
2157 _mesa_has_EXT_texture_norm16(ctx))
2158 ? GL_RED : 0;
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002159 case GL_RG8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002160 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2161 ? GL_RG : 0;
2162 case GL_RG_SNORM:
Danylo Piliaiev2b98a022018-09-06 17:01:07 +03002163 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002164 case GL_RG16_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002165 return _mesa_has_EXT_texture_snorm(ctx) ||
2166 (_mesa_has_EXT_render_snorm(ctx) &&
2167 _mesa_has_EXT_texture_norm16(ctx))
Ian Romanickf0c99d02012-07-27 08:31:12 -07002168 ? GL_RG : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002169 case GL_RGB_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002170 case GL_RGB8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01002171 case GL_RGB16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002172 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2173 ? GL_RGB : 0;
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002174 case GL_RGBA8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002175 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2176 ? GL_RGBA : 0;
2177 case GL_RGBA_SNORM:
2178 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002179 case GL_RGBA16_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002180 return _mesa_has_EXT_texture_snorm(ctx) ||
2181 (_mesa_has_EXT_render_snorm(ctx) &&
2182 _mesa_has_EXT_texture_norm16(ctx))
Ian Romanickf0c99d02012-07-27 08:31:12 -07002183 ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002184 case GL_ALPHA_SNORM:
2185 case GL_ALPHA8_SNORM:
2186 case GL_ALPHA16_SNORM:
Paul Berrydbd61352012-11-27 12:26:51 -08002187 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002188 ctx->Extensions.EXT_texture_snorm &&
Marek Olšák0be36992011-03-18 13:44:51 +01002189 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
Brian Paul513a3242014-01-08 09:05:29 -07002190 case GL_LUMINANCE_SNORM:
2191 case GL_LUMINANCE8_SNORM:
2192 case GL_LUMINANCE16_SNORM:
2193 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2194 ? GL_LUMINANCE : 0;
2195 case GL_LUMINANCE_ALPHA_SNORM:
2196 case GL_LUMINANCE8_ALPHA8_SNORM:
2197 case GL_LUMINANCE16_ALPHA16_SNORM:
2198 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2199 ? GL_LUMINANCE_ALPHA : 0;
2200 case GL_INTENSITY_SNORM:
2201 case GL_INTENSITY8_SNORM:
2202 case GL_INTENSITY16_SNORM:
2203 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2204 ? GL_INTENSITY : 0;
2205
Marek Olšák15f99d12011-02-16 00:35:44 +01002206 case GL_R16F:
2207 case GL_R32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002208 return ((_mesa_is_desktop_gl(ctx) &&
2209 ctx->Extensions.ARB_texture_rg &&
2210 ctx->Extensions.ARB_texture_float) ||
2211 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2212 ? GL_RED : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002213 case GL_RG16F:
2214 case GL_RG32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002215 return ((_mesa_is_desktop_gl(ctx) &&
2216 ctx->Extensions.ARB_texture_rg &&
2217 ctx->Extensions.ARB_texture_float) ||
2218 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2219 ? GL_RG : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002220 case GL_RGB16F:
2221 case GL_RGB32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002222 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002223 ? GL_RGB : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002224 case GL_RGBA16F:
2225 case GL_RGBA32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002226 return ((_mesa_is_desktop_gl(ctx) &&
2227 ctx->Extensions.ARB_texture_float) ||
2228 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Ian Romanickf0c99d02012-07-27 08:31:12 -07002229 ? GL_RGBA : 0;
Juan A. Suarez Romeroe1623b32018-01-15 10:58:50 +00002230 case GL_RGB9_E5:
2231 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_shared_exponent)
2232 ? GL_RGB: 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002233 case GL_ALPHA16F_ARB:
2234 case GL_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002235 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002236 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002237 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2238 case GL_LUMINANCE16F_ARB:
2239 case GL_LUMINANCE32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002240 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002241 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002242 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2243 case GL_LUMINANCE_ALPHA16F_ARB:
2244 case GL_LUMINANCE_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002245 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002246 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002247 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2248 case GL_INTENSITY16F_ARB:
2249 case GL_INTENSITY32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002250 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002251 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002252 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
Marek Olšák631d23d2011-04-26 02:27:25 +02002253 case GL_R11F_G11F_B10F:
Jordan Justen119002a2013-01-10 17:29:27 -08002254 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
2255 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Matt Turnercbef5372012-11-20 13:45:03 -08002256 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002257
2258 case GL_RGBA8UI_EXT:
2259 case GL_RGBA16UI_EXT:
2260 case GL_RGBA32UI_EXT:
2261 case GL_RGBA8I_EXT:
2262 case GL_RGBA16I_EXT:
2263 case GL_RGBA32I_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002264 return ctx->Version >= 30
2265 || (_mesa_is_desktop_gl(ctx) &&
2266 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002267
2268 case GL_RGB8UI_EXT:
2269 case GL_RGB16UI_EXT:
2270 case GL_RGB32UI_EXT:
2271 case GL_RGB8I_EXT:
2272 case GL_RGB16I_EXT:
2273 case GL_RGB32I_EXT:
Ian Romanicka86d6292012-12-03 11:55:12 -08002274 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
2275 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002276 case GL_R8UI:
2277 case GL_R8I:
2278 case GL_R16UI:
2279 case GL_R16I:
2280 case GL_R32UI:
2281 case GL_R32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002282 return ctx->Version >= 30
2283 || (_mesa_is_desktop_gl(ctx) &&
2284 ctx->Extensions.ARB_texture_rg &&
2285 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002286
2287 case GL_RG8UI:
2288 case GL_RG8I:
2289 case GL_RG16UI:
2290 case GL_RG16I:
2291 case GL_RG32UI:
2292 case GL_RG32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002293 return ctx->Version >= 30
2294 || (_mesa_is_desktop_gl(ctx) &&
2295 ctx->Extensions.ARB_texture_rg &&
2296 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
Brian Paul45bd5c42011-12-16 08:44:43 -07002297
Dave Airlie9c697a92011-10-04 20:59:40 +01002298 case GL_INTENSITY8I_EXT:
2299 case GL_INTENSITY8UI_EXT:
2300 case GL_INTENSITY16I_EXT:
2301 case GL_INTENSITY16UI_EXT:
2302 case GL_INTENSITY32I_EXT:
2303 case GL_INTENSITY32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002304 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002305 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002306 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2307
2308 case GL_LUMINANCE8I_EXT:
2309 case GL_LUMINANCE8UI_EXT:
2310 case GL_LUMINANCE16I_EXT:
2311 case GL_LUMINANCE16UI_EXT:
2312 case GL_LUMINANCE32I_EXT:
2313 case GL_LUMINANCE32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002314 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002315 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002316 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2317
2318 case GL_LUMINANCE_ALPHA8I_EXT:
2319 case GL_LUMINANCE_ALPHA8UI_EXT:
2320 case GL_LUMINANCE_ALPHA16I_EXT:
2321 case GL_LUMINANCE_ALPHA16UI_EXT:
2322 case GL_LUMINANCE_ALPHA32I_EXT:
2323 case GL_LUMINANCE_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002324 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002325 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002326 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
Dave Airlief449be62011-11-27 16:21:02 +00002327
Marek Olšák636802f2012-01-22 20:21:36 +01002328 case GL_ALPHA8I_EXT:
2329 case GL_ALPHA8UI_EXT:
2330 case GL_ALPHA16I_EXT:
2331 case GL_ALPHA16UI_EXT:
2332 case GL_ALPHA32I_EXT:
2333 case GL_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002334 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002335 ctx->Extensions.EXT_texture_integer &&
Marek Olšák636802f2012-01-22 20:21:36 +01002336 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2337
Dave Airlief449be62011-11-27 16:21:02 +00002338 case GL_RGB10_A2UI:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002339 return (_mesa_is_desktop_gl(ctx) &&
2340 ctx->Extensions.ARB_texture_rgb10_a2ui)
2341 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Marek Olšák1a06e842012-07-12 14:07:41 +02002342
2343 case GL_RGB565:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002344 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
2345 ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002346 default:
Eric Anholt65c41d52011-01-13 10:05:50 -08002347 return 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002348 }
Brian Paul463642c2005-02-08 02:06:00 +00002349}
2350
2351
Marek Olšákdf818d52011-03-06 05:26:12 +01002352/**
2353 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
2354 */
2355static void
2356invalidate_rb(GLuint key, void *data, void *userData)
2357{
2358 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2359 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
2360
2361 /* If this is a user-created FBO */
Brian Paul36ede892012-01-12 09:17:23 -07002362 if (_mesa_is_user_fbo(fb)) {
Marek Olšákdf818d52011-03-06 05:26:12 +01002363 GLuint i;
2364 for (i = 0; i < BUFFER_COUNT; i++) {
2365 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2366 if (att->Type == GL_RENDERBUFFER &&
2367 att->Renderbuffer == rb) {
2368 /* Mark fb status as indeterminate to force re-validation */
2369 fb->_Status = 0;
Marek Olšáka674ef72011-03-07 23:33:36 +01002370 return;
Marek Olšákdf818d52011-03-06 05:26:12 +01002371 }
2372 }
2373 }
2374}
2375
2376
Brian Paul4f3514e2009-01-22 15:19:56 -07002377/** sentinal value, see below */
2378#define NO_SAMPLES 1000
2379
Ian Romanickeb5bc622015-11-12 09:11:20 -08002380void
2381_mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2382 GLenum internalFormat, GLsizei width,
Marek Olšák2d115052018-06-11 15:26:41 -04002383 GLsizei height, GLsizei samples,
2384 GLsizei storageSamples)
Ian Romanickeb5bc622015-11-12 09:11:20 -08002385{
2386 const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2387
2388 assert(baseFormat != 0);
2389 assert(width >= 0 && width <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2390 assert(height >= 0 && height <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2391 assert(samples != NO_SAMPLES);
2392 if (samples != 0) {
2393 assert(samples > 0);
2394 assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
Marek Olšák2d115052018-06-11 15:26:41 -04002395 internalFormat, samples,
2396 storageSamples) == GL_NO_ERROR);
Ian Romanickeb5bc622015-11-12 09:11:20 -08002397 }
2398
2399 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2400
2401 if (rb->InternalFormat == internalFormat &&
2402 rb->Width == (GLuint) width &&
2403 rb->Height == (GLuint) height &&
Marek Olšák328c1c82018-06-11 17:24:16 -04002404 rb->NumSamples == samples &&
2405 rb->NumStorageSamples == storageSamples) {
Ian Romanickeb5bc622015-11-12 09:11:20 -08002406 /* no change in allocation needed */
2407 return;
2408 }
2409
2410 /* These MUST get set by the AllocStorage func */
2411 rb->Format = MESA_FORMAT_NONE;
2412 rb->NumSamples = samples;
Marek Olšák328c1c82018-06-11 17:24:16 -04002413 rb->NumStorageSamples = storageSamples;
Ian Romanickeb5bc622015-11-12 09:11:20 -08002414
2415 /* Now allocate the storage */
2416 assert(rb->AllocStorage);
2417 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
2418 /* No error - check/set fields now */
2419 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
2420 assert(rb->Width == (GLuint) width);
2421 assert(rb->Height == (GLuint) height);
2422 rb->InternalFormat = internalFormat;
2423 rb->_BaseFormat = baseFormat;
2424 assert(rb->_BaseFormat != 0);
2425 }
2426 else {
2427 /* Probably ran out of memory - clear the fields */
2428 rb->Width = 0;
2429 rb->Height = 0;
2430 rb->Format = MESA_FORMAT_NONE;
2431 rb->InternalFormat = GL_NONE;
2432 rb->_BaseFormat = GL_NONE;
2433 rb->NumSamples = 0;
Marek Olšák328c1c82018-06-11 17:24:16 -04002434 rb->NumStorageSamples = 0;
Ian Romanickeb5bc622015-11-12 09:11:20 -08002435 }
2436
2437 /* Invalidate the framebuffers the renderbuffer is attached in. */
2438 if (rb->AttachedAnytime) {
2439 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
2440 }
2441}
Brian Paul4f3514e2009-01-22 15:19:56 -07002442
2443/**
Martin Peresbf11c192015-02-13 15:35:48 +02002444 * Helper function used by renderbuffer_storage_direct() and
2445 * renderbuffer_storage_target().
2446 * samples will be NO_SAMPLES if called by a non-multisample function.
Brian Paul4f3514e2009-01-22 15:19:56 -07002447 */
2448static void
Martin Peresbf11c192015-02-13 15:35:48 +02002449renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2450 GLenum internalFormat, GLsizei width,
Marek Olšák2d115052018-06-11 15:26:41 -04002451 GLsizei height, GLsizei samples, GLsizei storageSamples,
2452 const char *func)
Brian Paulddc82ee2005-02-05 19:56:45 +00002453{
Brian Paul463642c2005-02-08 02:06:00 +00002454 GLenum baseFormat;
Chris Forbes90b5a242013-02-06 20:42:53 +13002455 GLenum sample_count_error;
Brian Paulddc82ee2005-02-05 19:56:45 +00002456
Brian Paul59e0faa2006-03-15 17:48:00 +00002457 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
Brian Paul463642c2005-02-08 02:06:00 +00002458 if (baseFormat == 0) {
Jordan Justen119002a2013-01-10 17:29:27 -08002459 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002460 func, _mesa_enum_to_string(internalFormat));
Brian Paulddc82ee2005-02-05 19:56:45 +00002461 return;
2462 }
2463
Yuanhan Liu49f84472011-10-25 15:36:59 +08002464 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Martin Peresbf11c192015-02-13 15:35:48 +02002465 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
2466 width);
Brian Paulddc82ee2005-02-05 19:56:45 +00002467 return;
2468 }
2469
Yuanhan Liu49f84472011-10-25 15:36:59 +08002470 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Martin Peresbf11c192015-02-13 15:35:48 +02002471 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
2472 height);
Brian Paul4f3514e2009-01-22 15:19:56 -07002473 return;
2474 }
2475
2476 if (samples == NO_SAMPLES) {
2477 /* NumSamples == 0 indicates non-multisampling */
2478 samples = 0;
Marek Olšák2d115052018-06-11 15:26:41 -04002479 storageSamples = 0;
Brian Paul4f3514e2009-01-22 15:19:56 -07002480 }
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002481 else {
2482 /* check the sample count;
2483 * note: driver may choose to use more samples than what's requested
2484 */
Martin Peresbf11c192015-02-13 15:35:48 +02002485 sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
Marek Olšák2d115052018-06-11 15:26:41 -04002486 internalFormat, samples, storageSamples);
Timothy Arceri46684d32015-08-13 18:44:51 +10002487
2488 /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
2489 *
2490 * "If a negative number is provided where an argument of type sizei or
2491 * sizeiptr is specified, the error INVALID VALUE is generated."
2492 */
Marek Olšák2d115052018-06-11 15:26:41 -04002493 if (samples < 0 || storageSamples < 0) {
Timothy Arceri46684d32015-08-13 18:44:51 +10002494 sample_count_error = GL_INVALID_VALUE;
2495 }
2496
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002497 if (sample_count_error != GL_NO_ERROR) {
Marek Olšák2d115052018-06-11 15:26:41 -04002498 _mesa_error(ctx, sample_count_error,
2499 "%s(samples=%d, storageSamples=%d)", func, samples,
2500 storageSamples);
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002501 return;
2502 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002503 }
2504
Marek Olšák2d115052018-06-11 15:26:41 -04002505 _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2506 storageSamples);
Brian Paulddc82ee2005-02-05 19:56:45 +00002507}
2508
Martin Peresbf11c192015-02-13 15:35:48 +02002509/**
2510 * Helper function used by _mesa_NamedRenderbufferStorage*().
2511 * samples will be NO_SAMPLES if called by a non-multisample function.
2512 */
2513static void
2514renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
2515 GLsizei width, GLsizei height, GLsizei samples,
Marek Olšák2d115052018-06-11 15:26:41 -04002516 GLsizei storageSamples, const char *func)
Martin Peresbf11c192015-02-13 15:35:48 +02002517{
2518 GET_CURRENT_CONTEXT(ctx);
2519
2520 if (MESA_VERBOSE & VERBOSE_API) {
2521 if (samples == NO_SAMPLES)
2522 _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
2523 func, renderbuffer,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002524 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002525 width, height);
2526 else
2527 _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
2528 func, renderbuffer,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002529 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002530 width, height, samples);
2531 }
2532
2533 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2534 if (!rb || rb == &DummyRenderbuffer) {
2535 /* ID was reserved, but no real renderbuffer object made yet */
2536 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
2537 func, renderbuffer);
2538 return;
2539 }
2540
Marek Olšák2d115052018-06-11 15:26:41 -04002541 renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2542 storageSamples, func);
Martin Peresbf11c192015-02-13 15:35:48 +02002543}
2544
2545/**
2546 * Helper function used by _mesa_RenderbufferStorage() and
2547 * _mesa_RenderbufferStorageMultisample().
2548 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
2549 */
2550static void
2551renderbuffer_storage_target(GLenum target, GLenum internalFormat,
2552 GLsizei width, GLsizei height, GLsizei samples,
Marek Olšák2d115052018-06-11 15:26:41 -04002553 GLsizei storageSamples, const char *func)
Martin Peresbf11c192015-02-13 15:35:48 +02002554{
2555 GET_CURRENT_CONTEXT(ctx);
2556
2557 if (MESA_VERBOSE & VERBOSE_API) {
2558 if (samples == NO_SAMPLES)
2559 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
2560 func,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002561 _mesa_enum_to_string(target),
2562 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002563 width, height);
2564 else
2565 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
2566 func,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002567 _mesa_enum_to_string(target),
2568 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002569 width, height, samples);
2570 }
2571
2572 if (target != GL_RENDERBUFFER_EXT) {
2573 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
2574 return;
2575 }
2576
2577 if (!ctx->CurrentRenderbuffer) {
2578 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
2579 func);
2580 return;
2581 }
2582
2583 renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
Marek Olšák2d115052018-06-11 15:26:41 -04002584 height, samples, storageSamples, func);
Martin Peresbf11c192015-02-13 15:35:48 +02002585}
2586
Brian Paul23c5b212010-05-28 13:33:03 -06002587
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002588void GLAPIENTRY
Brian Paul23c5b212010-05-28 13:33:03 -06002589_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002590{
Brian Paul51b79922010-02-24 11:57:26 -07002591 struct gl_renderbuffer *rb;
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002592 GET_CURRENT_CONTEXT(ctx);
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002593
Chia-I Wu2002e4d02010-04-06 17:46:17 +08002594 if (!ctx->Extensions.OES_EGL_image) {
2595 _mesa_error(ctx, GL_INVALID_OPERATION,
2596 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
2597 return;
2598 }
2599
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002600 if (target != GL_RENDERBUFFER) {
Brian Paul23c5b212010-05-28 13:33:03 -06002601 _mesa_error(ctx, GL_INVALID_ENUM,
2602 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002603 return;
2604 }
2605
2606 rb = ctx->CurrentRenderbuffer;
2607 if (!rb) {
Brian Paul23c5b212010-05-28 13:33:03 -06002608 _mesa_error(ctx, GL_INVALID_OPERATION,
2609 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002610 return;
2611 }
2612
2613 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2614
2615 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
2616}
Brian Paulddc82ee2005-02-05 19:56:45 +00002617
Brian Paul23c5b212010-05-28 13:33:03 -06002618
Brian Paul45e76d22009-10-08 20:27:27 -06002619/**
Paul Berry1a1db172012-11-06 08:57:59 -08002620 * Helper function for _mesa_GetRenderbufferParameteriv() and
2621 * _mesa_GetFramebufferAttachmentParameteriv()
Brian Paul45e76d22009-10-08 20:27:27 -06002622 * We have to be careful to respect the base format. For example, if a
2623 * renderbuffer/texture was created with internalFormat=GL_RGB but the
2624 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
2625 * we need to return zero.
2626 */
2627static GLint
Mark Mueller71fe9432014-01-04 14:11:43 -08002628get_component_bits(GLenum pname, GLenum baseFormat, mesa_format format)
Brian Paul45e76d22009-10-08 20:27:27 -06002629{
Brian Paulf0b6e9a2011-11-23 15:33:45 -07002630 if (_mesa_base_format_has_channel(baseFormat, pname))
2631 return _mesa_get_format_bits(format, pname);
2632 else
Brian Paul45e76d22009-10-08 20:27:27 -06002633 return 0;
Brian Paul45e76d22009-10-08 20:27:27 -06002634}
2635
2636
2637
Brian Paul1864c7d2005-02-08 03:46:37 +00002638void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002639_mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
Brian Paul4f3514e2009-01-22 15:19:56 -07002640 GLsizei width, GLsizei height)
2641{
Brian Paul722d9762009-01-20 16:58:49 -07002642 /* GL_ARB_fbo says calling this function is equivalent to calling
2643 * glRenderbufferStorageMultisample() with samples=0. We pass in
2644 * a token value here just for error reporting purposes.
2645 */
Martin Peresbf11c192015-02-13 15:35:48 +02002646 renderbuffer_storage_target(target, internalFormat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002647 NO_SAMPLES, 0, "glRenderbufferStorage");
Brian Paul4f3514e2009-01-22 15:19:56 -07002648}
2649
2650
2651void GLAPIENTRY
Brian Paul777a2ef2009-01-22 15:17:42 -07002652_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
Brian Paul4f3514e2009-01-22 15:19:56 -07002653 GLenum internalFormat,
Brian Paul777a2ef2009-01-22 15:17:42 -07002654 GLsizei width, GLsizei height)
2655{
Martin Peresbf11c192015-02-13 15:35:48 +02002656 renderbuffer_storage_target(target, internalFormat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002657 samples, samples,
2658 "glRenderbufferStorageMultisample");
Brian Paul777a2ef2009-01-22 15:17:42 -07002659}
2660
Brian Paul23c5b212010-05-28 13:33:03 -06002661
Marek Olšák3d6900d2018-06-28 02:05:12 -04002662void GLAPIENTRY
2663_mesa_RenderbufferStorageMultisampleAdvancedAMD(
2664 GLenum target, GLsizei samples, GLsizei storageSamples,
2665 GLenum internalFormat, GLsizei width, GLsizei height)
2666{
2667 renderbuffer_storage_target(target, internalFormat, width, height,
2668 samples, storageSamples,
2669 "glRenderbufferStorageMultisampleAdvancedAMD");
2670}
2671
2672
Brian Paul23c5b212010-05-28 13:33:03 -06002673/**
2674 * OpenGL ES version of glRenderBufferStorage.
2675 */
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002676void GLAPIENTRY
2677_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
Martin Peres7bd8b482015-02-12 17:54:43 +02002678 GLsizei width, GLsizei height)
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002679{
2680 switch (internalFormat) {
2681 case GL_RGB565:
2682 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
2683 /* choose a closest format */
2684 internalFormat = GL_RGB5;
2685 break;
2686 default:
2687 break;
2688 }
Brian Paul777a2ef2009-01-22 15:17:42 -07002689
Marek Olšák2d115052018-06-11 15:26:41 -04002690 renderbuffer_storage_target(target, internalFormat, width, height, 0, 0,
Martin Peresbf11c192015-02-13 15:35:48 +02002691 "glRenderbufferStorageEXT");
2692}
2693
2694void GLAPIENTRY
2695_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
2696 GLsizei width, GLsizei height)
2697{
2698 /* GL_ARB_fbo says calling this function is equivalent to calling
2699 * glRenderbufferStorageMultisample() with samples=0. We pass in
2700 * a token value here just for error reporting purposes.
2701 */
2702 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002703 NO_SAMPLES, 0, "glNamedRenderbufferStorage");
Martin Peresbf11c192015-02-13 15:35:48 +02002704}
2705
2706void GLAPIENTRY
Pierre-Eric Pelloux-Prayer01666ad2019-05-23 16:34:16 +02002707_mesa_NamedRenderbufferStorageEXT(GLuint renderbuffer, GLenum internalformat,
2708 GLsizei width, GLsizei height)
2709{
2710 GET_CURRENT_CONTEXT(ctx);
2711 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2712 if (!rb || rb == &DummyRenderbuffer) {
2713 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2714 rb = allocate_renderbuffer_locked(ctx, renderbuffer, "glNamedRenderbufferStorageEXT");
2715 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2716 }
2717 renderbuffer_storage(ctx, rb, internalformat, width, height, NO_SAMPLES,
2718 0, "glNamedRenderbufferStorageEXT");
2719}
2720
2721
2722void GLAPIENTRY
Martin Peresbf11c192015-02-13 15:35:48 +02002723_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
2724 GLenum internalformat,
2725 GLsizei width, GLsizei height)
2726{
2727 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002728 samples, samples,
Martin Peresbf11c192015-02-13 15:35:48 +02002729 "glNamedRenderbufferStorageMultisample");
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002730}
Brian Paul777a2ef2009-01-22 15:17:42 -07002731
Brian Paul23c5b212010-05-28 13:33:03 -06002732
Marek Olšák3d6900d2018-06-28 02:05:12 -04002733void GLAPIENTRY
Pierre-Eric Pelloux-Prayerda214352019-09-11 10:13:21 +02002734_mesa_NamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer, GLsizei samples,
2735 GLenum internalformat,
2736 GLsizei width, GLsizei height)
2737{
2738 GET_CURRENT_CONTEXT(ctx);
2739 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2740 if (!rb || rb == &DummyRenderbuffer) {
2741 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2742 rb = allocate_renderbuffer_locked(ctx, renderbuffer,
2743 "glNamedRenderbufferStorageMultisampleEXT");
2744 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2745 }
2746 renderbuffer_storage(ctx, rb, internalformat, width, height,
2747 samples, samples,
2748 "glNamedRenderbufferStorageMultisample");
2749}
2750
2751
2752void GLAPIENTRY
Marek Olšák3d6900d2018-06-28 02:05:12 -04002753_mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
2754 GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
2755 GLenum internalformat, GLsizei width, GLsizei height)
2756{
2757 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2758 samples, storageSamples,
2759 "glNamedRenderbufferStorageMultisampleAdvancedAMD");
2760}
2761
2762
Martin Peres245e5c42015-02-13 15:46:55 +02002763static void
2764get_render_buffer_parameteriv(struct gl_context *ctx,
2765 struct gl_renderbuffer *rb, GLenum pname,
2766 GLint *params, const char *func)
Brian Paulddc82ee2005-02-05 19:56:45 +00002767{
Brian Paul800e5532009-11-02 15:39:39 -07002768 /* No need to flush here since we're just quering state which is
2769 * not effected by rendering.
2770 */
Brian Paul474f28e2005-10-08 14:41:17 +00002771
Brian Paul463642c2005-02-08 02:06:00 +00002772 switch (pname) {
2773 case GL_RENDERBUFFER_WIDTH_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002774 *params = rb->Width;
Brian Paul463642c2005-02-08 02:06:00 +00002775 return;
2776 case GL_RENDERBUFFER_HEIGHT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002777 *params = rb->Height;
Brian Paul463642c2005-02-08 02:06:00 +00002778 return;
2779 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002780 *params = rb->InternalFormat;
Brian Paul463642c2005-02-08 02:06:00 +00002781 return;
Brian Paul1b939532005-05-31 23:55:21 +00002782 case GL_RENDERBUFFER_RED_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002783 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002784 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002785 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002786 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002787 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
Brian Paul45e76d22009-10-08 20:27:27 -06002788 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
Marek Olšák328c1c82018-06-11 17:24:16 -04002789 return;
Brian Paul722d9762009-01-20 16:58:49 -07002790 case GL_RENDERBUFFER_SAMPLES:
Ian Romanickae86ebf2012-07-27 07:49:49 -07002791 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
2792 || _mesa_is_gles3(ctx)) {
Brian Paul722d9762009-01-20 16:58:49 -07002793 *params = rb->NumSamples;
Marek Olšák328c1c82018-06-11 17:24:16 -04002794 return;
Brian Paul722d9762009-01-20 16:58:49 -07002795 }
Marek Olšák328c1c82018-06-11 17:24:16 -04002796 break;
2797 case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
2798 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
2799 *params = rb->NumStorageSamples;
2800 return;
2801 }
2802 break;
Martin Peres245e5c42015-02-13 15:46:55 +02002803 }
Marek Olšák328c1c82018-06-11 17:24:16 -04002804
2805 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
2806 _mesa_enum_to_string(pname));
Martin Peres245e5c42015-02-13 15:46:55 +02002807}
2808
2809
2810void GLAPIENTRY
2811_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
2812{
2813 GET_CURRENT_CONTEXT(ctx);
2814
2815 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul463642c2005-02-08 02:06:00 +00002816 _mesa_error(ctx, GL_INVALID_ENUM,
2817 "glGetRenderbufferParameterivEXT(target)");
2818 return;
2819 }
Martin Peres245e5c42015-02-13 15:46:55 +02002820
2821 if (!ctx->CurrentRenderbuffer) {
2822 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
2823 "(no renderbuffer bound)");
2824 return;
2825 }
2826
2827 get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
2828 params, "glGetRenderbufferParameteriv");
2829}
2830
2831
2832void GLAPIENTRY
2833_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
2834 GLint *params)
2835{
2836 GET_CURRENT_CONTEXT(ctx);
2837
2838 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2839 if (!rb || rb == &DummyRenderbuffer) {
2840 /* ID was reserved, but no real renderbuffer object made yet */
2841 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
2842 "(invalid renderbuffer %i)", renderbuffer);
2843 return;
2844 }
2845
2846 get_render_buffer_parameteriv(ctx, rb, pname, params,
2847 "glGetNamedRenderbufferParameteriv");
Brian Paulddc82ee2005-02-05 19:56:45 +00002848}
2849
2850
Pierre-Eric Pelloux-Prayer01666ad2019-05-23 16:34:16 +02002851void GLAPIENTRY
2852_mesa_GetNamedRenderbufferParameterivEXT(GLuint renderbuffer, GLenum pname,
2853 GLint *params)
2854{
2855 GET_CURRENT_CONTEXT(ctx);
2856
2857 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2858 if (!rb || rb == &DummyRenderbuffer) {
2859 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2860 rb = allocate_renderbuffer_locked(ctx, renderbuffer, "glGetNamedRenderbufferParameterivEXT");
2861 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2862 }
2863
2864 get_render_buffer_parameteriv(ctx, rb, pname, params,
2865 "glGetNamedRenderbufferParameterivEXT");
2866}
2867
2868
Brian Paul1864c7d2005-02-08 03:46:37 +00002869GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002870_mesa_IsFramebuffer(GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00002871{
Brian Paulddc82ee2005-02-05 19:56:45 +00002872 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +00002873 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Brian Paulbc6cced2005-10-04 15:01:27 +00002874 if (framebuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00002875 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
Brian Paulbc6cced2005-10-04 15:01:27 +00002876 if (rb != NULL && rb != &DummyFramebuffer)
2877 return GL_TRUE;
2878 }
2879 return GL_FALSE;
Brian Paulddc82ee2005-02-05 19:56:45 +00002880}
2881
2882
briana492ab72009-11-10 15:33:31 -07002883/**
2884 * Check if any of the attachments of the given framebuffer are textures
2885 * (render to texture). Call ctx->Driver.RenderTexture() for such
2886 * attachments.
2887 */
Brian Paulea4fe662006-03-26 05:22:17 +00002888static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002889check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paulea4fe662006-03-26 05:22:17 +00002890{
2891 GLuint i;
Matt Turnerbfcdb842015-02-20 20:18:47 -08002892 assert(ctx->Driver.RenderTexture);
briana65b84d2009-11-10 18:02:03 -07002893
Brian Paul36ede892012-01-12 09:17:23 -07002894 if (_mesa_is_winsys_fbo(fb))
briana65b84d2009-11-10 18:02:03 -07002895 return; /* can't render to texture with winsys framebuffers */
2896
Brian Paulea4fe662006-03-26 05:22:17 +00002897 for (i = 0; i < BUFFER_COUNT; i++) {
2898 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Ian Romanickfb497132013-07-27 12:04:20 -07002899 if (att->Texture && att->Renderbuffer->TexImage
2900 && driver_RenderTexture_is_safe(att)) {
Brian Paulea4fe662006-03-26 05:22:17 +00002901 ctx->Driver.RenderTexture(ctx, fb, att);
2902 }
2903 }
2904}
2905
2906
Brian Paul0e31e022005-12-01 00:25:00 +00002907/**
2908 * Examine all the framebuffer's attachments to see if any are textures.
2909 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
2910 * notify the device driver that the texture image may have changed.
2911 */
2912static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002913check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paul0e31e022005-12-01 00:25:00 +00002914{
Eric Anholt7ccb26f2014-03-03 09:16:48 -08002915 /* Skip if we know NeedsFinishRenderTexture won't be set. */
2916 if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
2917 return;
briana65b84d2009-11-10 18:02:03 -07002918
Brian Paul0e31e022005-12-01 00:25:00 +00002919 if (ctx->Driver.FinishRenderTexture) {
2920 GLuint i;
2921 for (i = 0; i < BUFFER_COUNT; i++) {
2922 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Eric Anholtc810e672013-05-10 12:36:43 -07002923 struct gl_renderbuffer *rb = att->Renderbuffer;
2924 if (rb && rb->NeedsFinishRenderTexture) {
Eric Anholta5b04522013-05-10 12:17:52 -07002925 ctx->Driver.FinishRenderTexture(ctx, rb);
Brian Paul0e31e022005-12-01 00:25:00 +00002926 }
2927 }
2928 }
2929}
2930
2931
Ian Romanick4a9522a2013-07-18 17:39:22 -07002932static void
Timothy Arcerib54a2312018-09-08 14:20:17 +10002933bind_framebuffer(GLenum target, GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00002934{
briane6f60d32009-11-10 15:47:34 -07002935 struct gl_framebuffer *newDrawFb, *newReadFb;
Brian Paul0bffb112005-11-08 14:45:48 +00002936 GLboolean bindReadBuf, bindDrawBuf;
Brian Paulddc82ee2005-02-05 19:56:45 +00002937 GET_CURRENT_CONTEXT(ctx);
2938
Brian Paul0bffb112005-11-08 14:45:48 +00002939 switch (target) {
Brian Paul0bffb112005-11-08 14:45:48 +00002940 case GL_DRAW_FRAMEBUFFER_EXT:
Brian Paul0bffb112005-11-08 14:45:48 +00002941 bindDrawBuf = GL_TRUE;
2942 bindReadBuf = GL_FALSE;
2943 break;
2944 case GL_READ_FRAMEBUFFER_EXT:
Brian Paul0bffb112005-11-08 14:45:48 +00002945 bindDrawBuf = GL_FALSE;
2946 bindReadBuf = GL_TRUE;
2947 break;
Brian Paul0bffb112005-11-08 14:45:48 +00002948 case GL_FRAMEBUFFER_EXT:
2949 bindDrawBuf = GL_TRUE;
2950 bindReadBuf = GL_TRUE;
2951 break;
2952 default:
Brian Pauleba4ff62005-09-06 21:22:16 +00002953 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00002954 return;
2955 }
2956
Brian Paul3deaa012005-02-07 05:08:24 +00002957 if (framebuffer) {
Brian Paule4b23562005-05-04 20:11:35 +00002958 /* Binding a user-created framebuffer object */
briane6f60d32009-11-10 15:47:34 -07002959 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
2960 if (newDrawFb == &DummyFramebuffer) {
Brian Paul923b6fc2005-02-08 04:08:56 +00002961 /* ID was reserved, but no real framebuffer object made yet */
briane6f60d32009-11-10 15:47:34 -07002962 newDrawFb = NULL;
Brian Paul1864c7d2005-02-08 03:46:37 +00002963 }
Timothy Arcerib54a2312018-09-08 14:20:17 +10002964 else if (!newDrawFb && ctx->API == API_OPENGL_CORE) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07002965 /* All FBO IDs must be Gen'd */
Timothy Arcerib54a2312018-09-08 14:20:17 +10002966 _mesa_error(ctx, GL_INVALID_OPERATION,
2967 "glBindFramebuffer(non-gen name)");
Brian Paul1bc59bf2009-01-22 15:07:34 -07002968 return;
2969 }
2970
briane6f60d32009-11-10 15:47:34 -07002971 if (!newDrawFb) {
Martin Peres7bd8b482015-02-12 17:54:43 +02002972 /* create new framebuffer object */
2973 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
2974 if (!newDrawFb) {
2975 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
2976 return;
2977 }
briane6f60d32009-11-10 15:47:34 -07002978 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
Brian Paul3deaa012005-02-07 05:08:24 +00002979 }
briane6f60d32009-11-10 15:47:34 -07002980 newReadFb = newDrawFb;
Brian Paul3deaa012005-02-07 05:08:24 +00002981 }
Brian Paul463642c2005-02-08 02:06:00 +00002982 else {
Brian Paule4b23562005-05-04 20:11:35 +00002983 /* Binding the window system framebuffer (which was originally set
2984 * with MakeCurrent).
2985 */
briane6f60d32009-11-10 15:47:34 -07002986 newDrawFb = ctx->WinSysDrawBuffer;
2987 newReadFb = ctx->WinSysReadBuffer;
Brian Paul3deaa012005-02-07 05:08:24 +00002988 }
2989
Ian Romanickfed9b0e2015-11-13 10:46:40 -08002990 _mesa_bind_framebuffers(ctx,
2991 bindDrawBuf ? newDrawFb : ctx->DrawBuffer,
2992 bindReadBuf ? newReadFb : ctx->ReadBuffer);
2993}
2994
2995void
2996_mesa_bind_framebuffers(struct gl_context *ctx,
2997 struct gl_framebuffer *newDrawFb,
2998 struct gl_framebuffer *newReadFb)
2999{
3000 struct gl_framebuffer *const oldDrawFb = ctx->DrawBuffer;
3001 struct gl_framebuffer *const oldReadFb = ctx->ReadBuffer;
3002 const bool bindDrawBuf = oldDrawFb != newDrawFb;
3003 const bool bindReadBuf = oldReadFb != newReadFb;
3004
Matt Turnerbfcdb842015-02-20 20:18:47 -08003005 assert(newDrawFb);
3006 assert(newDrawFb != &DummyFramebuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00003007
Brian Paulea4fe662006-03-26 05:22:17 +00003008 /*
Brian Paul16144632009-02-26 14:49:24 -07003009 * OK, now bind the new Draw/Read framebuffers, if they're changing.
briana65b84d2009-11-10 18:02:03 -07003010 *
3011 * We also check if we're beginning and/or ending render-to-texture.
3012 * When a framebuffer with texture attachments is unbound, call
3013 * ctx->Driver.FinishRenderTexture().
3014 * When a framebuffer with texture attachments is bound, call
3015 * ctx->Driver.RenderTexture().
3016 *
3017 * Note that if the ReadBuffer has texture attachments we don't consider
3018 * that a render-to-texture case.
Brian Paulea4fe662006-03-26 05:22:17 +00003019 */
Brian Paul0bffb112005-11-08 14:45:48 +00003020 if (bindReadBuf) {
briana65b84d2009-11-10 18:02:03 -07003021 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
brianbc569cd2009-11-10 16:00:35 -07003022
briana65b84d2009-11-10 18:02:03 -07003023 /* check if old readbuffer was render-to-texture */
3024 check_end_texture_render(ctx, oldReadFb);
3025
3026 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
Brian Paul0bffb112005-11-08 14:45:48 +00003027 }
3028
3029 if (bindDrawBuf) {
briana65b84d2009-11-10 18:02:03 -07003030 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Rhys Perry67f40da2018-06-14 19:56:28 -06003031 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
Brian32d86eb2007-08-16 18:52:48 +01003032
Eric Anholta1fd13f2012-02-10 12:05:16 -08003033 /* check if old framebuffer had any texture attachments */
3034 if (oldDrawFb)
briana65b84d2009-11-10 18:02:03 -07003035 check_end_texture_render(ctx, oldDrawFb);
brianbc569cd2009-11-10 16:00:35 -07003036
briana65b84d2009-11-10 18:02:03 -07003037 /* check if newly bound framebuffer has any texture attachments */
3038 check_begin_texture_render(ctx, newDrawFb);
3039
3040 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
Marek Olšák8c053e52020-01-30 18:56:22 -05003041 _mesa_update_allow_draw_out_of_order(ctx);
Brian Paul0bffb112005-11-08 14:45:48 +00003042 }
Brian Paul59e0faa2006-03-15 17:48:00 +00003043
Brian Paul16144632009-02-26 14:49:24 -07003044 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
Ian Romanickfed9b0e2015-11-13 10:46:40 -08003045 /* The few classic drivers that actually hook this function really only
3046 * want to know if the draw framebuffer changed.
3047 */
3048 ctx->Driver.BindFramebuffer(ctx,
3049 bindDrawBuf ? GL_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
3050 newDrawFb, newReadFb);
Brian Paul59e0faa2006-03-15 17:48:00 +00003051 }
Brian Paulddc82ee2005-02-05 19:56:45 +00003052}
3053
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003054void GLAPIENTRY
Ian Romanick4a9522a2013-07-18 17:39:22 -07003055_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003056{
Ian Romanick4a9522a2013-07-18 17:39:22 -07003057 /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
3058 * point, but they allow the use of user-generated names.
3059 */
Timothy Arcerib54a2312018-09-08 14:20:17 +10003060 bind_framebuffer(target, framebuffer);
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003061}
3062
Brian Paulc1377ed2014-03-22 10:31:58 -06003063
Ian Romanick4a9522a2013-07-18 17:39:22 -07003064void GLAPIENTRY
3065_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
3066{
Timothy Arcerib54a2312018-09-08 14:20:17 +10003067 bind_framebuffer(target, framebuffer);
Ian Romanick4a9522a2013-07-18 17:39:22 -07003068}
Brian Paulddc82ee2005-02-05 19:56:45 +00003069
Brian Paulc1377ed2014-03-22 10:31:58 -06003070
Brian Paul1864c7d2005-02-08 03:46:37 +00003071void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003072_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00003073{
3074 GLint i;
3075 GET_CURRENT_CONTEXT(ctx);
3076
Eduardo Lima Mitevf77a4732014-12-11 23:34:17 +01003077 if (n < 0) {
3078 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
3079 return;
3080 }
3081
Brian Paul800e5532009-11-02 15:39:39 -07003082 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00003083
3084 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00003085 if (framebuffers[i] > 0) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003086 struct gl_framebuffer *fb;
3087 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
3088 if (fb) {
Matt Turnerbfcdb842015-02-20 20:18:47 -08003089 assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
Brian Paul91802fd2005-10-04 16:01:02 +00003090
3091 /* check if deleting currently bound framebuffer object */
Ian Romanick764be9f2013-11-13 14:00:06 -08003092 if (fb == ctx->DrawBuffer) {
3093 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08003094 assert(fb->RefCount >= 2);
Ian Romanick764be9f2013-11-13 14:00:06 -08003095 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3096 }
3097 if (fb == ctx->ReadBuffer) {
3098 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08003099 assert(fb->RefCount >= 2);
Ian Romanick764be9f2013-11-13 14:00:06 -08003100 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
3101 }
Brian Paul91802fd2005-10-04 16:01:02 +00003102
Martin Peres7bd8b482015-02-12 17:54:43 +02003103 /* remove from hash table immediately, to free the ID */
3104 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00003105
Brian Paul1864c7d2005-02-08 03:46:37 +00003106 if (fb != &DummyFramebuffer) {
3107 /* But the object will not be freed until it's no longer
3108 * bound in any context.
3109 */
Brian Pauld5229442009-02-09 08:30:55 -07003110 _mesa_reference_framebuffer(&fb, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02003111 }
3112 }
Brian Paulddc82ee2005-02-05 19:56:45 +00003113 }
3114 }
3115}
3116
3117
Laura Ekstrandf868de72015-01-23 14:54:48 -08003118/**
3119 * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
3120 * It is not exposed to the rest of Mesa to encourage the use of
3121 * nameless buffers in driver internals.
3122 */
3123static void
3124create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
Brian Paulddc82ee2005-02-05 19:56:45 +00003125{
3126 GET_CURRENT_CONTEXT(ctx);
3127 GLuint first;
3128 GLint i;
Laura Ekstrandf868de72015-01-23 14:54:48 -08003129 struct gl_framebuffer *fb;
3130
3131 const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
Brian Paulddc82ee2005-02-05 19:56:45 +00003132
Brian Paulddc82ee2005-02-05 19:56:45 +00003133 if (n < 0) {
Laura Ekstrandf868de72015-01-23 14:54:48 -08003134 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00003135 return;
3136 }
3137
3138 if (!framebuffers)
3139 return;
3140
Matt Turner015f2202015-07-30 14:31:04 -07003141 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
3142
Brian Paulddc82ee2005-02-05 19:56:45 +00003143 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
3144
3145 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00003146 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00003147 framebuffers[i] = name;
Laura Ekstrandf868de72015-01-23 14:54:48 -08003148
3149 if (dsa) {
3150 fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
3151 if (!fb) {
Matt Turnerbdc9c202016-05-22 07:00:34 -07003152 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
Laura Ekstrandf868de72015-01-23 14:54:48 -08003153 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
3154 return;
3155 }
3156 }
3157 else
3158 fb = &DummyFramebuffer;
3159
Matt Turner015f2202015-07-30 14:31:04 -07003160 _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, name, fb);
Brian Paulddc82ee2005-02-05 19:56:45 +00003161 }
Matt Turner015f2202015-07-30 14:31:04 -07003162
3163 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
Brian Paulddc82ee2005-02-05 19:56:45 +00003164}
3165
3166
Laura Ekstrandf868de72015-01-23 14:54:48 -08003167void GLAPIENTRY
3168_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
3169{
3170 create_framebuffers(n, framebuffers, false);
3171}
3172
3173
3174void GLAPIENTRY
3175_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
3176{
3177 create_framebuffers(n, framebuffers, true);
3178}
3179
3180
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003181GLenum
3182_mesa_check_framebuffer_status(struct gl_context *ctx,
3183 struct gl_framebuffer *buffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00003184{
Brian Paule4b23562005-05-04 20:11:35 +00003185 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00003186
Brian Paul36ede892012-01-12 09:17:23 -07003187 if (_mesa_is_winsys_fbo(buffer)) {
Matt Turner8dd15e62013-07-26 16:36:19 -07003188 /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
3189 if (buffer != &IncompleteFramebuffer) {
3190 return GL_FRAMEBUFFER_COMPLETE_EXT;
3191 } else {
3192 return GL_FRAMEBUFFER_UNDEFINED;
3193 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00003194 }
3195
Brian Paul800e5532009-11-02 15:39:39 -07003196 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00003197
Brian Paul72966362009-01-21 16:28:38 -07003198 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
3199 _mesa_test_framebuffer_completeness(ctx, buffer);
3200 }
3201
Brian Paul0bffb112005-11-08 14:45:48 +00003202 return buffer->_Status;
Brian Paulddc82ee2005-02-05 19:56:45 +00003203}
3204
Brian Paul45bd5c42011-12-16 08:44:43 -07003205
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003206GLenum GLAPIENTRY
Samuel Pitoiset78d35102017-06-26 14:16:41 +02003207_mesa_CheckFramebufferStatus_no_error(GLenum target)
3208{
3209 GET_CURRENT_CONTEXT(ctx);
3210
3211 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3212 return _mesa_check_framebuffer_status(ctx, fb);
3213}
3214
3215
3216GLenum GLAPIENTRY
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003217_mesa_CheckFramebufferStatus(GLenum target)
3218{
3219 struct gl_framebuffer *fb;
3220 GET_CURRENT_CONTEXT(ctx);
3221
3222 if (MESA_VERBOSE & VERBOSE_API)
3223 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003224 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003225
3226 fb = get_framebuffer_target(ctx, target);
3227 if (!fb) {
3228 _mesa_error(ctx, GL_INVALID_ENUM,
3229 "glCheckFramebufferStatus(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003230 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003231 return 0;
3232 }
3233
3234 return _mesa_check_framebuffer_status(ctx, fb);
3235}
3236
3237
3238GLenum GLAPIENTRY
3239_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
3240{
3241 struct gl_framebuffer *fb;
3242 GET_CURRENT_CONTEXT(ctx);
3243
3244 /* Validate the target (for conformance's sake) and grab a reference to the
3245 * default framebuffer in case framebuffer = 0.
3246 * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
3247 * (30.10.2014, PDF page 336) says:
3248 * "If framebuffer is zero, then the status of the default read or
3249 * draw framebuffer (as determined by target) is returned."
3250 */
3251 switch (target) {
3252 case GL_DRAW_FRAMEBUFFER:
3253 case GL_FRAMEBUFFER:
3254 fb = ctx->WinSysDrawBuffer;
3255 break;
3256 case GL_READ_FRAMEBUFFER:
3257 fb = ctx->WinSysReadBuffer;
3258 break;
3259 default:
3260 _mesa_error(ctx, GL_INVALID_ENUM,
3261 "glCheckNamedFramebufferStatus(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003262 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003263 return 0;
3264 }
3265
3266 if (framebuffer) {
3267 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
3268 "glCheckNamedFramebufferStatus");
3269 if (!fb)
3270 return 0;
3271 }
3272
3273 return _mesa_check_framebuffer_status(ctx, fb);
3274}
3275
3276
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003277GLenum GLAPIENTRY
3278_mesa_CheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target)
3279{
3280 struct gl_framebuffer *fb;
3281 GET_CURRENT_CONTEXT(ctx);
3282
3283 switch (target) {
3284 case GL_DRAW_FRAMEBUFFER:
3285 case GL_FRAMEBUFFER:
3286 case GL_READ_FRAMEBUFFER:
3287 break;
3288 default:
3289 _mesa_error(ctx, GL_INVALID_ENUM,
3290 "glCheckNamedFramebufferStatusEXT(invalid target %s)",
3291 _mesa_enum_to_string(target));
3292 return 0;
3293 }
3294
3295 if (framebuffer == 0) {
3296 return _mesa_CheckNamedFramebufferStatus(0, target);
3297 }
3298
3299 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
3300 "glCheckNamedFramebufferStatusEXT");
3301 if (!fb)
3302 return 0;
3303
3304 return _mesa_check_framebuffer_status(ctx, fb);
3305}
3306
3307
Chad Versacebf8ad172011-11-10 10:19:20 -08003308/**
3309 * Replicate the src attachment point. Used by framebuffer_texture() when
3310 * the same texture is attached at GL_DEPTH_ATTACHMENT and
3311 * GL_STENCIL_ATTACHMENT.
3312 */
3313static void
3314reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
3315 gl_buffer_index dst,
3316 gl_buffer_index src)
3317{
3318 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
3319 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
Brian Paulddc82ee2005-02-05 19:56:45 +00003320
Chad Versacebf8ad172011-11-10 10:19:20 -08003321 assert(src_att->Texture != NULL);
Brian Paul45bd5c42011-12-16 08:44:43 -07003322 assert(src_att->Renderbuffer != NULL);
Chad Versacebf8ad172011-11-10 10:19:20 -08003323
3324 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
3325 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
3326 dst_att->Type = src_att->Type;
3327 dst_att->Complete = src_att->Complete;
3328 dst_att->TextureLevel = src_att->TextureLevel;
Nanley Chery63318d32016-11-15 16:42:23 -08003329 dst_att->CubeMapFace = src_att->CubeMapFace;
Chad Versacebf8ad172011-11-10 10:19:20 -08003330 dst_att->Zoffset = src_att->Zoffset;
Dave Airlie35859d52016-02-29 17:16:10 +10003331 dst_att->Layered = src_att->Layered;
Chad Versacebf8ad172011-11-10 10:19:20 -08003332}
Brian Paulddc82ee2005-02-05 19:56:45 +00003333
Brian Paul45bd5c42011-12-16 08:44:43 -07003334
Timothy Arceri304058a2017-05-05 16:25:11 +10003335static struct gl_texture_object *
3336get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
3337{
3338 if (!texture)
3339 return NULL;
3340
3341 return _mesa_lookup_texture(ctx, texture);
3342}
3343
3344
Brian Paulddc82ee2005-02-05 19:56:45 +00003345/**
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003346 * Common code called by gl*FramebufferTexture*() to retrieve the correct
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003347 * texture object pointer.
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003348 *
3349 * \param texObj where the pointer to the texture object is returned. Note
3350 * that a successful call may return texObj = NULL.
3351 *
3352 * \return true if no errors, false if errors
Brian Paulddc82ee2005-02-05 19:56:45 +00003353 */
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003354static bool
Timothy Arceri304058a2017-05-05 16:25:11 +10003355get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
3356 bool layered, const char *caller,
3357 struct gl_texture_object **texObj)
Brian Paulddc82ee2005-02-05 19:56:45 +00003358{
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003359 *texObj = NULL; /* This will get returned if texture = 0. */
Brian Paulea4fe662006-03-26 05:22:17 +00003360
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003361 if (!texture)
3362 return true;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003363
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003364 *texObj = _mesa_lookup_texture(ctx, texture);
3365 if (*texObj == NULL || (*texObj)->Target == 0) {
3366 /* Can't render to a non-existent texture object.
3367 *
3368 * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
3369 * Managing Framebuffer Objects specifies a different error
3370 * depending upon the calling function (PDF pages 325-328).
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003371 * *FramebufferTexture (where layered = GL_TRUE) throws invalid
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003372 * value, while the other commands throw invalid operation (where
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003373 * layered = GL_FALSE).
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003374 */
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003375 const GLenum error = layered ? GL_INVALID_VALUE :
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003376 GL_INVALID_OPERATION;
3377 _mesa_error(ctx, error,
3378 "%s(non-existent texture %u)", caller, texture);
3379 return false;
3380 }
3381
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003382 return true;
3383}
3384
3385
3386/**
3387 * Common code called by gl*FramebufferTexture() to verify the texture target
3388 * and decide whether or not the attachment should truly be considered
3389 * layered.
3390 *
3391 * \param layered true if attachment should be considered layered, false if
3392 * not
3393 *
3394 * \return true if no errors, false if errors
3395 */
3396static bool
3397check_layered_texture_target(struct gl_context *ctx, GLenum target,
3398 const char *caller, GLboolean *layered)
3399{
3400 *layered = GL_TRUE;
3401
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003402 switch (target) {
3403 case GL_TEXTURE_3D:
3404 case GL_TEXTURE_1D_ARRAY_EXT:
3405 case GL_TEXTURE_2D_ARRAY_EXT:
3406 case GL_TEXTURE_CUBE_MAP:
3407 case GL_TEXTURE_CUBE_MAP_ARRAY:
3408 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3409 return true;
3410 case GL_TEXTURE_1D:
3411 case GL_TEXTURE_2D:
3412 case GL_TEXTURE_RECTANGLE:
3413 case GL_TEXTURE_2D_MULTISAMPLE:
3414 /* These texture types are valid to pass to
3415 * glFramebufferTexture(), but since they aren't layered, it
3416 * is equivalent to calling glFramebufferTexture{1D,2D}().
3417 */
3418 *layered = GL_FALSE;
3419 return true;
3420 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003421
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003422 _mesa_error(ctx, GL_INVALID_OPERATION,
3423 "%s(invalid texture target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003424 _mesa_enum_to_string(target));
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003425 return false;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003426}
3427
3428
3429/**
3430 * Common code called by gl*FramebufferTextureLayer() to verify the texture
3431 * target.
3432 *
3433 * \return true if no errors, false if errors
3434 */
3435static bool
3436check_texture_target(struct gl_context *ctx, GLenum target,
3437 const char *caller)
3438{
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003439 /* We're being called by glFramebufferTextureLayer().
3440 * The only legal texture types for that function are 3D,
3441 * cube-map, and 1D/2D/cube-map array textures.
Ian Romanick832ea232015-05-20 17:19:29 -07003442 *
3443 * We don't need to check for GL_ARB_texture_cube_map_array because the
3444 * application wouldn't have been able to create a texture with a
3445 * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003446 */
3447 switch (target) {
3448 case GL_TEXTURE_3D:
3449 case GL_TEXTURE_1D_ARRAY:
3450 case GL_TEXTURE_2D_ARRAY:
3451 case GL_TEXTURE_CUBE_MAP_ARRAY:
3452 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3453 return true;
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003454 case GL_TEXTURE_CUBE_MAP:
Timothy Arceri781a7892018-08-29 12:40:12 +10003455 /* GL_TEXTURE_CUBE_MAP is only allowed by OpenGL 4.5 here, which
3456 * includes the DSA API.
3457 *
3458 * Because DSA is only enabled for GL 3.1+ and this can be called
3459 * from _mesa_FramebufferTextureLayer in compatibility profile,
3460 * we need to check the version.
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003461 */
Timothy Arceri781a7892018-08-29 12:40:12 +10003462 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003463 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003464
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003465 _mesa_error(ctx, GL_INVALID_OPERATION,
3466 "%s(invalid texture target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003467 _mesa_enum_to_string(target));
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003468 return false;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003469}
3470
3471
3472/**
3473 * Common code called by glFramebufferTexture*D() to verify the texture
3474 * target.
3475 *
3476 * \return true if no errors, false if errors
3477 */
3478static bool
3479check_textarget(struct gl_context *ctx, int dims, GLenum target,
3480 GLenum textarget, const char *caller)
3481{
3482 bool err = false;
3483
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003484 switch (textarget) {
3485 case GL_TEXTURE_1D:
3486 err = dims != 1;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003487 break;
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003488 case GL_TEXTURE_1D_ARRAY:
3489 err = dims != 1 || !ctx->Extensions.EXT_texture_array;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003490 break;
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003491 case GL_TEXTURE_2D:
3492 err = dims != 2;
3493 break;
3494 case GL_TEXTURE_2D_ARRAY:
3495 err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
3496 (_mesa_is_gles(ctx) && ctx->Version < 30);
3497 break;
3498 case GL_TEXTURE_2D_MULTISAMPLE:
3499 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3500 err = dims != 2 ||
3501 !ctx->Extensions.ARB_texture_multisample ||
3502 (_mesa_is_gles(ctx) && ctx->Version < 31);
3503 break;
3504 case GL_TEXTURE_RECTANGLE:
3505 err = dims != 2 || _mesa_is_gles(ctx) ||
3506 !ctx->Extensions.NV_texture_rectangle;
3507 break;
3508 case GL_TEXTURE_CUBE_MAP:
3509 case GL_TEXTURE_CUBE_MAP_ARRAY:
3510 err = true;
3511 break;
3512 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3513 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3514 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3515 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3516 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3517 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3518 err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
3519 break;
3520 case GL_TEXTURE_3D:
3521 err = dims != 3;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003522 break;
3523 default:
Kenneth Graunkea40640f2016-10-03 16:37:26 -07003524 _mesa_error(ctx, GL_INVALID_ENUM,
3525 "%s(unknown textarget 0x%x)", caller, textarget);
3526 return false;
Laura Ekstranda602b212015-03-02 13:43:09 -08003527 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003528
Laura Ekstranda602b212015-03-02 13:43:09 -08003529 if (err) {
3530 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003531 "%s(invalid textarget %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003532 caller, _mesa_enum_to_string(textarget));
Laura Ekstranda602b212015-03-02 13:43:09 -08003533 return false;
3534 }
3535
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003536 /* Make sure textarget is consistent with the texture's type */
3537 err = (target == GL_TEXTURE_CUBE_MAP) ?
3538 !_mesa_is_cube_face(textarget): (target != textarget);
3539
3540 if (err) {
3541 _mesa_error(ctx, GL_INVALID_OPERATION,
3542 "%s(mismatched texture target)", caller);
3543 return false;
3544 }
3545
3546 return true;
3547}
3548
3549
3550/**
3551 * Common code called by gl*FramebufferTextureLayer() and
3552 * glFramebufferTexture3D() to validate the layer.
3553 *
3554 * \return true if no errors, false if errors
3555 */
3556static bool
3557check_layer(struct gl_context *ctx, GLenum target, GLint layer,
3558 const char *caller)
3559{
Laura Ekstranda602b212015-03-02 13:43:09 -08003560 /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
3561 * spec says:
3562 *
3563 * "An INVALID_VALUE error is generated if texture is non-zero
3564 * and layer is negative."
3565 */
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003566 if (layer < 0) {
Brian Paul08ba4a12017-12-05 09:57:23 -07003567 _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
Laura Ekstranda602b212015-03-02 13:43:09 -08003568 return false;
3569 }
3570
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003571 if (target == GL_TEXTURE_3D) {
Laura Ekstranda602b212015-03-02 13:43:09 -08003572 const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003573 if (layer >= maxSize) {
Fredrik Höglund8ba7ad82015-05-09 15:31:45 +02003574 _mesa_error(ctx, GL_INVALID_VALUE,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003575 "%s(invalid layer %u)", caller, layer);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003576 return false;
Fredrik Höglund8ba7ad82015-05-09 15:31:45 +02003577 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003578 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003579 else if ((target == GL_TEXTURE_1D_ARRAY) ||
3580 (target == GL_TEXTURE_2D_ARRAY) ||
3581 (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
3582 (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
3583 if (layer >= ctx->Const.MaxArrayTextureLayers) {
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003584 _mesa_error(ctx, GL_INVALID_VALUE,
Laura Ekstranda602b212015-03-02 13:43:09 -08003585 "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003586 caller, layer);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003587 return false;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003588 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003589 }
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003590 else if (target == GL_TEXTURE_CUBE_MAP) {
3591 if (layer >= 6) {
3592 _mesa_error(ctx, GL_INVALID_VALUE,
3593 "%s(layer %u >= 6)", caller, layer);
3594 return false;
3595 }
3596 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003597
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003598 return true;
3599}
3600
3601
3602/**
3603 * Common code called by all gl*FramebufferTexture*() entry points to verify
3604 * the level.
3605 *
3606 * \return true if no errors, false if errors
3607 */
3608static bool
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003609check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
3610 GLenum target, GLint level, const char *caller)
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003611{
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003612 /* Section 9.2.8 of the OpenGL 4.6 specification says:
3613 *
3614 * "If texture refers to an immutable-format texture, level must be
3615 * greater than or equal to zero and smaller than the value of
3616 * TEXTURE_VIEW_NUM_LEVELS for texture."
3617 */
3618 const int max_levels = texObj->Immutable ? texObj->ImmutableLevels :
3619 _mesa_max_texture_levels(ctx, target);
3620
3621 if (level < 0 || level >= max_levels) {
Laura Ekstranda602b212015-03-02 13:43:09 -08003622 _mesa_error(ctx, GL_INVALID_VALUE,
3623 "%s(invalid level %d)", caller, level);
3624 return false;
3625 }
Brian Paulea4fe662006-03-26 05:22:17 +00003626
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003627 return true;
3628}
3629
3630
Timothy Arcerid90ced42017-05-05 16:46:03 +10003631struct gl_renderbuffer_attachment *
3632_mesa_get_and_validate_attachment(struct gl_context *ctx,
3633 struct gl_framebuffer *fb,
3634 GLenum attachment, const char *caller)
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003635{
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003636 /* The window-system framebuffer object is immutable */
3637 if (_mesa_is_winsys_fbo(fb)) {
3638 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
3639 caller);
Timothy Arcerid90ced42017-05-05 16:46:03 +10003640 return NULL;
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003641 }
3642
3643 /* Not a hash lookup, so we can afford to get the attachment here. */
Timothy Arcerid90ced42017-05-05 16:46:03 +10003644 bool is_color_attachment;
3645 struct gl_renderbuffer_attachment *att =
3646 get_attachment(ctx, fb, attachment, &is_color_attachment);
Brian Paul3deaa012005-02-07 05:08:24 +00003647 if (att == NULL) {
Ilia Mirkin62b8f492017-01-24 00:26:29 -05003648 if (is_color_attachment) {
3649 _mesa_error(ctx, GL_INVALID_OPERATION,
3650 "%s(invalid color attachment %s)", caller,
3651 _mesa_enum_to_string(attachment));
3652 } else {
3653 _mesa_error(ctx, GL_INVALID_ENUM,
3654 "%s(invalid attachment %s)", caller,
3655 _mesa_enum_to_string(attachment));
3656 }
Timothy Arcerid90ced42017-05-05 16:46:03 +10003657 return NULL;
Brian Paul3deaa012005-02-07 05:08:24 +00003658 }
3659
Timothy Arcerid90ced42017-05-05 16:46:03 +10003660 return att;
3661}
3662
3663
3664void
3665_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
3666 GLenum attachment,
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003667 struct gl_renderbuffer_attachment *att,
Timothy Arcerid90ced42017-05-05 16:46:03 +10003668 struct gl_texture_object *texObj, GLenum textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003669 GLint level, GLsizei samples,
3670 GLuint layer, GLboolean layered)
Timothy Arcerid90ced42017-05-05 16:46:03 +10003671{
Brian Paul800e5532009-11-02 15:39:39 -07003672 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paul474f28e2005-10-08 14:41:17 +00003673
Timothy Arcerif0857fe2017-10-16 11:59:31 +11003674 simple_mtx_lock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +00003675 if (texObj) {
Chad Versacebf8ad172011-11-10 10:19:20 -08003676 if (attachment == GL_DEPTH_ATTACHMENT &&
Paul Berryb9819a02012-04-13 21:50:08 -07003677 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
3678 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
3679 _mesa_tex_target_to_face(textarget) ==
3680 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003681 samples == fb->Attachment[BUFFER_STENCIL].NumSamples &&
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003682 layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003683 /* The texture object is already attached to the stencil attachment
3684 * point. Don't create a new renderbuffer; just reuse the stencil
3685 * attachment's. This is required to prevent a GL error in
3686 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
3687 */
3688 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
3689 BUFFER_STENCIL);
Chad Versacebf8ad172011-11-10 10:19:20 -08003690 } else if (attachment == GL_STENCIL_ATTACHMENT &&
Martin Peres7bd8b482015-02-12 17:54:43 +02003691 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
Paul Berryb9819a02012-04-13 21:50:08 -07003692 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
3693 _mesa_tex_target_to_face(textarget) ==
3694 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003695 samples == fb->Attachment[BUFFER_DEPTH].NumSamples &&
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003696 layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003697 /* As above, but with depth and stencil transposed. */
3698 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
3699 BUFFER_DEPTH);
Chad Versacebf8ad172011-11-10 10:19:20 -08003700 } else {
Martin Peres7bd8b482015-02-12 17:54:43 +02003701 set_texture_attachment(ctx, fb, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003702 level, samples, layer, layered);
Laura Ekstrand8f78c682015-01-27 14:11:13 -08003703
Martin Peres7bd8b482015-02-12 17:54:43 +02003704 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3705 /* Above we created a new renderbuffer and attached it to the
3706 * depth attachment point. Now attach it to the stencil attachment
3707 * point too.
3708 */
3709 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3710 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
3711 BUFFER_DEPTH);
3712 }
Chad Versacebf8ad172011-11-10 10:19:20 -08003713 }
3714
Brian Paul2897cee2009-01-29 09:20:18 -07003715 /* Set the render-to-texture flag. We'll check this flag in
3716 * glTexImage() and friends to determine if we need to revalidate
3717 * any FBOs that might be rendering into this texture.
3718 * This flag never gets cleared since it's non-trivial to determine
3719 * when all FBOs might be done rendering to this texture. That's OK
3720 * though since it's uncommon to render to a texture then repeatedly
3721 * call glTexImage() to change images in the texture.
3722 */
3723 texObj->_RenderToTexture = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +00003724 }
3725 else {
Brian Paul94512812014-02-01 08:58:43 -07003726 remove_attachment(ctx, att);
Chad Versacebf8ad172011-11-10 10:19:20 -08003727 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003728 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3729 remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
Chad Versacebf8ad172011-11-10 10:19:20 -08003730 }
Brian Paul3deaa012005-02-07 05:08:24 +00003731 }
Brian Paul72966362009-01-21 16:28:38 -07003732
3733 invalidate_framebuffer(fb);
3734
Timothy Arcerif0857fe2017-10-16 11:59:31 +11003735 simple_mtx_unlock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +00003736}
3737
3738
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003739static void
Timothy Arceri20cabc22017-05-08 10:59:15 +10003740framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
3741 GLenum textarget, GLuint texture,
3742 GLint level, GLint layer)
3743{
3744 GET_CURRENT_CONTEXT(ctx);
3745
3746 /* Get the framebuffer object */
3747 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3748
3749 /* Get the texture object */
3750 struct gl_texture_object *texObj =
3751 get_texture_for_framebuffer(ctx, texture);
3752
3753 struct gl_renderbuffer_attachment *att =
3754 get_attachment(ctx, fb, attachment, NULL);
3755
3756 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003757 level, 0, layer, GL_FALSE);
Timothy Arceri20cabc22017-05-08 10:59:15 +10003758}
3759
3760
3761static void
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003762framebuffer_texture_with_dims(int dims, GLenum target, GLuint framebuffer,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003763 GLenum attachment, GLenum textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003764 GLuint texture, GLint level, GLsizei samples,
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003765 GLint layer, const char *caller, bool dsa)
Brian Paulea4fe662006-03-26 05:22:17 +00003766{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003767 GET_CURRENT_CONTEXT(ctx);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003768 struct gl_framebuffer *fb;
3769 struct gl_texture_object *texObj;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003770
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003771 /* Get the framebuffer object */
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003772 if (dsa) {
3773 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer, caller);
3774 } else {
3775 fb = get_framebuffer_target(ctx, target);
3776 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003777 if (!fb) {
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003778 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003779 _mesa_enum_to_string(target));
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003780 return;
3781 }
3782
3783 /* Get the texture object */
Timothy Arceri304058a2017-05-05 16:25:11 +10003784 if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003785 return;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003786
3787 if (texObj) {
3788 if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
3789 return;
3790
3791 if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
3792 return;
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003793
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003794 if (!check_level(ctx, texObj, textarget, level, caller))
Marek Olšák04a78062016-05-27 21:40:19 +02003795 return;
3796 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003797
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003798 struct gl_renderbuffer_attachment *att =
3799 _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
3800 if (!att)
3801 return;
3802
3803 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003804 level, samples, layer, GL_FALSE);
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003805}
3806
3807
3808void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003809_mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
3810 GLenum textarget, GLuint texture,
3811 GLint level)
3812{
3813 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3814 texture, level, 0);
3815}
3816
3817
3818void GLAPIENTRY
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003819_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
3820 GLenum textarget, GLuint texture, GLint level)
3821{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003822 framebuffer_texture_with_dims(1, target, 0, attachment, textarget, texture,
3823 level, 0, 0, "glFramebufferTexture1D", false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003824}
3825
3826
Brian Paul1864c7d2005-02-08 03:46:37 +00003827void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003828_mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
3829 GLenum textarget, GLuint texture,
3830 GLint level)
3831{
3832 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3833 texture, level, 0);
3834}
3835
3836
3837void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003838_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
Brian Paulc1377ed2014-03-22 10:31:58 -06003839 GLenum textarget, GLuint texture, GLint level)
Brian Paulddc82ee2005-02-05 19:56:45 +00003840{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003841 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3842 level, 0, 0, "glFramebufferTexture2D", false);
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003843}
3844
3845
3846void GLAPIENTRY
3847_mesa_FramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment,
3848 GLenum textarget, GLuint texture,
3849 GLint level, GLsizei samples)
3850{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003851 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3852 level, samples, 0,
3853 "glFramebufferTexture2DMultisampleEXT",
3854 false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003855}
3856
3857
Brian Paul1864c7d2005-02-08 03:46:37 +00003858void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003859_mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
3860 GLenum textarget, GLuint texture,
3861 GLint level, GLint layer)
3862{
3863 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3864 texture, level, layer);
3865}
3866
3867
3868void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003869_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
Brian Paulc1377ed2014-03-22 10:31:58 -06003870 GLenum textarget, GLuint texture,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003871 GLint level, GLint layer)
Brian Paulddc82ee2005-02-05 19:56:45 +00003872{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003873 framebuffer_texture_with_dims(3, target, 0, attachment, textarget, texture,
3874 level, 0, layer, "glFramebufferTexture3D", false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003875}
3876
3877
Timothy Arceri01081c62017-05-10 11:22:47 +10003878static ALWAYS_INLINE void
Timothy Arcerif6229282017-05-10 11:44:54 +10003879frame_buffer_texture(GLuint framebuffer, GLenum target,
3880 GLenum attachment, GLuint texture,
3881 GLint level, GLint layer, const char *func,
3882 bool dsa, bool no_error, bool check_layered)
Ian Romanickbb372f12007-05-16 15:34:22 -07003883{
3884 GET_CURRENT_CONTEXT(ctx);
Timothy Arcerif6229282017-05-10 11:44:54 +10003885 GLboolean layered = GL_FALSE;
3886
3887 if (!no_error && check_layered) {
3888 if (!_mesa_has_geometry_shaders(ctx)) {
3889 _mesa_error(ctx, GL_INVALID_OPERATION,
3890 "unsupported function (%s) called", func);
3891 return;
3892 }
3893 }
Ian Romanickbb372f12007-05-16 15:34:22 -07003894
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003895 /* Get the framebuffer object */
Timothy Arceri01081c62017-05-10 11:22:47 +10003896 struct gl_framebuffer *fb;
Timothy Arcerif6198e92017-05-11 15:43:44 +10003897 if (no_error) {
3898 if (dsa) {
3899 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
3900 } else {
3901 fb = get_framebuffer_target(ctx, target);
3902 }
Timothy Arceri01081c62017-05-10 11:22:47 +10003903 } else {
Timothy Arcerif6198e92017-05-11 15:43:44 +10003904 if (dsa) {
3905 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
3906 if (!fb)
3907 return;
3908 } else {
3909 fb = get_framebuffer_target(ctx, target);
3910 if (!fb) {
3911 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
3912 func, _mesa_enum_to_string(target));
3913 return;
3914 }
Timothy Arceri01081c62017-05-10 11:22:47 +10003915 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003916 }
3917
Timothy Arcerif6198e92017-05-11 15:43:44 +10003918 /* Get the texture object and framebuffer attachment*/
3919 struct gl_renderbuffer_attachment *att;
Timothy Arceri01081c62017-05-10 11:22:47 +10003920 struct gl_texture_object *texObj;
Timothy Arcerif6198e92017-05-11 15:43:44 +10003921 if (no_error) {
3922 texObj = get_texture_for_framebuffer(ctx, texture);
3923 att = get_attachment(ctx, fb, attachment, NULL);
3924 } else {
Timothy Arcerif6229282017-05-10 11:44:54 +10003925 if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
Timothy Arcerif6198e92017-05-11 15:43:44 +10003926 &texObj))
3927 return;
3928
3929 att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
3930 if (!att)
3931 return;
3932 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003933
Timothy Arceri01081c62017-05-10 11:22:47 +10003934 GLenum textarget = 0;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003935 if (texObj) {
Timothy Arcerif6229282017-05-10 11:44:54 +10003936 if (check_layered) {
3937 /* We do this regardless of no_error because this sets layered */
3938 if (!check_layered_texture_target(ctx, texObj->Target, func,
3939 &layered))
Timothy Arcerif6198e92017-05-11 15:43:44 +10003940 return;
Timothy Arcerif6229282017-05-10 11:44:54 +10003941 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003942
Timothy Arcerif6229282017-05-10 11:44:54 +10003943 if (!no_error) {
3944 if (!check_layered) {
3945 if (!check_texture_target(ctx, texObj->Target, func))
3946 return;
3947
3948 if (!check_layer(ctx, texObj->Target, layer, func))
3949 return;
3950 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003951
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003952 if (!check_level(ctx, texObj, texObj->Target, level, func))
Timothy Arcerif6198e92017-05-11 15:43:44 +10003953 return;
3954 }
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003955
Timothy Arcerif6229282017-05-10 11:44:54 +10003956 if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003957 assert(layer >= 0 && layer < 6);
3958 textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
3959 layer = 0;
3960 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003961 }
3962
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003963 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003964 level, 0, layer, layered);
Ian Romanickbb372f12007-05-16 15:34:22 -07003965}
3966
Timothy Arcerie75e8d62017-05-08 11:24:07 +10003967void GLAPIENTRY
3968_mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
3969 GLuint texture, GLint level,
3970 GLint layer)
3971{
Timothy Arcerif6229282017-05-10 11:44:54 +10003972 frame_buffer_texture(0, target, attachment, texture, level, layer,
3973 "glFramebufferTextureLayer", false, true, false);
Timothy Arcerie75e8d62017-05-08 11:24:07 +10003974}
3975
Ian Romanickbb372f12007-05-16 15:34:22 -07003976
3977void GLAPIENTRY
Timothy Arceri01081c62017-05-10 11:22:47 +10003978_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
3979 GLuint texture, GLint level, GLint layer)
3980{
Timothy Arcerif6229282017-05-10 11:44:54 +10003981 frame_buffer_texture(0, target, attachment, texture, level, layer,
3982 "glFramebufferTextureLayer", false, false, false);
Timothy Arceri01081c62017-05-10 11:22:47 +10003983}
3984
3985
3986void GLAPIENTRY
Timothy Arceri4e125c42017-05-08 11:37:33 +10003987_mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
3988 GLenum attachment,
3989 GLuint texture, GLint level,
3990 GLint layer)
3991{
Timothy Arcerif6229282017-05-10 11:44:54 +10003992 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
3993 "glNamedFramebufferTextureLayer", true, true, false);
Timothy Arceri4e125c42017-05-08 11:37:33 +10003994}
3995
3996
3997void GLAPIENTRY
Laura Ekstrandd78c8312015-01-28 13:19:57 -08003998_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
3999 GLuint texture, GLint level, GLint layer)
4000{
Timothy Arcerif6229282017-05-10 11:44:54 +10004001 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
4002 "glNamedFramebufferTextureLayer", true, false, false);
Laura Ekstrandd78c8312015-01-28 13:19:57 -08004003}
4004
4005
4006void GLAPIENTRY
Timothy Arceri4e8aa4b2017-05-08 11:52:45 +10004007_mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
4008 GLuint texture, GLint level)
4009{
4010 frame_buffer_texture(0, target, attachment, texture, level, 0,
4011 "glFramebufferTexture", false, true, true);
4012}
4013
4014
4015void GLAPIENTRY
Jordan Justen02f2bce2013-04-18 10:46:12 -07004016_mesa_FramebufferTexture(GLenum target, GLenum attachment,
4017 GLuint texture, GLint level)
4018{
Timothy Arcerif6229282017-05-10 11:44:54 +10004019 frame_buffer_texture(0, target, attachment, texture, level, 0,
4020 "glFramebufferTexture", false, false, true);
Jordan Justen02f2bce2013-04-18 10:46:12 -07004021}
4022
Timothy Arceri3336d242017-05-08 12:01:33 +10004023void GLAPIENTRY
4024_mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
4025 GLuint texture, GLint level)
4026{
4027 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4028 "glNamedFramebufferTexture", true, true, true);
4029}
4030
Jordan Justen02f2bce2013-04-18 10:46:12 -07004031
Laura Ekstrandd78c8312015-01-28 13:19:57 -08004032void GLAPIENTRY
4033_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
4034 GLuint texture, GLint level)
4035{
Timothy Arcerif6229282017-05-10 11:44:54 +10004036 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4037 "glNamedFramebufferTexture", true, false, true);
Laura Ekstrandd78c8312015-01-28 13:19:57 -08004038}
4039
4040
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004041void GLAPIENTRY
4042_mesa_NamedFramebufferTexture1DEXT(GLuint framebuffer, GLenum attachment,
4043 GLenum textarget, GLuint texture, GLint level)
4044{
4045 framebuffer_texture_with_dims(1, GL_FRAMEBUFFER, framebuffer, attachment,
4046 textarget, texture, level, 0, 0,
4047 "glNamedFramebufferTexture1DEXT", true);
4048}
4049
4050
4051void GLAPIENTRY
4052_mesa_NamedFramebufferTexture2DEXT(GLuint framebuffer, GLenum attachment,
4053 GLenum textarget, GLuint texture, GLint level)
4054{
4055 framebuffer_texture_with_dims(2, GL_FRAMEBUFFER, framebuffer, attachment,
4056 textarget, texture, level, 0, 0,
4057 "glNamedFramebufferTexture2DEXT", true);
4058}
4059
4060
4061void GLAPIENTRY
4062_mesa_NamedFramebufferTexture3DEXT(GLuint framebuffer, GLenum attachment,
4063 GLenum textarget, GLuint texture,
4064 GLint level, GLint zoffset)
4065{
4066 framebuffer_texture_with_dims(3, GL_FRAMEBUFFER, framebuffer, attachment,
4067 textarget, texture, level, 0, zoffset,
4068 "glNamedFramebufferTexture3DEXT", true);
4069}
4070
4071
Laura Ekstranda29318b2015-02-27 17:27:30 -08004072void
4073_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
4074 struct gl_framebuffer *fb,
4075 GLenum attachment,
Ian Romanick9ae42ab2015-11-11 16:30:41 -08004076 struct gl_renderbuffer *rb)
4077{
4078 assert(!_mesa_is_winsys_fbo(fb));
4079
4080 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
4081
4082 assert(ctx->Driver.FramebufferRenderbuffer);
4083 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
4084
4085 /* Some subsequent GL commands may depend on the framebuffer's visual
4086 * after the binding is updated. Update visual info now.
4087 */
4088 _mesa_update_framebuffer_visual(ctx, fb);
4089}
4090
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004091static ALWAYS_INLINE void
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004092framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
4093 GLenum attachment, GLenum renderbuffertarget,
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004094 GLuint renderbuffer, const char *func, bool no_error)
Brian Paulddc82ee2005-02-05 19:56:45 +00004095{
Brian Paul2c6f9112005-02-24 05:47:06 +00004096 struct gl_renderbuffer_attachment *att;
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004097 struct gl_renderbuffer *rb;
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004098 bool is_color_attachment;
Brian Paul3deaa012005-02-07 05:08:24 +00004099
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004100 if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004101 _mesa_error(ctx, GL_INVALID_ENUM,
4102 "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
4103 return;
4104 }
4105
4106 if (renderbuffer) {
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004107 if (!no_error) {
4108 rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
4109 if (!rb)
4110 return;
4111 } else {
4112 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
4113 }
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004114 } else {
4115 /* remove renderbuffer attachment */
4116 rb = NULL;
4117 }
4118
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004119 if (!no_error) {
4120 if (_mesa_is_winsys_fbo(fb)) {
4121 /* Can't attach new renderbuffers to a window system framebuffer */
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004122 _mesa_error(ctx, GL_INVALID_OPERATION,
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004123 "%s(window-system framebuffer)", func);
4124 return;
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004125 }
4126
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004127 att = get_attachment(ctx, fb, attachment, &is_color_attachment);
4128 if (att == NULL) {
4129 /*
4130 * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
4131 * to a Framebuffer":
4132 *
4133 * "An INVALID_OPERATION error is generated if attachment is
4134 * COLOR_- ATTACHMENTm where m is greater than or equal to the
4135 * value of MAX_COLOR_- ATTACHMENTS ."
4136 *
4137 * If we are at this point, is because the attachment is not valid, so
4138 * if is_color_attachment is true, is because of the previous reason.
4139 */
4140 if (is_color_attachment) {
4141 _mesa_error(ctx, GL_INVALID_OPERATION,
4142 "%s(invalid color attachment %s)", func,
4143 _mesa_enum_to_string(attachment));
4144 } else {
4145 _mesa_error(ctx, GL_INVALID_ENUM,
4146 "%s(invalid attachment %s)", func,
4147 _mesa_enum_to_string(attachment));
4148 }
Brian Paulddc82ee2005-02-05 19:56:45 +00004149
Brian Paul30590072009-01-21 11:06:11 -07004150 return;
4151 }
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004152
4153 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
4154 rb && rb->Format != MESA_FORMAT_NONE) {
4155 /* make sure the renderbuffer is a depth/stencil format */
4156 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
4157 if (baseFormat != GL_DEPTH_STENCIL) {
4158 _mesa_error(ctx, GL_INVALID_OPERATION,
4159 "%s(renderbuffer is not DEPTH_STENCIL format)", func);
4160 return;
4161 }
4162 }
Brian Paul30590072009-01-21 11:06:11 -07004163 }
4164
Ian Romanick9ae42ab2015-11-11 16:30:41 -08004165 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
Brian Paulddc82ee2005-02-05 19:56:45 +00004166}
4167
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004168static void
4169framebuffer_renderbuffer_error(struct gl_context *ctx,
4170 struct gl_framebuffer *fb, GLenum attachment,
4171 GLenum renderbuffertarget,
4172 GLuint renderbuffer, const char *func)
4173{
4174 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4175 renderbuffer, func, false);
4176}
4177
Samuel Pitoiset0a20e432017-07-19 12:28:21 +02004178static void
4179framebuffer_renderbuffer_no_error(struct gl_context *ctx,
4180 struct gl_framebuffer *fb, GLenum attachment,
4181 GLenum renderbuffertarget,
4182 GLuint renderbuffer, const char *func)
4183{
4184 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4185 renderbuffer, func, true);
4186}
4187
4188void GLAPIENTRY
4189_mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
4190 GLenum renderbuffertarget,
4191 GLuint renderbuffer)
4192{
4193 GET_CURRENT_CONTEXT(ctx);
4194
4195 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
4196 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4197 renderbuffer, "glFramebufferRenderbuffer");
4198}
4199
Brian Paul1864c7d2005-02-08 03:46:37 +00004200void GLAPIENTRY
Laura Ekstranda29318b2015-02-27 17:27:30 -08004201_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
4202 GLenum renderbuffertarget,
4203 GLuint renderbuffer)
4204{
4205 struct gl_framebuffer *fb;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004206 GET_CURRENT_CONTEXT(ctx);
4207
4208 fb = get_framebuffer_target(ctx, target);
4209 if (!fb) {
4210 _mesa_error(ctx, GL_INVALID_ENUM,
4211 "glFramebufferRenderbuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004212 _mesa_enum_to_string(target));
Laura Ekstranda29318b2015-02-27 17:27:30 -08004213 return;
4214 }
4215
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004216 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4217 renderbuffer, "glFramebufferRenderbuffer");
Laura Ekstranda29318b2015-02-27 17:27:30 -08004218}
4219
Samuel Pitoiset7bc50df2017-07-19 12:32:42 +02004220void GLAPIENTRY
4221_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
4222 GLenum attachment,
4223 GLenum renderbuffertarget,
4224 GLuint renderbuffer)
4225{
4226 GET_CURRENT_CONTEXT(ctx);
4227
4228 struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4229 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4230 renderbuffer,
4231 "glNamedFramebufferRenderbuffer");
4232}
Laura Ekstranda29318b2015-02-27 17:27:30 -08004233
4234void GLAPIENTRY
4235_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
4236 GLenum renderbuffertarget,
4237 GLuint renderbuffer)
4238{
4239 struct gl_framebuffer *fb;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004240 GET_CURRENT_CONTEXT(ctx);
4241
4242 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4243 "glNamedFramebufferRenderbuffer");
Fredrik Höglund5a55f682015-05-16 19:43:39 +02004244 if (!fb)
4245 return;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004246
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004247 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4248 renderbuffer,
4249 "glNamedFramebufferRenderbuffer");
Laura Ekstranda29318b2015-02-27 17:27:30 -08004250}
4251
4252
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004253void GLAPIENTRY
4254_mesa_NamedFramebufferRenderbufferEXT(GLuint framebuffer, GLenum attachment,
4255 GLenum renderbuffertarget,
4256 GLuint renderbuffer)
4257{
4258 struct gl_framebuffer *fb;
4259 GET_CURRENT_CONTEXT(ctx);
4260
4261 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4262 "glNamedFramebufferRenderbufferEXT");
4263 if (!fb)
4264 return;
4265
4266 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4267 renderbuffer,
4268 "glNamedFramebufferRenderbuffer");
4269}
4270
4271
Timothy Arceri8b006302017-05-05 15:21:22 +10004272static void
4273get_framebuffer_attachment_parameter(struct gl_context *ctx,
4274 struct gl_framebuffer *buffer,
4275 GLenum attachment, GLenum pname,
4276 GLint *params, const char *caller)
Brian Paulddc82ee2005-02-05 19:56:45 +00004277{
Brian Paul2c6f9112005-02-24 05:47:06 +00004278 const struct gl_renderbuffer_attachment *att;
Robert Foss88becf72017-03-01 19:14:39 -05004279 bool is_color_attachment = false;
Marek Olšák000896c2011-07-19 03:05:07 +02004280 GLenum err;
Brian Paulddc82ee2005-02-05 19:56:45 +00004281
Kenneth Graunke19f13b22016-03-07 16:43:35 -08004282 /* The error code for an attachment type of GL_NONE differs between APIs.
4283 *
4284 * From the ES 2.0.25 specification, page 127:
4285 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4286 * querying any other pname will generate INVALID_ENUM."
4287 *
4288 * From the OpenGL 3.0 specification, page 337, or identically,
4289 * the OpenGL ES 3.0.4 specification, page 240:
4290 *
4291 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no
4292 * framebuffer is bound to target. In this case querying pname
4293 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero, and all other
4294 * queries will generate an INVALID_OPERATION error."
4295 */
4296 err = ctx->API == API_OPENGLES2 && ctx->Version < 30 ?
4297 GL_INVALID_ENUM : GL_INVALID_OPERATION;
Marek Olšák000896c2011-07-19 03:05:07 +02004298
Brian Paul36ede892012-01-12 09:17:23 -07004299 if (_mesa_is_winsys_fbo(buffer)) {
Ian Romanickda2e41c2011-10-03 12:04:09 -07004300 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
4301 * says:
4302 *
4303 * "If the framebuffer currently bound to target is zero, then
4304 * INVALID_OPERATION is generated."
4305 *
4306 * The EXT_framebuffer_object spec has the same wording, and the
4307 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
4308 * spec.
4309 */
Brian Paulc1377ed2014-03-22 10:31:58 -06004310 if ((!_mesa_is_desktop_gl(ctx) ||
4311 !ctx->Extensions.ARB_framebuffer_object)
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004312 && !_mesa_is_gles3(ctx)) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004313 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004314 "%s(window-system framebuffer)", caller);
Martin Peres7bd8b482015-02-12 17:54:43 +02004315 return;
Ian Romanickda2e41c2011-10-03 12:04:09 -07004316 }
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004317
4318 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
4319 attachment != GL_DEPTH && attachment != GL_STENCIL) {
Samuel Iglesias Gonsalvez284bd1e2015-01-16 16:00:13 +01004320 _mesa_error(ctx, GL_INVALID_ENUM,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004321 "%s(invalid attachment %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004322 _mesa_enum_to_string(attachment));
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004323 return;
4324 }
Kenneth Graunke789e0962016-03-08 23:59:37 -08004325
4326 /* The specs are not clear about how to handle
4327 * GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME with the default framebuffer,
4328 * but dEQP-GLES3 expects an INVALID_ENUM error. This has also been
4329 * discussed in:
4330 *
4331 * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=12928#c1
4332 * and https://bugs.freedesktop.org/show_bug.cgi?id=31947
4333 */
4334 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4335 _mesa_error(ctx, GL_INVALID_ENUM,
4336 "%s(requesting GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME "
4337 "when GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
4338 "GL_FRAMEBUFFER_DEFAULT is not allowed)", caller);
4339 return;
4340 }
4341
Brian Paul61ec2052010-06-22 08:37:44 -06004342 /* the default / window-system FBO */
Timothy Arcerie6187612017-05-05 15:02:20 +10004343 att = get_fb0_attachment(ctx, buffer, attachment);
Brian Paul61ec2052010-06-22 08:37:44 -06004344 }
4345 else {
4346 /* user-created framebuffer FBO */
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004347 att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
Brian Paul61ec2052010-06-22 08:37:44 -06004348 }
4349
Brian Paul3deaa012005-02-07 05:08:24 +00004350 if (att == NULL) {
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004351 /*
4352 * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
4353 *
4354 * "An INVALID_OPERATION error is generated if a framebuffer object
4355 * is bound to target and attachment is COLOR_ATTACHMENTm where m is
4356 * greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
4357 *
4358 * If we are at this point, is because the attachment is not valid, so
4359 * if is_color_attachment is true, is because of the previous reason.
4360 */
4361 if (is_color_attachment) {
4362 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
4363 caller, _mesa_enum_to_string(attachment));
4364 } else {
4365 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
4366 _mesa_enum_to_string(attachment));
4367 }
Brian Paulddc82ee2005-02-05 19:56:45 +00004368 return;
4369 }
4370
Brian Paul30590072009-01-21 11:06:11 -07004371 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Brian Paule9592742014-04-21 13:24:25 -06004372 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
Anuj Phogatbd1880d2014-03-11 17:04:11 -07004373 if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
4374 /* This behavior is first specified in OpenGL 4.4 specification.
4375 *
4376 * From the OpenGL 4.4 spec page 275:
4377 * "This query cannot be performed for a combined depth+stencil
4378 * attachment, since it does not have a single format."
4379 */
4380 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004381 "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
4382 " is invalid for depth+stencil attachment)", caller);
Anuj Phogatbd1880d2014-03-11 17:04:11 -07004383 return;
4384 }
Brian Paul30590072009-01-21 11:06:11 -07004385 /* the depth and stencil attachments must point to the same buffer */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02004386 depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
4387 stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
Brian Paul30590072009-01-21 11:06:11 -07004388 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
4389 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004390 "%s(DEPTH/STENCIL attachments differ)", caller);
Brian Paul30590072009-01-21 11:06:11 -07004391 return;
4392 }
4393 }
4394
Brian Paul800e5532009-11-02 15:39:39 -07004395 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00004396
Brian Paulddc82ee2005-02-05 19:56:45 +00004397 switch (pname) {
4398 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
Iago Toral Quirogacf439952015-02-24 19:02:56 +01004399 /* From the OpenGL spec, 9.2. Binding and Managing Framebuffer Objects:
4400 *
4401 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4402 * either no framebuffer is bound to target; or the default framebuffer
4403 * is bound, attachment is DEPTH or STENCIL, and the number of depth or
4404 * stencil bits, respectively, is zero."
Alejandro Piñeiro90596142017-01-13 11:39:24 -02004405 *
4406 * Note that we don't need explicit checks on DEPTH and STENCIL, because
4407 * on the case the spec is pointing, att->Type is already NONE, so we
4408 * just need to check att->Type.
Iago Toral Quirogacf439952015-02-24 19:02:56 +01004409 */
Alejandro Piñeiro90596142017-01-13 11:39:24 -02004410 *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
4411 GL_FRAMEBUFFER_DEFAULT : att->Type;
Brian Paul3deaa012005-02-07 05:08:24 +00004412 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004413 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004414 if (att->Type == GL_RENDERBUFFER_EXT) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004415 *params = att->Renderbuffer->Name;
Brian Paul3deaa012005-02-07 05:08:24 +00004416 }
4417 else if (att->Type == GL_TEXTURE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004418 *params = att->Texture->Name;
Brian Paul3deaa012005-02-07 05:08:24 +00004419 }
4420 else {
Brian Paul20cf1852010-12-03 08:23:31 -07004421 assert(att->Type == GL_NONE);
Ian Romanick0cdaa472012-07-27 07:47:28 -07004422 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
Marek Olšák000896c2011-07-19 03:05:07 +02004423 *params = 0;
4424 } else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004425 goto invalid_pname_enum;
Marek Olšák000896c2011-07-19 03:05:07 +02004426 }
Brian Paul3deaa012005-02-07 05:08:24 +00004427 }
4428 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004429 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004430 if (att->Type == GL_TEXTURE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004431 *params = att->TextureLevel;
Brian Paul3deaa012005-02-07 05:08:24 +00004432 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004433 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004434 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004435 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004436 }
Brian Paul3deaa012005-02-07 05:08:24 +00004437 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004438 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004439 }
4440 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004441 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004442 if (att->Type == GL_TEXTURE) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06004443 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
4444 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
4445 }
4446 else {
4447 *params = 0;
4448 }
Brian Paul3deaa012005-02-07 05:08:24 +00004449 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004450 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004451 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004452 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004453 }
Brian Paul3deaa012005-02-07 05:08:24 +00004454 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004455 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004456 }
4457 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004458 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
Ian Romanick0cdaa472012-07-27 07:47:28 -07004459 if (ctx->API == API_OPENGLES) {
4460 goto invalid_pname_enum;
4461 } else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004462 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004463 _mesa_enum_to_string(pname));
Ian Romanick0cdaa472012-07-27 07:47:28 -07004464 } else if (att->Type == GL_TEXTURE) {
Samuel Iglesias Gonsalvez8e49a3e2014-12-11 23:34:13 +01004465 if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
4466 att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06004467 *params = att->Zoffset;
4468 }
4469 else {
4470 *params = 0;
4471 }
Brian Paul3deaa012005-02-07 05:08:24 +00004472 }
4473 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004474 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004475 }
4476 return;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004477 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Brian Paulc1377ed2014-03-22 10:31:58 -06004478 if ((!_mesa_is_desktop_gl(ctx) ||
4479 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004480 && !_mesa_is_gles3(ctx)) {
4481 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004482 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004483 else if (att->Type == GL_NONE) {
Kenneth Graunke713cd232016-12-09 16:16:53 -08004484 if (_mesa_is_winsys_fbo(buffer) &&
4485 (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
4486 *params = GL_LINEAR;
4487 } else {
4488 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4489 _mesa_enum_to_string(pname));
4490 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004491 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004492 else {
Gert Wollny76c3f6f2018-11-14 10:58:40 +01004493 if (ctx->Extensions.EXT_sRGB) {
Eric Anholt4d231572019-07-01 15:43:19 -07004494 *params = (_mesa_is_format_srgb(att->Renderbuffer->Format) ?
4495 GL_SRGB : GL_LINEAR);
Marek Olšák81ae8c62011-01-23 13:26:43 +01004496 }
4497 else {
4498 /* According to ARB_framebuffer_sRGB, we should return LINEAR
4499 * if the sRGB conversion is unsupported. */
4500 *params = GL_LINEAR;
4501 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004502 }
4503 return;
4504 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Brian Paulc1377ed2014-03-22 10:31:58 -06004505 if ((ctx->API != API_OPENGL_COMPAT ||
4506 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004507 && ctx->API != API_OPENGL_CORE
4508 && !_mesa_is_gles3(ctx)) {
4509 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004510 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004511 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004512 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004513 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004514 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004515 else {
Mark Mueller71fe9432014-01-04 14:11:43 -08004516 mesa_format format = att->Renderbuffer->Format;
Ian Romanickd7475c72013-01-18 17:25:57 -08004517
4518 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
4519 * 3.0.1 spec says:
4520 *
4521 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
4522 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
4523 * generate an INVALID_OPERATION error.
4524 */
Brian Paulc1377ed2014-03-22 10:31:58 -06004525 if (_mesa_is_gles3(ctx) &&
4526 attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Ian Romanickd7475c72013-01-18 17:25:57 -08004527 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004528 "%s(cannot query "
Ian Romanickd7475c72013-01-18 17:25:57 -08004529 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004530 "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
Ian Romanickd7475c72013-01-18 17:25:57 -08004531 return;
4532 }
4533
Mark Mueller50a01d22014-01-20 19:08:54 -08004534 if (format == MESA_FORMAT_S_UINT8) {
Brian Paul45e76d22009-10-08 20:27:27 -06004535 /* special cases */
4536 *params = GL_INDEX;
4537 }
Mark Muellereeed49f2014-01-26 15:12:56 -08004538 else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
Marek Olšák11652802011-06-01 15:48:51 +02004539 /* depends on the attachment parameter */
4540 if (attachment == GL_STENCIL_ATTACHMENT) {
4541 *params = GL_INDEX;
4542 }
4543 else {
4544 *params = GL_FLOAT;
4545 }
4546 }
Brian Paul45e76d22009-10-08 20:27:27 -06004547 else {
4548 *params = _mesa_get_format_datatype(format);
4549 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004550 }
4551 return;
4552 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004553 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004554 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004555 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004556 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004557 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Brian Paulc1377ed2014-03-22 10:31:58 -06004558 if ((!_mesa_is_desktop_gl(ctx) ||
4559 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004560 && !_mesa_is_gles3(ctx)) {
4561 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004562 }
Brian Paul45e76d22009-10-08 20:27:27 -06004563 else if (att->Texture) {
4564 const struct gl_texture_image *texImage =
Brian Paulf262ed62015-01-02 16:56:12 -07004565 _mesa_select_tex_image(att->Texture, att->Texture->Target,
Brian Paul45e76d22009-10-08 20:27:27 -06004566 att->TextureLevel);
4567 if (texImage) {
4568 *params = get_component_bits(pname, texImage->_BaseFormat,
4569 texImage->TexFormat);
4570 }
4571 else {
4572 *params = 0;
4573 }
4574 }
4575 else if (att->Renderbuffer) {
4576 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
4577 att->Renderbuffer->Format);
4578 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004579 else {
Timothy Arceri786b9ad2017-05-05 15:39:15 +10004580 assert(att->Type == GL_NONE);
4581 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4582 _mesa_enum_to_string(pname));
Brian Paul1bc59bf2009-01-22 15:07:34 -07004583 }
4584 return;
Paul Berryec79c052013-11-19 21:17:19 -08004585 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
4586 if (!_mesa_has_geometry_shaders(ctx)) {
4587 goto invalid_pname_enum;
4588 } else if (att->Type == GL_TEXTURE) {
4589 *params = att->Layered;
4590 } else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004591 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004592 _mesa_enum_to_string(pname));
Paul Berryec79c052013-11-19 21:17:19 -08004593 } else {
4594 goto invalid_pname_enum;
4595 }
4596 return;
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08004597 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4598 if (!ctx->Extensions.EXT_multisampled_render_to_texture) {
4599 goto invalid_pname_enum;
4600 } else if (att->Type == GL_TEXTURE) {
4601 *params = att->NumSamples;
4602 } else if (att->Type == GL_NONE) {
4603 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4604 _mesa_enum_to_string(pname));
4605 } else {
4606 goto invalid_pname_enum;
4607 }
4608 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004609 default:
Ian Romanick0cdaa472012-07-27 07:47:28 -07004610 goto invalid_pname_enum;
Brian Paulddc82ee2005-02-05 19:56:45 +00004611 }
Ian Romanick0cdaa472012-07-27 07:47:28 -07004612
4613 return;
4614
4615invalid_pname_enum:
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004616 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004617 _mesa_enum_to_string(pname));
Ian Romanick0cdaa472012-07-27 07:47:28 -07004618 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004619}
4620
4621
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004622void GLAPIENTRY
4623_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
4624 GLenum pname, GLint *params)
4625{
4626 GET_CURRENT_CONTEXT(ctx);
4627 struct gl_framebuffer *buffer;
4628
4629 buffer = get_framebuffer_target(ctx, target);
4630 if (!buffer) {
4631 _mesa_error(ctx, GL_INVALID_ENUM,
4632 "glGetFramebufferAttachmentParameteriv(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004633 _mesa_enum_to_string(target));
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004634 return;
4635 }
4636
Timothy Arceri8b006302017-05-05 15:21:22 +10004637 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4638 params,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004639 "glGetFramebufferAttachmentParameteriv");
4640}
4641
4642
4643void GLAPIENTRY
4644_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
4645 GLenum attachment,
4646 GLenum pname, GLint *params)
4647{
4648 GET_CURRENT_CONTEXT(ctx);
4649 struct gl_framebuffer *buffer;
4650
4651 if (framebuffer) {
4652 buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4653 "glGetNamedFramebufferAttachmentParameteriv");
4654 if (!buffer)
4655 return;
4656 }
4657 else {
4658 /*
4659 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4660 * 4.5 core spec (30.10.2014, PDF page 314):
4661 * "If framebuffer is zero, then the default draw framebuffer is
4662 * queried."
4663 */
4664 buffer = ctx->WinSysDrawBuffer;
4665 }
4666
Timothy Arceri8b006302017-05-05 15:21:22 +10004667 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4668 params,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004669 "glGetNamedFramebufferAttachmentParameteriv");
4670}
4671
4672
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004673void GLAPIENTRY
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004674_mesa_GetNamedFramebufferAttachmentParameterivEXT(GLuint framebuffer,
4675 GLenum attachment,
4676 GLenum pname, GLint *params)
4677{
4678 GET_CURRENT_CONTEXT(ctx);
4679 struct gl_framebuffer *buffer;
4680
4681 if (framebuffer) {
4682 buffer = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4683 "glGetNamedFramebufferAttachmentParameterivEXT");
4684 if (!buffer)
4685 return;
4686 }
4687 else {
4688 /*
4689 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4690 * 4.5 core spec (30.10.2014, PDF page 314):
4691 * "If framebuffer is zero, then the default draw framebuffer is
4692 * queried."
4693 */
4694 buffer = ctx->WinSysDrawBuffer;
4695 }
4696
4697 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4698 params,
4699 "glGetNamedFramebufferAttachmentParameterivEXT");
4700}
4701
4702
4703void GLAPIENTRY
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004704_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
4705 GLint param)
4706{
4707 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004708 struct gl_framebuffer *fb = NULL;
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004709
Rhys Perry67f40da2018-06-14 19:56:28 -06004710 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
4711 !ctx->Extensions.ARB_sample_locations) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004712 _mesa_error(ctx, GL_INVALID_OPERATION,
4713 "glNamedFramebufferParameteri("
Rhys Perry67f40da2018-06-14 19:56:28 -06004714 "neither ARB_framebuffer_no_attachments nor "
4715 "ARB_sample_locations is available)");
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004716 return;
4717 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004718
Rhys Perry67f40da2018-06-14 19:56:28 -06004719 if (framebuffer) {
4720 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4721 "glNamedFramebufferParameteri");
4722 } else {
4723 fb = ctx->WinSysDrawBuffer;
4724 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004725
4726 if (fb) {
4727 framebuffer_parameteri(ctx, fb, pname, param,
4728 "glNamedFramebufferParameteriv");
4729 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004730}
4731
4732
Pierre-Eric Pelloux-Prayer8cfb3e42019-11-05 14:47:53 +01004733/* Helper function for ARB_framebuffer_no_attachments functions interacting with EXT_direct_state_access */
4734static struct gl_framebuffer *
4735lookup_named_framebuffer_ext_dsa(struct gl_context *ctx, GLuint framebuffer, const char* caller)
4736{
4737 struct gl_framebuffer *fb = NULL;
4738
4739 if (framebuffer) {
4740 /* The ARB_framebuffer_no_attachments spec says:
4741 *
4742 * "The error INVALID_VALUE is generated if <framebuffer> is not
4743 * a name returned by GenFramebuffers. If a framebuffer object
4744 * named <framebuffer> does not yet exist, it will be created."
4745 *
4746 * This is different from the EXT_direct_state_access spec which says:
4747 *
4748 * "If the framebuffer object named by the framebuffer parameter has not
4749 * been previously bound or has been deleted since the last binding,
4750 * the GL first creates a new state vector in the same manner as when
4751 * BindFramebuffer creates a new framebuffer object"
4752 *
4753 * So first we verify that the name exists.
4754 */
4755 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4756 if (!fb) {
4757 _mesa_error(ctx, GL_INVALID_VALUE, "%s(frameBuffer)", caller);
4758 return NULL;
4759 }
4760 /* Then, make sure it's initialized */
4761 if (fb == &DummyFramebuffer) {
4762 fb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
Pierre-Eric Pelloux-Prayer8cfb3e42019-11-05 14:47:53 +01004763 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, fb);
Pierre-Eric Pelloux-Prayer8cfb3e42019-11-05 14:47:53 +01004764 }
4765 }
4766 else
4767 fb = ctx->WinSysDrawBuffer;
4768
4769 return fb;
4770}
4771
4772
4773void GLAPIENTRY
4774_mesa_NamedFramebufferParameteriEXT(GLuint framebuffer, GLenum pname,
4775 GLint param)
4776{
4777 GET_CURRENT_CONTEXT(ctx);
4778 struct gl_framebuffer *fb =
4779 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
4780 "glNamedFramebufferParameteriEXT");
4781
4782 if (!fb)
4783 return;
4784
4785 framebuffer_parameteri(ctx, fb, pname, param,
4786 "glNamedFramebufferParameteriEXT");
4787}
4788
4789
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004790void GLAPIENTRY
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004791_mesa_GetFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4792 GLint *param)
4793{
4794 GET_CURRENT_CONTEXT(ctx);
4795 struct gl_framebuffer *fb;
4796
4797 if (framebuffer)
4798 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4799 "glGetFramebufferParameterivEXT");
4800 else
4801 fb = ctx->WinSysDrawBuffer;
4802
4803 if (fb) {
4804 /* The GL_EXT_direct_state_access says:
4805 *
4806 * The pname parameter must be one of framebuffer dependent values
4807 * listed in either table 4.nnn (namely DRAW_BUFFER, READ_BUFFER,
4808 * or DRAW_BUFFER0 through DRAW_BUFFER15).
4809 */
4810 if (pname == GL_DRAW_BUFFER) {
4811 *param = fb->ColorDrawBuffer[0];
4812
4813 }
4814 else if (pname == GL_READ_BUFFER) {
4815 *param = fb->ColorReadBuffer;
4816 }
4817 else if (GL_DRAW_BUFFER0 <= pname && pname <= GL_DRAW_BUFFER15) {
Marcin Ślusarz0906d5d2020-07-24 19:19:07 +02004818 unsigned buffer = pname - GL_DRAW_BUFFER0;
4819 if (buffer < ARRAY_SIZE(fb->ColorDrawBuffer))
4820 *param = fb->ColorDrawBuffer[buffer];
4821 else
4822 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004823 }
4824 else {
4825 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
4826 }
4827 }
4828}
4829
4830
4831void GLAPIENTRY
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004832_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
4833 GLint *param)
4834{
4835 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004836 struct gl_framebuffer *fb;
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004837
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004838 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4839 _mesa_error(ctx, GL_INVALID_OPERATION,
4840 "glNamedFramebufferParameteriv("
Rhys Perry67f40da2018-06-14 19:56:28 -06004841 "neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
4842 " is available)");
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004843 return;
4844 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004845
Rhys Perry67f40da2018-06-14 19:56:28 -06004846 if (framebuffer)
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004847 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4848 "glGetNamedFramebufferParameteriv");
Rhys Perry67f40da2018-06-14 19:56:28 -06004849 else
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004850 fb = ctx->WinSysDrawBuffer;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004851
4852 if (fb) {
4853 get_framebuffer_parameteriv(ctx, fb, pname, param,
4854 "glGetNamedFramebufferParameteriv");
4855 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004856}
4857
4858
Pierre-Eric Pelloux-Prayer8cfb3e42019-11-05 14:47:53 +01004859void GLAPIENTRY
4860_mesa_GetNamedFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4861 GLint *param)
4862{
4863 GET_CURRENT_CONTEXT(ctx);
4864 struct gl_framebuffer *fb =
4865 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
4866 "glGetNamedFramebufferParameterivEXT");
4867
4868 if (!fb)
4869 return;
4870
4871 get_framebuffer_parameteriv(ctx, fb, pname, param,
4872 "glGetNamedFramebufferParameterivEXT");
4873}
4874
4875
Ian Romanick342be8a2012-08-13 09:27:00 -07004876static void
Laura Ekstrand65d4a202015-02-04 09:49:58 -08004877invalidate_framebuffer_storage(struct gl_context *ctx,
4878 struct gl_framebuffer *fb,
4879 GLsizei numAttachments,
Ian Romanick342be8a2012-08-13 09:27:00 -07004880 const GLenum *attachments, GLint x, GLint y,
4881 GLsizei width, GLsizei height, const char *name)
4882{
4883 int i;
Ian Romanick342be8a2012-08-13 09:27:00 -07004884
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08004885 /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
4886 * Spec (2.2.2015, PDF page 522) says:
4887 * "An INVALID_VALUE error is generated if numAttachments, width, or
4888 * height is negative."
4889 */
Ian Romanick342be8a2012-08-13 09:27:00 -07004890 if (numAttachments < 0) {
4891 _mesa_error(ctx, GL_INVALID_VALUE,
4892 "%s(numAttachments < 0)", name);
4893 return;
4894 }
4895
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08004896 if (width < 0) {
4897 _mesa_error(ctx, GL_INVALID_VALUE,
4898 "%s(width < 0)", name);
4899 return;
4900 }
4901
4902 if (height < 0) {
4903 _mesa_error(ctx, GL_INVALID_VALUE,
4904 "%s(height < 0)", name);
4905 return;
4906 }
4907
Ian Romanick342be8a2012-08-13 09:27:00 -07004908 /* The GL_ARB_invalidate_subdata spec says:
4909 *
4910 * "If an attachment is specified that does not exist in the
4911 * framebuffer bound to <target>, it is ignored."
4912 *
4913 * It also says:
4914 *
4915 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
4916 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
4917 * INVALID_OPERATION is generated."
4918 *
4919 * No mention is made of GL_AUXi being out of range. Therefore, we allow
4920 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
4921 * set of retrictions).
4922 */
4923 for (i = 0; i < numAttachments; i++) {
4924 if (_mesa_is_winsys_fbo(fb)) {
4925 switch (attachments[i]) {
4926 case GL_ACCUM:
4927 case GL_AUX0:
4928 case GL_AUX1:
4929 case GL_AUX2:
4930 case GL_AUX3:
4931 /* Accumulation buffers and auxilary buffers were removed in
4932 * OpenGL 3.1, and they never existed in OpenGL ES.
4933 */
Paul Berrydbd61352012-11-27 12:26:51 -08004934 if (ctx->API != API_OPENGL_COMPAT)
Ian Romanick342be8a2012-08-13 09:27:00 -07004935 goto invalid_enum;
4936 break;
4937 case GL_COLOR:
4938 case GL_DEPTH:
4939 case GL_STENCIL:
4940 break;
4941 case GL_BACK_LEFT:
4942 case GL_BACK_RIGHT:
4943 case GL_FRONT_LEFT:
4944 case GL_FRONT_RIGHT:
4945 if (!_mesa_is_desktop_gl(ctx))
4946 goto invalid_enum;
4947 break;
4948 default:
4949 goto invalid_enum;
4950 }
4951 } else {
4952 switch (attachments[i]) {
4953 case GL_DEPTH_ATTACHMENT:
4954 case GL_STENCIL_ATTACHMENT:
4955 break;
Eduardo Lima Mitev242ad322014-11-18 16:28:18 +01004956 case GL_DEPTH_STENCIL_ATTACHMENT:
4957 /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
4958 * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
4959 * extension does not make this attachment point valid on ES 2.0.
4960 */
4961 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
4962 break;
4963 /* fallthrough */
Ian Romanick342be8a2012-08-13 09:27:00 -07004964 case GL_COLOR_ATTACHMENT0:
4965 case GL_COLOR_ATTACHMENT1:
4966 case GL_COLOR_ATTACHMENT2:
4967 case GL_COLOR_ATTACHMENT3:
4968 case GL_COLOR_ATTACHMENT4:
4969 case GL_COLOR_ATTACHMENT5:
4970 case GL_COLOR_ATTACHMENT6:
4971 case GL_COLOR_ATTACHMENT7:
4972 case GL_COLOR_ATTACHMENT8:
4973 case GL_COLOR_ATTACHMENT9:
4974 case GL_COLOR_ATTACHMENT10:
4975 case GL_COLOR_ATTACHMENT11:
4976 case GL_COLOR_ATTACHMENT12:
4977 case GL_COLOR_ATTACHMENT13:
4978 case GL_COLOR_ATTACHMENT14:
4979 case GL_COLOR_ATTACHMENT15: {
Brian Paul859c3872012-11-04 16:43:44 -07004980 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
Ian Romanick342be8a2012-08-13 09:27:00 -07004981 if (k >= ctx->Const.MaxColorAttachments) {
4982 _mesa_error(ctx, GL_INVALID_OPERATION,
4983 "%s(attachment >= max. color attachments)", name);
4984 return;
4985 }
Constantin Baranov53904c62013-10-13 01:17:15 +03004986 break;
Ian Romanick342be8a2012-08-13 09:27:00 -07004987 }
4988 default:
4989 goto invalid_enum;
4990 }
4991 }
4992 }
4993
4994 /* We don't actually do anything for this yet. Just return after
4995 * validating the parameters and generating the required errors.
4996 */
4997 return;
4998
4999invalid_enum:
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08005000 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005001 _mesa_enum_to_string(attachments[i]));
Ian Romanick342be8a2012-08-13 09:27:00 -07005002 return;
5003}
5004
Rob Clark0c42b5f2018-11-01 11:10:46 -04005005static struct gl_renderbuffer_attachment *
5006get_fb_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
5007 const GLenum attachment)
5008{
5009 switch (attachment) {
5010 case GL_COLOR:
5011 return &fb->Attachment[BUFFER_BACK_LEFT];
5012 case GL_COLOR_ATTACHMENT0:
5013 case GL_COLOR_ATTACHMENT1:
5014 case GL_COLOR_ATTACHMENT2:
5015 case GL_COLOR_ATTACHMENT3:
5016 case GL_COLOR_ATTACHMENT4:
5017 case GL_COLOR_ATTACHMENT5:
5018 case GL_COLOR_ATTACHMENT6:
5019 case GL_COLOR_ATTACHMENT7:
5020 case GL_COLOR_ATTACHMENT8:
5021 case GL_COLOR_ATTACHMENT9:
5022 case GL_COLOR_ATTACHMENT10:
5023 case GL_COLOR_ATTACHMENT11:
5024 case GL_COLOR_ATTACHMENT12:
5025 case GL_COLOR_ATTACHMENT13:
5026 case GL_COLOR_ATTACHMENT14:
Tapani Pälli9762a9f2019-02-14 09:02:31 +02005027 case GL_COLOR_ATTACHMENT15: {
5028 const unsigned i = attachment - GL_COLOR_ATTACHMENT0;
5029 if (i >= ctx->Const.MaxColorAttachments)
5030 return NULL;
Marcin Ślusarzc3a251f2020-07-24 19:51:30 +02005031 assert(BUFFER_COLOR0 + i < ARRAY_SIZE(fb->Attachment));
Tapani Pälli9762a9f2019-02-14 09:02:31 +02005032 return &fb->Attachment[BUFFER_COLOR0 + i];
5033 }
Rob Clark0c42b5f2018-11-01 11:10:46 -04005034 case GL_DEPTH:
5035 case GL_DEPTH_ATTACHMENT:
5036 case GL_DEPTH_STENCIL_ATTACHMENT:
5037 return &fb->Attachment[BUFFER_DEPTH];
5038 case GL_STENCIL:
5039 case GL_STENCIL_ATTACHMENT:
5040 return &fb->Attachment[BUFFER_STENCIL];
5041 default:
5042 return NULL;
5043 }
5044}
5045
5046static void
5047discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
5048 GLsizei numAttachments, const GLenum *attachments)
5049{
5050 if (!ctx->Driver.DiscardFramebuffer)
5051 return;
5052
5053 for (int i = 0; i < numAttachments; i++) {
5054 struct gl_renderbuffer_attachment *att =
5055 get_fb_attachment(ctx, fb, attachments[i]);
5056
5057 if (!att)
5058 continue;
5059
Eric Anholtdb2ae512019-01-30 09:33:53 -08005060 /* If we're asked to invalidate just depth or just stencil, but the
5061 * attachment is packed depth/stencil, then we can only use
5062 * Driver.DiscardFramebuffer if the attachments list includes both depth
5063 * and stencil and they both point at the same renderbuffer.
5064 */
5065 if ((attachments[i] == GL_DEPTH_ATTACHMENT ||
5066 attachments[i] == GL_STENCIL_ATTACHMENT) &&
5067 (!att->Renderbuffer ||
5068 att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL)) {
5069 GLenum other_format = (attachments[i] == GL_DEPTH_ATTACHMENT ?
5070 GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
5071 bool has_both = false;
5072 for (int j = 0; j < numAttachments; j++) {
Eric Anholt3be4b892020-01-13 13:06:01 -08005073 if (attachments[j] == other_format) {
Eric Anholtdb2ae512019-01-30 09:33:53 -08005074 has_both = true;
Eric Anholt3be4b892020-01-13 13:06:01 -08005075 break;
5076 }
Eric Anholtdb2ae512019-01-30 09:33:53 -08005077 }
5078
5079 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer !=
5080 fb->Attachment[BUFFER_STENCIL].Renderbuffer || !has_both)
5081 continue;
5082 }
5083
Rob Clark0c42b5f2018-11-01 11:10:46 -04005084 ctx->Driver.DiscardFramebuffer(ctx, fb, att);
5085 }
5086}
Brian Paulc1377ed2014-03-22 10:31:58 -06005087
Ian Romanick342be8a2012-08-13 09:27:00 -07005088void GLAPIENTRY
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005089_mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5090 const GLenum *attachments, GLint x,
5091 GLint y, GLsizei width, GLsizei height)
5092{
5093 /* no-op */
5094}
5095
5096
5097void GLAPIENTRY
Ian Romanick342be8a2012-08-13 09:27:00 -07005098_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
5099 const GLenum *attachments, GLint x, GLint y,
5100 GLsizei width, GLsizei height)
5101{
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005102 struct gl_framebuffer *fb;
5103 GET_CURRENT_CONTEXT(ctx);
5104
5105 fb = get_framebuffer_target(ctx, target);
5106 if (!fb) {
5107 _mesa_error(ctx, GL_INVALID_ENUM,
5108 "glInvalidateSubFramebuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005109 _mesa_enum_to_string(target));
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005110 return;
5111 }
5112
5113 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
Ian Romanick342be8a2012-08-13 09:27:00 -07005114 x, y, width, height,
5115 "glInvalidateSubFramebuffer");
5116}
5117
Brian Paulc1377ed2014-03-22 10:31:58 -06005118
Ian Romanick342be8a2012-08-13 09:27:00 -07005119void GLAPIENTRY
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005120_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
5121 GLsizei numAttachments,
5122 const GLenum *attachments,
5123 GLint x, GLint y,
5124 GLsizei width, GLsizei height)
5125{
5126 struct gl_framebuffer *fb;
5127 GET_CURRENT_CONTEXT(ctx);
5128
5129 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5130 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5131 * default draw framebuffer is affected."
5132 */
5133 if (framebuffer) {
5134 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5135 "glInvalidateNamedFramebufferSubData");
5136 if (!fb)
5137 return;
5138 }
5139 else
5140 fb = ctx->WinSysDrawBuffer;
5141
5142 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5143 x, y, width, height,
5144 "glInvalidateNamedFramebufferSubData");
5145}
5146
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005147void GLAPIENTRY
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005148_mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5149 const GLenum *attachments)
5150{
Rob Clark0c42b5f2018-11-01 11:10:46 -04005151 struct gl_framebuffer *fb;
5152 GET_CURRENT_CONTEXT(ctx);
5153
5154 fb = get_framebuffer_target(ctx, target);
5155 if (!fb)
5156 return;
5157
5158 discard_framebuffer(ctx, fb, numAttachments, attachments);
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005159}
5160
5161
5162void GLAPIENTRY
Ian Romanick342be8a2012-08-13 09:27:00 -07005163_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
5164 const GLenum *attachments)
5165{
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005166 struct gl_framebuffer *fb;
5167 GET_CURRENT_CONTEXT(ctx);
5168
5169 fb = get_framebuffer_target(ctx, target);
5170 if (!fb) {
5171 _mesa_error(ctx, GL_INVALID_ENUM,
5172 "glInvalidateFramebuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005173 _mesa_enum_to_string(target));
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005174 return;
5175 }
5176
Ian Romanick342be8a2012-08-13 09:27:00 -07005177 /* The GL_ARB_invalidate_subdata spec says:
5178 *
5179 * "The command
5180 *
5181 * void InvalidateFramebuffer(enum target,
5182 * sizei numAttachments,
5183 * const enum *attachments);
5184 *
5185 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5186 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5187 * <MAX_VIEWPORT_DIMS[1]> respectively."
5188 */
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005189 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
Brian Paulc1377ed2014-03-22 10:31:58 -06005190 0, 0,
Samuel Iglesias Gonsálvezaa849d92016-03-01 12:02:27 +01005191 ctx->Const.MaxViewportWidth,
5192 ctx->Const.MaxViewportHeight,
Ian Romanick342be8a2012-08-13 09:27:00 -07005193 "glInvalidateFramebuffer");
Rob Clark0c42b5f2018-11-01 11:10:46 -04005194
5195 discard_framebuffer(ctx, fb, numAttachments, attachments);
Ian Romanick342be8a2012-08-13 09:27:00 -07005196}
Tapani Pälli413941e2013-02-18 09:12:27 +02005197
Brian Paulc1377ed2014-03-22 10:31:58 -06005198
Tapani Pälli413941e2013-02-18 09:12:27 +02005199void GLAPIENTRY
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005200_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
5201 GLsizei numAttachments,
5202 const GLenum *attachments)
5203{
5204 struct gl_framebuffer *fb;
5205 GET_CURRENT_CONTEXT(ctx);
5206
5207 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5208 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5209 * default draw framebuffer is affected."
5210 */
5211 if (framebuffer) {
5212 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5213 "glInvalidateNamedFramebufferData");
5214 if (!fb)
5215 return;
5216 }
5217 else
5218 fb = ctx->WinSysDrawBuffer;
5219
5220 /* The GL_ARB_invalidate_subdata spec says:
5221 *
5222 * "The command
5223 *
5224 * void InvalidateFramebuffer(enum target,
5225 * sizei numAttachments,
5226 * const enum *attachments);
5227 *
5228 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5229 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5230 * <MAX_VIEWPORT_DIMS[1]> respectively."
5231 */
5232 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5233 0, 0,
Samuel Iglesias Gonsálvezaa849d92016-03-01 12:02:27 +01005234 ctx->Const.MaxViewportWidth,
5235 ctx->Const.MaxViewportHeight,
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005236 "glInvalidateNamedFramebufferData");
5237}
5238
5239
5240void GLAPIENTRY
Tapani Pälli413941e2013-02-18 09:12:27 +02005241_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
5242 const GLenum *attachments)
5243{
5244 struct gl_framebuffer *fb;
5245 GLint i;
5246
5247 GET_CURRENT_CONTEXT(ctx);
5248
5249 fb = get_framebuffer_target(ctx, target);
5250 if (!fb) {
5251 _mesa_error(ctx, GL_INVALID_ENUM,
5252 "glDiscardFramebufferEXT(target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005253 _mesa_enum_to_string(target));
Tapani Pälli413941e2013-02-18 09:12:27 +02005254 return;
5255 }
5256
5257 if (numAttachments < 0) {
5258 _mesa_error(ctx, GL_INVALID_VALUE,
5259 "glDiscardFramebufferEXT(numAttachments < 0)");
5260 return;
5261 }
5262
5263 for (i = 0; i < numAttachments; i++) {
5264 switch (attachments[i]) {
5265 case GL_COLOR:
5266 case GL_DEPTH:
5267 case GL_STENCIL:
5268 if (_mesa_is_user_fbo(fb))
5269 goto invalid_enum;
5270 break;
5271 case GL_COLOR_ATTACHMENT0:
5272 case GL_DEPTH_ATTACHMENT:
5273 case GL_STENCIL_ATTACHMENT:
5274 if (_mesa_is_winsys_fbo(fb))
5275 goto invalid_enum;
5276 break;
5277 default:
5278 goto invalid_enum;
5279 }
5280 }
5281
Rob Clark0c42b5f2018-11-01 11:10:46 -04005282 discard_framebuffer(ctx, fb, numAttachments, attachments);
Tapani Pälli413941e2013-02-18 09:12:27 +02005283
5284 return;
5285
5286invalid_enum:
5287 _mesa_error(ctx, GL_INVALID_ENUM,
5288 "glDiscardFramebufferEXT(attachment %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005289 _mesa_enum_to_string(attachments[i]));
Tapani Pälli413941e2013-02-18 09:12:27 +02005290}
Rhys Perry67f40da2018-06-14 19:56:28 -06005291
5292static void
5293sample_locations(struct gl_context *ctx, struct gl_framebuffer *fb,
5294 GLuint start, GLsizei count, const GLfloat *v, bool no_error,
5295 const char *name)
5296{
5297 GLsizei i;
5298
5299 if (!no_error) {
5300 if (!ctx->Extensions.ARB_sample_locations) {
5301 _mesa_error(ctx, GL_INVALID_OPERATION,
5302 "%s not supported "
5303 "(ARB_sample_locations not available)", name);
5304 return;
5305 }
5306
5307 if (start + count > MAX_SAMPLE_LOCATION_TABLE_SIZE) {
5308 _mesa_error(ctx, GL_INVALID_VALUE,
5309 "%s(start+size > sample location table size)", name);
5310 return;
5311 }
5312 }
5313
5314 if (!fb->SampleLocationTable) {
5315 size_t size = MAX_SAMPLE_LOCATION_TABLE_SIZE * 2 * sizeof(GLfloat);
5316 fb->SampleLocationTable = malloc(size);
Eric Engestrom9a4bd6b2018-06-18 11:39:05 +01005317 if (!fb->SampleLocationTable) {
Rhys Perry67f40da2018-06-14 19:56:28 -06005318 _mesa_error(ctx, GL_OUT_OF_MEMORY,
5319 "Cannot allocate sample location table");
Eric Engestrom9a4bd6b2018-06-18 11:39:05 +01005320 return;
5321 }
Rhys Perry67f40da2018-06-14 19:56:28 -06005322 for (i = 0; i < MAX_SAMPLE_LOCATION_TABLE_SIZE * 2; i++)
5323 fb->SampleLocationTable[i] = 0.5f;
5324 }
5325
5326 for (i = 0; i < count * 2; i++) {
5327 /* The ARB_sample_locations spec says:
5328 *
5329 * Sample locations outside of [0,1] result in undefined
5330 * behavior.
5331 *
5332 * To simplify driver implementations, we choose to clamp to
5333 * [0,1] and change NaN into 0.5.
5334 */
5335 if (isnan(v[i]) || v[i] < 0.0f || v[i] > 1.0f) {
5336 static GLuint msg_id = 0;
5337 static const char* msg = "Invalid sample location specified";
5338 _mesa_debug_get_id(&msg_id);
5339
5340 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_UNDEFINED,
5341 msg_id, MESA_DEBUG_SEVERITY_HIGH, strlen(msg), msg);
5342 }
5343
5344 if (isnan(v[i]))
5345 fb->SampleLocationTable[start * 2 + i] = 0.5f;
5346 else
Alyssa Rosenzweig05bacdb2020-05-19 11:08:51 -04005347 fb->SampleLocationTable[start * 2 + i] = SATURATE(v[i]);
Rhys Perry67f40da2018-06-14 19:56:28 -06005348 }
5349
5350 if (fb == ctx->DrawBuffer)
5351 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
5352}
5353
5354void GLAPIENTRY
5355_mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
5356 GLsizei count, const GLfloat *v)
5357{
5358 struct gl_framebuffer *fb;
5359
5360 GET_CURRENT_CONTEXT(ctx);
5361
5362 fb = get_framebuffer_target(ctx, target);
5363 if (!fb) {
5364 _mesa_error(ctx, GL_INVALID_ENUM,
5365 "glFramebufferSampleLocationsfvARB(target %s)",
5366 _mesa_enum_to_string(target));
5367 return;
5368 }
5369
5370 sample_locations(ctx, fb, start, count, v, false,
5371 "glFramebufferSampleLocationsfvARB");
5372}
5373
5374void GLAPIENTRY
5375_mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
5376 GLsizei count, const GLfloat *v)
5377{
5378 struct gl_framebuffer *fb;
5379
5380 GET_CURRENT_CONTEXT(ctx);
5381
5382 if (framebuffer) {
5383 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5384 "glNamedFramebufferSampleLocationsfvARB");
5385 if (!fb)
5386 return;
5387 }
5388 else
5389 fb = ctx->WinSysDrawBuffer;
5390
5391 sample_locations(ctx, fb, start, count, v, false,
5392 "glNamedFramebufferSampleLocationsfvARB");
5393}
5394
5395void GLAPIENTRY
5396_mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
5397 GLsizei count, const GLfloat *v)
5398{
5399 GET_CURRENT_CONTEXT(ctx);
5400 sample_locations(ctx, get_framebuffer_target(ctx, target), start,
5401 count, v, true, "glFramebufferSampleLocationsfvARB");
5402}
5403
5404void GLAPIENTRY
5405_mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
5406 GLuint start, GLsizei count,
5407 const GLfloat *v)
5408{
5409 GET_CURRENT_CONTEXT(ctx);
5410 sample_locations(ctx, _mesa_lookup_framebuffer(ctx, framebuffer), start,
5411 count, v, true, "glNamedFramebufferSampleLocationsfvARB");
5412}
5413
5414void GLAPIENTRY
5415_mesa_EvaluateDepthValuesARB(void)
5416{
5417 GET_CURRENT_CONTEXT(ctx);
5418
5419 if (!ctx->Extensions.ARB_sample_locations) {
5420 _mesa_error(ctx, GL_INVALID_OPERATION,
5421 "EvaluateDepthValuesARB not supported (neither "
5422 "ARB_sample_locations nor NV_sample_locations is available)");
5423 return;
5424 }
5425
5426 if (ctx->Driver.EvaluateDepthValues)
5427 ctx->Driver.EvaluateDepthValues(ctx);
5428}