blob: 600c941a24f281598eeec1fe900d1a87f756e12e [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-Prayer34852122020-09-04 14:07:04 +0200177 _mesa_HashInsert(ctx->Shared->FrameBuffers, id, fb, true);
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 }
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +0200186 _mesa_HashInsert(ctx->Shared->FrameBuffers, id, fb, false);
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) {
Erik Faye-Lund9e13a162020-09-22 12:18:30 +0200347 case GL_FRONT:
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400348 case GL_FRONT_LEFT:
Marek Olšákd58a3902016-09-08 21:02:29 +0200349 /* Front buffers can be allocated on the first use, but
350 * glGetFramebufferAttachmentParameteriv must work even if that
351 * allocation hasn't happened yet. In such case, use the back buffer,
352 * which should be the same.
353 */
354 if (fb->Attachment[BUFFER_FRONT_LEFT].Type == GL_NONE)
355 return &fb->Attachment[BUFFER_BACK_LEFT];
356 else
357 return &fb->Attachment[BUFFER_FRONT_LEFT];
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400358 case GL_FRONT_RIGHT:
Marek Olšákd58a3902016-09-08 21:02:29 +0200359 /* Same as above. */
360 if (fb->Attachment[BUFFER_FRONT_RIGHT].Type == GL_NONE)
361 return &fb->Attachment[BUFFER_BACK_RIGHT];
362 else
363 return &fb->Attachment[BUFFER_FRONT_RIGHT];
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400364 case GL_BACK_LEFT:
365 return &fb->Attachment[BUFFER_BACK_LEFT];
366 case GL_BACK_RIGHT:
367 return &fb->Attachment[BUFFER_BACK_RIGHT];
Kenneth Graunke4f538c32017-10-26 11:44:09 -0700368 case GL_BACK:
369 /* The ARB_ES3_1_compatibility spec says:
370 *
371 * "Since this command can only query a single framebuffer
372 * attachment, BACK is equivalent to BACK_LEFT."
373 */
374 if (ctx->Extensions.ARB_ES3_1_compatibility)
375 return &fb->Attachment[BUFFER_BACK_LEFT];
376 return NULL;
Brian Paul61ec2052010-06-22 08:37:44 -0600377 case GL_AUX0:
378 if (fb->Visual.numAuxBuffers == 1) {
379 return &fb->Attachment[BUFFER_AUX0];
380 }
381 return NULL;
Ian Romanicka8328cc2011-10-03 12:02:18 -0700382
383 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
384 *
385 * "If the default framebuffer is bound to target, then attachment must
386 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
387 * identifying a color buffer; DEPTH, identifying the depth buffer; or
388 * STENCIL, identifying the stencil buffer."
389 *
390 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
391 * language. However, revision #33 of the ARB_framebuffer_object spec
392 * says:
393 *
394 * "If the default framebuffer is bound to <target>, then <attachment>
395 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
396 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
397 * depth buffer, or the stencil buffer, and <pname> may be
398 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
399 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
400 *
401 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
402 * from glext.h, so shipping apps should not use those values.
403 *
404 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
405 * support queries of the window system FBO.
406 */
407 case GL_DEPTH:
Brian Paul61ec2052010-06-22 08:37:44 -0600408 return &fb->Attachment[BUFFER_DEPTH];
Ian Romanicka8328cc2011-10-03 12:02:18 -0700409 case GL_STENCIL:
Brian Paul61ec2052010-06-22 08:37:44 -0600410 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul3deaa012005-02-07 05:08:24 +0000411 default:
412 return NULL;
413 }
414}
415
416
Brian Paul61ec2052010-06-22 08:37:44 -0600417
Brian Pauld9468c92005-02-10 16:08:07 +0000418/**
419 * Remove any texture or renderbuffer attached to the given attachment
420 * point. Update reference counts, etc.
421 */
Brian Paul94512812014-02-01 08:58:43 -0700422static void
423remove_attachment(struct gl_context *ctx,
424 struct gl_renderbuffer_attachment *att)
Brian Paul3deaa012005-02-07 05:08:24 +0000425{
Eric Anholtc810e672013-05-10 12:36:43 -0700426 struct gl_renderbuffer *rb = att->Renderbuffer;
427
428 /* tell driver that we're done rendering to this texture. */
429 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700430 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700431
Brian Paul3deaa012005-02-07 05:08:24 +0000432 if (att->Type == GL_TEXTURE) {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800433 assert(att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100434 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800435 assert(!att->Texture);
Brian Paul3deaa012005-02-07 05:08:24 +0000436 }
Brian Paul0e31e022005-12-01 00:25:00 +0000437 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800438 assert(!att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100439 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800440 assert(!att->Renderbuffer);
Brian Paul3deaa012005-02-07 05:08:24 +0000441 }
442 att->Type = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000443 att->Complete = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +0000444}
445
Eric Anholt749a9272013-04-22 10:38:41 -0700446/**
Ian Romanickfb497132013-07-27 12:04:20 -0700447 * Verify a couple error conditions that will lead to an incomplete FBO and
448 * may cause problems for the driver's RenderTexture path.
449 */
450static bool
451driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
452{
453 const struct gl_texture_image *const texImage =
454 att->Texture->Image[att->CubeMapFace][att->TextureLevel];
455
Marek Olšák8a101922016-05-30 16:29:18 +0200456 if (!texImage ||
457 texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
Ian Romanickfb497132013-07-27 12:04:20 -0700458 return false;
459
Ian Romanick41485fe2013-07-27 12:16:56 -0700460 if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
461 && att->Zoffset >= texImage->Height)
462 || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
463 && att->Zoffset >= texImage->Depth))
464 return false;
465
Ian Romanickfb497132013-07-27 12:04:20 -0700466 return true;
467}
468
469/**
Eric Anholt749a9272013-04-22 10:38:41 -0700470 * Create a renderbuffer which will be set up by the driver to wrap the
471 * texture image slice.
472 *
473 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
474 * to share most of their framebuffer rendering code between winsys,
475 * renderbuffer, and texture attachments.
476 *
477 * The allocated renderbuffer uses a non-zero Name so that drivers can check
478 * it for determining vertical orientation, but we use ~0 to make it fairly
479 * unambiguous with actual user (non-texture) renderbuffers.
480 */
481void
482_mesa_update_texture_renderbuffer(struct gl_context *ctx,
483 struct gl_framebuffer *fb,
484 struct gl_renderbuffer_attachment *att)
485{
486 struct gl_texture_image *texImage;
487 struct gl_renderbuffer *rb;
488
Eric Anholte98c39c2013-05-10 11:51:01 -0700489 texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
Eric Anholt749a9272013-04-22 10:38:41 -0700490
491 rb = att->Renderbuffer;
492 if (!rb) {
493 rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
494 if (!rb) {
495 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
496 return;
497 }
Timothy Arceri8046a942017-04-07 07:55:17 +1000498 att->Renderbuffer = rb;
Eric Anholt749a9272013-04-22 10:38:41 -0700499
500 /* This can't get called on a texture renderbuffer, so set it to NULL
501 * for clarity compared to user renderbuffers.
502 */
503 rb->AllocStorage = NULL;
Eric Anholtc810e672013-05-10 12:36:43 -0700504
505 rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
Eric Anholt749a9272013-04-22 10:38:41 -0700506 }
507
Ian Romanick2f9fe2d2013-07-28 13:08:27 -0700508 if (!texImage)
509 return;
510
Eric Anholt77a405d2013-04-22 11:04:21 -0700511 rb->_BaseFormat = texImage->_BaseFormat;
512 rb->Format = texImage->TexFormat;
513 rb->InternalFormat = texImage->InternalFormat;
514 rb->Width = texImage->Width2;
515 rb->Height = texImage->Height2;
Marek Olšáka3969aa2013-11-20 01:47:36 +0100516 rb->Depth = texImage->Depth2;
Eric Anholt77a405d2013-04-22 11:04:21 -0700517 rb->NumSamples = texImage->NumSamples;
Marek Olšák328c1c82018-06-11 17:24:16 -0400518 rb->NumStorageSamples = texImage->NumSamples;
Eric Anholte98c39c2013-05-10 11:51:01 -0700519 rb->TexImage = texImage;
Eric Anholt77a405d2013-04-22 11:04:21 -0700520
Ian Romanickfb497132013-07-27 12:04:20 -0700521 if (driver_RenderTexture_is_safe(att))
522 ctx->Driver.RenderTexture(ctx, fb, att);
Eric Anholt749a9272013-04-22 10:38:41 -0700523}
Brian Paul3deaa012005-02-07 05:08:24 +0000524
Brian Pauld9468c92005-02-10 16:08:07 +0000525/**
526 * Bind a texture object to an attachment point.
527 * The previous binding, if any, will be removed first.
528 */
Brian Paul94512812014-02-01 08:58:43 -0700529static void
530set_texture_attachment(struct gl_context *ctx,
531 struct gl_framebuffer *fb,
532 struct gl_renderbuffer_attachment *att,
533 struct gl_texture_object *texObj,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -0800534 GLenum texTarget, GLuint level, GLsizei samples,
535 GLuint layer, GLboolean layered)
Brian Paul3deaa012005-02-07 05:08:24 +0000536{
Eric Anholtc810e672013-05-10 12:36:43 -0700537 struct gl_renderbuffer *rb = att->Renderbuffer;
538
539 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700540 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700541
Brian Paul0e31e022005-12-01 00:25:00 +0000542 if (att->Texture == texObj) {
543 /* re-attaching same texture */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800544 assert(att->Type == GL_TEXTURE);
Brian Paul0e31e022005-12-01 00:25:00 +0000545 }
546 else {
547 /* new attachment */
Brian Paul94512812014-02-01 08:58:43 -0700548 remove_attachment(ctx, att);
Brian Paul0e31e022005-12-01 00:25:00 +0000549 att->Type = GL_TEXTURE;
Brian9e01b912007-08-13 11:29:46 +0100550 assert(!att->Texture);
551 _mesa_reference_texobj(&att->Texture, texObj);
Brian Paul0e31e022005-12-01 00:25:00 +0000552 }
Eric Anholt749a9272013-04-22 10:38:41 -0700553 invalidate_framebuffer(fb);
Brian Paul0e31e022005-12-01 00:25:00 +0000554
555 /* always update these fields */
Brian Paul3deaa012005-02-07 05:08:24 +0000556 att->TextureLevel = level;
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -0800557 att->NumSamples = samples;
Brian Paul26f1ad62009-10-23 18:15:55 -0600558 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
Laura Ekstrand085c67d2015-03-02 16:48:59 -0800559 att->Zoffset = layer;
Jordan Justena6280802013-04-18 10:08:50 -0700560 att->Layered = layered;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000561 att->Complete = GL_FALSE;
Brian Paul519b23b2006-03-20 18:51:57 +0000562
Eric Anholt749a9272013-04-22 10:38:41 -0700563 _mesa_update_texture_renderbuffer(ctx, fb, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000564}
565
566
Brian Pauld9468c92005-02-10 16:08:07 +0000567/**
568 * Bind a renderbuffer to an attachment point.
569 * The previous binding, if any, will be removed first.
570 */
Brian Paul94512812014-02-01 08:58:43 -0700571static void
572set_renderbuffer_attachment(struct gl_context *ctx,
573 struct gl_renderbuffer_attachment *att,
574 struct gl_renderbuffer *rb)
Brian Paul3deaa012005-02-07 05:08:24 +0000575{
Brian Paulea4fe662006-03-26 05:22:17 +0000576 /* XXX check if re-doing same attachment, exit early */
Brian Paul94512812014-02-01 08:58:43 -0700577 remove_attachment(ctx, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000578 att->Type = GL_RENDERBUFFER_EXT;
Brian Paul2c6f9112005-02-24 05:47:06 +0000579 att->Texture = NULL; /* just to be safe */
James Legg1581e122015-02-07 23:33:15 +0000580 att->Layered = GL_FALSE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000581 att->Complete = GL_FALSE;
Briandccd9c42007-04-02 09:56:28 -0600582 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
Brian Paul3deaa012005-02-07 05:08:24 +0000583}
584
Brian Paulddc82ee2005-02-05 19:56:45 +0000585
Brian Paulf0bbbf62005-02-09 03:50:30 +0000586/**
Brian Paule4b23562005-05-04 20:11:35 +0000587 * Fallback for ctx->Driver.FramebufferRenderbuffer()
Brian Paul84716042005-11-16 04:05:54 +0000588 * Attach a renderbuffer object to a framebuffer object.
Brian Paule4b23562005-05-04 20:11:35 +0000589 */
590void
Laura Ekstrand3d100372015-02-27 17:23:59 -0800591_mesa_FramebufferRenderbuffer_sw(struct gl_context *ctx,
592 struct gl_framebuffer *fb,
593 GLenum attachment,
594 struct gl_renderbuffer *rb)
Brian Paule4b23562005-05-04 20:11:35 +0000595{
Brian Paul84716042005-11-16 04:05:54 +0000596 struct gl_renderbuffer_attachment *att;
597
Timothy Arcerif0857fe2017-10-16 11:59:31 +1100598 simple_mtx_lock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +0000599
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200600 att = get_attachment(ctx, fb, attachment, NULL);
Matt Turnerbfcdb842015-02-20 20:18:47 -0800601 assert(att);
Brian Paule4b23562005-05-04 20:11:35 +0000602 if (rb) {
Brian Paul94512812014-02-01 08:58:43 -0700603 set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700604 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
605 /* do stencil attachment here (depth already done above) */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200606 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
Brian Paul30590072009-01-21 11:06:11 -0700607 assert(att);
Brian Paul94512812014-02-01 08:58:43 -0700608 set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700609 }
Marek Olšákdf818d52011-03-06 05:26:12 +0100610 rb->AttachedAnytime = GL_TRUE;
Brian Paule4b23562005-05-04 20:11:35 +0000611 }
612 else {
Brian Paul94512812014-02-01 08:58:43 -0700613 remove_attachment(ctx, att);
James Legg846c7152014-05-23 12:25:37 +0100614 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
615 /* detach stencil (depth was detached above) */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -0200616 att = get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT, NULL);
James Legg846c7152014-05-23 12:25:37 +0100617 assert(att);
618 remove_attachment(ctx, att);
619 }
Brian Paule4b23562005-05-04 20:11:35 +0000620 }
Brian Paulea4fe662006-03-26 05:22:17 +0000621
Brian Paul72966362009-01-21 16:28:38 -0700622 invalidate_framebuffer(fb);
623
Timothy Arcerif0857fe2017-10-16 11:59:31 +1100624 simple_mtx_unlock(&fb->Mutex);
Brian Paule4b23562005-05-04 20:11:35 +0000625}
626
627
628/**
Brian Paul62c66b32011-01-24 19:38:52 -0700629 * Fallback for ctx->Driver.ValidateFramebuffer()
630 * Check if the renderbuffer's formats are supported by the software
631 * renderer.
632 * Drivers should probably override this.
633 */
634void
635_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
636{
637 gl_buffer_index buf;
638 for (buf = 0; buf < BUFFER_COUNT; buf++) {
639 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
640 if (rb) {
641 switch (rb->_BaseFormat) {
642 case GL_ALPHA:
643 case GL_LUMINANCE_ALPHA:
644 case GL_LUMINANCE:
645 case GL_INTENSITY:
Brian Pauld3015652011-01-24 19:38:52 -0700646 case GL_RED:
647 case GL_RG:
Brian Paul62c66b32011-01-24 19:38:52 -0700648 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
649 return;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200650
651 default:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200652 switch (rb->Format) {
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200653 /* XXX This list is likely incomplete. */
Mark Muellereeed49f2014-01-26 15:12:56 -0800654 case MESA_FORMAT_R9G9B9E5_FLOAT:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200655 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
656 return;
657 default:;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200658 /* render buffer format is supported by software rendering */
Marek Olšák9d7698c2011-04-26 02:18:24 +0200659 }
Brian Paul62c66b32011-01-24 19:38:52 -0700660 }
661 }
662 }
663}
664
665
666/**
Marek Olšákf8855a42013-03-14 14:22:56 +0100667 * Return true if the framebuffer has a combined depth/stencil
668 * renderbuffer attached.
669 */
670GLboolean
671_mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
672{
673 const struct gl_renderbuffer_attachment *depth =
674 &fb->Attachment[BUFFER_DEPTH];
675 const struct gl_renderbuffer_attachment *stencil =
676 &fb->Attachment[BUFFER_STENCIL];
677
678 if (depth->Type == stencil->Type) {
679 if (depth->Type == GL_RENDERBUFFER_EXT &&
680 depth->Renderbuffer == stencil->Renderbuffer)
681 return GL_TRUE;
682
683 if (depth->Type == GL_TEXTURE &&
684 depth->Texture == stencil->Texture)
685 return GL_TRUE;
686 }
687
688 return GL_FALSE;
689}
690
691
692/**
Brian Paul9f731c82009-02-17 16:47:54 -0700693 * For debug only.
694 */
695static void
696att_incomplete(const char *msg)
697{
Brian Paul93bcf782012-05-09 12:09:21 -0600698 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
699 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
700 }
Brian Paul9f731c82009-02-17 16:47:54 -0700701}
702
703
704/**
Brian Paulc26c2002009-09-15 17:20:32 -0600705 * For debug only.
706 */
707static void
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700708fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
Brian Paulc26c2002009-09-15 17:20:32 -0600709{
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700710 static GLuint msg_id;
711
Mark Janesb8a1a322018-12-06 16:35:43 -0800712 _mesa_gl_debugf(ctx, &msg_id,
713 MESA_DEBUG_SOURCE_API,
714 MESA_DEBUG_TYPE_OTHER,
715 MESA_DEBUG_SEVERITY_MEDIUM,
716 "FBO incomplete: %s [%d]\n", msg, index);
Eric Anholt3c21a7d2013-06-06 11:13:02 -0700717
Brian Paul93bcf782012-05-09 12:09:21 -0600718 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
719 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
720 }
Brian Paulc26c2002009-09-15 17:20:32 -0600721}
722
723
Brian Paule67f6ee2010-10-22 11:38:23 -0600724/**
725 * Is the given base format a legal format for a color renderbuffer?
726 */
Eric Anholt059cca92011-01-02 17:58:07 -0800727GLboolean
728_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
Brian Paule67f6ee2010-10-22 11:38:23 -0600729{
730 switch (baseFormat) {
731 case GL_RGB:
732 case GL_RGBA:
733 return GL_TRUE;
Marek Olšák6e618532010-10-02 21:53:03 +0200734 case GL_LUMINANCE:
735 case GL_LUMINANCE_ALPHA:
736 case GL_INTENSITY:
Brian Paule67f6ee2010-10-22 11:38:23 -0600737 case GL_ALPHA:
Jordan Justencf300ea2012-12-27 12:41:10 -0800738 return ctx->API == API_OPENGL_COMPAT &&
739 ctx->Extensions.ARB_framebuffer_object;
Brian Paule67f6ee2010-10-22 11:38:23 -0600740 case GL_RED:
741 case GL_RG:
742 return ctx->Extensions.ARB_texture_rg;
743 default:
744 return GL_FALSE;
745 }
746}
747
Tapani Pälli331e5f12020-08-28 13:04:21 +0300748static GLboolean
749is_float_format(GLenum internalFormat)
750{
751 switch (internalFormat) {
752 case GL_R16F:
753 case GL_RG16F:
754 case GL_RGB16F:
755 case GL_RGBA16F:
756 case GL_R32F:
757 case GL_RG32F:
758 case GL_RGB32F:
759 case GL_RGBA32F:
760 return true;
761 default:
762 return false;
763 }
764}
Brian Paule67f6ee2010-10-22 11:38:23 -0600765
766/**
Jordan Justen6c7fa722012-12-27 13:34:44 -0800767 * Is the given base format a legal format for a color renderbuffer?
768 */
769static GLboolean
Brian Paulc1377ed2014-03-22 10:31:58 -0600770is_format_color_renderable(const struct gl_context *ctx, mesa_format format,
771 GLenum internalFormat)
Jordan Justen6c7fa722012-12-27 13:34:44 -0800772{
773 const GLenum baseFormat =
774 _mesa_get_format_base_format(format);
775 GLboolean valid;
776
777 valid = _mesa_is_legal_color_format(ctx, baseFormat);
778 if (!valid || _mesa_is_desktop_gl(ctx)) {
779 return valid;
780 }
781
782 /* Reject additional cases for GLES */
783 switch (internalFormat) {
Tapani Pälli0d356cf2018-05-24 14:05:27 +0300784 case GL_R8_SNORM:
785 case GL_RG8_SNORM:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800786 case GL_RGBA8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +0300787 return _mesa_has_EXT_render_snorm(ctx);
788 case GL_R16_SNORM:
789 case GL_RG16_SNORM:
790 case GL_RGBA16_SNORM:
791 return _mesa_has_EXT_texture_norm16(ctx) &&
792 _mesa_has_EXT_render_snorm(ctx);
Tapani Pälli331e5f12020-08-28 13:04:21 +0300793 case GL_R:
794 case GL_RG:
795 return _mesa_has_EXT_texture_rg(ctx);
796 case GL_R16F:
797 case GL_RG16F:
Tapani Pälli8447b0f2020-09-01 14:20:27 +0300798 return _mesa_is_gles3(ctx) ||
799 (_mesa_has_EXT_color_buffer_half_float(ctx) &&
800 _mesa_has_EXT_texture_rg(ctx));
Tapani Pälli331e5f12020-08-28 13:04:21 +0300801 case GL_RGBA16F:
802 case GL_RGBA32F:
803 return _mesa_has_EXT_color_buffer_float(ctx);
Tapani Pälli8447b0f2020-09-01 14:20:27 +0300804 case GL_RGB16F:
805 return _mesa_has_EXT_color_buffer_half_float(ctx) &&
806 _mesa_has_OES_texture_half_float(ctx);
Jordan Justen6c7fa722012-12-27 13:34:44 -0800807 case GL_RGB32F:
808 case GL_RGB32I:
809 case GL_RGB32UI:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800810 case GL_RGB16I:
811 case GL_RGB16UI:
812 case GL_RGB8_SNORM:
813 case GL_RGB8I:
814 case GL_RGB8UI:
815 case GL_SRGB8:
Eric Anholtc16a7442017-05-01 09:28:33 -0700816 case GL_RGB10:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800817 case GL_RGB9_E5:
Marek Olšák32a33472018-11-09 16:47:46 -0500818 case GL_SR8_EXT:
Jordan Justen6c7fa722012-12-27 13:34:44 -0800819 return GL_FALSE;
820 default:
821 break;
822 }
823
Nicolai Hähnled2b60e42017-09-27 15:25:10 +0200824 if (internalFormat != GL_RGB10_A2 &&
825 (format == MESA_FORMAT_B10G10R10A2_UNORM ||
826 format == MESA_FORMAT_B10G10R10X2_UNORM ||
827 format == MESA_FORMAT_R10G10B10A2_UNORM ||
828 format == MESA_FORMAT_R10G10B10X2_UNORM)) {
Jordan Justen6c7fa722012-12-27 13:34:44 -0800829 return GL_FALSE;
830 }
831
832 return GL_TRUE;
833}
834
Tapani Pälli331e5f12020-08-28 13:04:21 +0300835/**
836 * Check that implements various limitations of floating point
837 * rendering extensions on OpenGL ES.
838 *
839 * Check passes if texture format is not floating point or
840 * is floating point and is color renderable.
841 *
842 * Check fails if texture format is floating point and cannot
843 * be rendered to with current context and set of supported
844 * extensions.
845 */
846static GLboolean
847gles_check_float_renderable(const struct gl_context *ctx,
848 struct gl_renderbuffer_attachment *att)
849{
850 /* Only check floating point texture cases. */
851 if (!att->Texture || !is_float_format(att->Renderbuffer->InternalFormat))
852 return true;
853
854 /* GL_RGBA with unsized GL_FLOAT type, no extension can make this
855 * color renderable.
856 */
857 if (att->Texture->_IsFloat && att->Renderbuffer->_BaseFormat == GL_RGBA)
858 return false;
859
860 /* Unsized GL_HALF_FLOAT supported only with EXT_color_buffer_half_float. */
Tapani Pälli8447b0f2020-09-01 14:20:27 +0300861 if (att->Texture->_IsHalfFloat && !_mesa_has_EXT_color_buffer_half_float(ctx))
Tapani Pälli331e5f12020-08-28 13:04:21 +0300862 return false;
863
864 const struct gl_texture_object *texObj = att->Texture;
865 const struct gl_texture_image *texImage =
866 texObj->Image[att->CubeMapFace][att->TextureLevel];
867
868 return is_format_color_renderable(ctx, texImage->TexFormat,
869 att->Renderbuffer->InternalFormat);
870}
Jordan Justen6c7fa722012-12-27 13:34:44 -0800871
872/**
Brian Paule67f6ee2010-10-22 11:38:23 -0600873 * Is the given base format a legal format for a depth/stencil renderbuffer?
874 */
875static GLboolean
876is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
877{
878 switch (baseFormat) {
879 case GL_DEPTH_COMPONENT:
880 case GL_DEPTH_STENCIL_EXT:
881 return GL_TRUE;
882 default:
883 return GL_FALSE;
884 }
885}
Brian Paulc26c2002009-09-15 17:20:32 -0600886
887
888/**
Brian Paulf0bbbf62005-02-09 03:50:30 +0000889 * Test if an attachment point is complete and update its Complete field.
890 * \param format if GL_COLOR, this is a color attachment point,
891 * if GL_DEPTH, this is a depth component attachment point,
892 * if GL_STENCIL, this is a stencil component attachment point.
893 */
894static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400895test_attachment_completeness(const struct gl_context *ctx, GLenum format,
Brian Paul2c6f9112005-02-24 05:47:06 +0000896 struct gl_renderbuffer_attachment *att)
Brian Paulf0bbbf62005-02-09 03:50:30 +0000897{
898 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
899
900 /* assume complete */
901 att->Complete = GL_TRUE;
902
Brian Paulf0bbbf62005-02-09 03:50:30 +0000903 /* Look for reasons why the attachment might be incomplete */
904 if (att->Type == GL_TEXTURE) {
Brian Paule4b23562005-05-04 20:11:35 +0000905 const struct gl_texture_object *texObj = att->Texture;
Brian Paulb2c3fd92017-12-04 21:27:54 -0700906 const struct gl_texture_image *texImage;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600907 GLenum baseFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000908
Brian Paule4b23562005-05-04 20:11:35 +0000909 if (!texObj) {
Brian Paul9f731c82009-02-17 16:47:54 -0700910 att_incomplete("no texobj");
Brian Paule4b23562005-05-04 20:11:35 +0000911 att->Complete = GL_FALSE;
912 return;
913 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000914
915 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
916 if (!texImage) {
Brian Paul9f731c82009-02-17 16:47:54 -0700917 att_incomplete("no teximage");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000918 att->Complete = GL_FALSE;
919 return;
920 }
921 if (texImage->Width < 1 || texImage->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700922 att_incomplete("teximage width/height=0");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000923 att->Complete = GL_FALSE;
924 return;
925 }
Ian Romanick25281fe2013-07-27 12:27:45 -0700926
927 switch (texObj->Target) {
928 case GL_TEXTURE_3D:
929 if (att->Zoffset >= texImage->Depth) {
930 att_incomplete("bad z offset");
931 att->Complete = GL_FALSE;
932 return;
933 }
934 break;
935 case GL_TEXTURE_1D_ARRAY:
936 if (att->Zoffset >= texImage->Height) {
937 att_incomplete("bad 1D-array layer");
938 att->Complete = GL_FALSE;
939 return;
940 }
941 break;
942 case GL_TEXTURE_2D_ARRAY:
943 if (att->Zoffset >= texImage->Depth) {
944 att_incomplete("bad 2D-array layer");
945 att->Complete = GL_FALSE;
946 return;
947 }
948 break;
949 case GL_TEXTURE_CUBE_MAP_ARRAY:
950 if (att->Zoffset >= texImage->Depth) {
951 att_incomplete("bad cube-array layer");
952 att->Complete = GL_FALSE;
953 return;
954 }
955 break;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000956 }
957
Ilia Mirkin68c4af12016-02-17 20:31:38 -0500958 baseFormat = texImage->_BaseFormat;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600959
Brian Paulf0bbbf62005-02-09 03:50:30 +0000960 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800961 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700962 att_incomplete("bad format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000963 att->Complete = GL_FALSE;
964 return;
965 }
Brian Paul1f7c9142009-09-30 20:28:45 -0600966 if (_mesa_is_format_compressed(texImage->TexFormat)) {
Eric Anholt957f3c82009-05-15 16:24:59 -0700967 att_incomplete("compressed internalformat");
968 att->Complete = GL_FALSE;
969 return;
970 }
Tapani Pällie3330352015-02-12 14:33:53 +0200971
972 /* OES_texture_float allows creation and use of floating point
973 * textures with GL_FLOAT, GL_HALF_FLOAT but it does not allow
974 * these textures to be used as a render target, this is done via
975 * GL_EXT_color_buffer(_half)_float with set of new sized types.
976 */
Tapani Pälli331e5f12020-08-28 13:04:21 +0300977 if (_mesa_is_gles(ctx) && !gles_check_float_renderable(ctx, att)) {
Tapani Pällie3330352015-02-12 14:33:53 +0200978 att_incomplete("bad internal format");
979 att->Complete = GL_FALSE;
980 return;
981 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000982 }
983 else if (format == GL_DEPTH) {
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600984 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000985 /* OK */
986 }
Ian Romanicka92b9e62013-11-13 14:10:34 -0800987 else if (ctx->Extensions.ARB_depth_texture &&
Ian Romanick49493222013-11-13 14:15:11 -0800988 baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000989 /* OK */
990 }
991 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000992 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700993 att_incomplete("bad depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000994 return;
995 }
996 }
997 else {
Matt Turnerbfcdb842015-02-20 20:18:47 -0800998 assert(format == GL_STENCIL);
Ian Romanicka92b9e62013-11-13 14:10:34 -0800999 if (ctx->Extensions.ARB_depth_texture &&
Ian Romanick49493222013-11-13 14:15:11 -08001000 baseFormat == GL_DEPTH_STENCIL) {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -06001001 /* OK */
Dave Airlie782e71c2015-04-05 13:19:18 +10001002 } else if (ctx->Extensions.ARB_texture_stencil8 &&
1003 baseFormat == GL_STENCIL_INDEX) {
1004 /* OK */
1005 } else {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -06001006 /* no such thing as stencil-only textures */
1007 att_incomplete("illegal stencil texture");
1008 att->Complete = GL_FALSE;
1009 return;
1010 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001011 }
1012 }
Brian Paule4b23562005-05-04 20:11:35 +00001013 else if (att->Type == GL_RENDERBUFFER_EXT) {
Ilia Mirkin68c4af12016-02-17 20:31:38 -05001014 const GLenum baseFormat = att->Renderbuffer->_BaseFormat;
Brian Paul45e76d22009-10-08 20:27:27 -06001015
Matt Turnerbfcdb842015-02-20 20:18:47 -08001016 assert(att->Renderbuffer);
Brian Paul49918882006-03-20 15:27:55 +00001017 if (!att->Renderbuffer->InternalFormat ||
1018 att->Renderbuffer->Width < 1 ||
1019 att->Renderbuffer->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -07001020 att_incomplete("0x0 renderbuffer");
Brian Paulf0bbbf62005-02-09 03:50:30 +00001021 att->Complete = GL_FALSE;
1022 return;
1023 }
1024 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -08001025 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -07001026 att_incomplete("bad renderbuffer color format");
Brian Paulf0bbbf62005-02-09 03:50:30 +00001027 att->Complete = GL_FALSE;
1028 return;
1029 }
1030 }
1031 else if (format == GL_DEPTH) {
Brian Paul45e76d22009-10-08 20:27:27 -06001032 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +00001033 /* OK */
1034 }
Ian Romanick49493222013-11-13 14:15:11 -08001035 else if (baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +00001036 /* OK */
1037 }
1038 else {
Brian Paul9f731c82009-02-17 16:47:54 -07001039 att_incomplete("bad renderbuffer depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +00001040 att->Complete = GL_FALSE;
1041 return;
1042 }
1043 }
1044 else {
1045 assert(format == GL_STENCIL);
Ian Romanick49493222013-11-13 14:15:11 -08001046 if (baseFormat == GL_STENCIL_INDEX ||
1047 baseFormat == GL_DEPTH_STENCIL) {
Brian Paul1ad7b992005-09-28 02:29:50 +00001048 /* OK */
1049 }
1050 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +00001051 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -07001052 att_incomplete("bad renderbuffer stencil format");
Brian Paulf0bbbf62005-02-09 03:50:30 +00001053 return;
1054 }
1055 }
1056 }
Brian Paule4b23562005-05-04 20:11:35 +00001057 else {
Matt Turnerbfcdb842015-02-20 20:18:47 -08001058 assert(att->Type == GL_NONE);
Brian Paule4b23562005-05-04 20:11:35 +00001059 /* complete */
1060 return;
1061 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001062}
1063
1064
1065/**
1066 * Test if the given framebuffer object is complete and update its
1067 * Status field with the results.
Brian Paul3528f692009-01-22 15:13:18 -07001068 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
1069 * driver to make hardware-specific validation/completeness checks.
Brian Paule4b23562005-05-04 20:11:35 +00001070 * Also update the framebuffer's Width and Height fields if the
1071 * framebuffer is complete.
Brian Paulf0bbbf62005-02-09 03:50:30 +00001072 */
Brian Paule4b23562005-05-04 20:11:35 +00001073void
Brian Paulf9288542010-10-22 11:25:14 -06001074_mesa_test_framebuffer_completeness(struct gl_context *ctx,
1075 struct gl_framebuffer *fb)
Brian Paulf0bbbf62005-02-09 03:50:30 +00001076{
Brian Paul989edea2009-01-22 15:05:13 -07001077 GLuint numImages;
1078 GLenum intFormat = GL_NONE; /* color buffers' internal format */
1079 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
Marek Olšák459f05c2018-06-11 18:30:34 -04001080 GLint numColorSamples = -1;
1081 GLint numColorStorageSamples = -1;
1082 GLint numDepthSamples = -1;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001083 GLint fixedSampleLocations = -1;
Brian Paule4b23562005-05-04 20:11:35 +00001084 GLint i;
Brian Paul28b014e2006-04-05 03:05:17 +00001085 GLuint j;
Paul Berry532b1fe2014-01-07 06:29:47 -08001086 /* Covers max_layer_count, is_layered, and layer_tex_target */
1087 bool layer_info_valid = false;
1088 GLuint max_layer_count = 0, att_layer_count;
Brian Paul5306ee72014-01-22 10:02:28 -08001089 bool is_layered = false;
Paul Berry28af1dc2013-11-19 19:01:37 -08001090 GLenum layer_tex_target = 0;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001091 bool has_depth_attachment = false;
1092 bool has_stencil_attachment = false;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001093
Brian Paul36ede892012-01-12 09:17:23 -07001094 assert(_mesa_is_user_fbo(fb));
Brian Paulc7264412005-06-01 00:50:23 +00001095
Marek Olšáke06d6162012-08-04 13:37:03 +02001096 /* we're changing framebuffer fields here */
1097 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1098
Brian Paulf0bbbf62005-02-09 03:50:30 +00001099 numImages = 0;
Brian Paule4b23562005-05-04 20:11:35 +00001100 fb->Width = 0;
1101 fb->Height = 0;
Marek Olšák21d407c2013-03-28 01:50:21 +01001102 fb->_AllColorBuffersFixedPoint = GL_TRUE;
Marek Olšák755648c2013-03-28 01:56:01 +01001103 fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
Kevin Rogovinda819992015-06-17 13:29:50 +03001104 fb->_HasAttachments = true;
Brian Paulff00ab72016-10-10 11:29:14 -06001105 fb->_IntegerBuffers = 0;
Kenneth Graunke5b51d752018-07-21 23:40:16 -07001106 fb->_RGBBuffers = 0;
Ilia Mirkin070a5e52019-02-12 21:32:27 -05001107 fb->_FP32Buffers = 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001108
Brian Paul989edea2009-01-22 15:05:13 -07001109 /* Start at -2 to more easily loop over all attachment points.
1110 * -2: depth buffer
1111 * -1: stencil buffer
1112 * >=0: color buffer
1113 */
Brian Paule4b23562005-05-04 20:11:35 +00001114 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001115 struct gl_renderbuffer_attachment *att;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001116 GLenum f;
Kenneth Graunke69215882019-02-22 01:16:41 -08001117 GLenum baseFormat;
Mark Mueller71fe9432014-01-04 14:11:43 -08001118 mesa_format attFormat;
Paul Berry95140742013-11-19 15:55:51 -08001119 GLenum att_tex_target = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001120
Brian Paul1bc59bf2009-01-22 15:07:34 -07001121 /*
1122 * XXX for ARB_fbo, only check color buffers that are named by
1123 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
1124 */
1125
Brian Paul989edea2009-01-22 15:05:13 -07001126 /* check for attachment completeness
1127 */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001128 if (i == -2) {
Brian Paule4b23562005-05-04 20:11:35 +00001129 att = &fb->Attachment[BUFFER_DEPTH];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001130 test_attachment_completeness(ctx, GL_DEPTH, att);
1131 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001132 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001133 fbo_incomplete(ctx, "depth attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001134 return;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001135 } else if (att->Type != GL_NONE) {
1136 has_depth_attachment = true;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001137 }
1138 }
1139 else if (i == -1) {
Brian Paule4b23562005-05-04 20:11:35 +00001140 att = &fb->Attachment[BUFFER_STENCIL];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001141 test_attachment_completeness(ctx, GL_STENCIL, att);
1142 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +00001143 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001144 fbo_incomplete(ctx, "stencil attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001145 return;
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001146 } else if (att->Type != GL_NONE) {
1147 has_stencil_attachment = true;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001148 }
1149 }
1150 else {
Brian Paule4b23562005-05-04 20:11:35 +00001151 att = &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paulf0bbbf62005-02-09 03:50:30 +00001152 test_attachment_completeness(ctx, GL_COLOR, att);
1153 if (!att->Complete) {
Tapani Pälli8447b0f2020-09-01 14:20:27 +03001154 /* With EXT_color_buffer_half_float, check if attachment was incomplete
1155 * due to invalid format. This is special case for the extension where
1156 * CTS tests expect unsupported framebuffer status instead of incomplete.
1157 */
1158 if ((_mesa_is_gles(ctx) && _mesa_has_EXT_color_buffer_half_float(ctx)) &&
1159 !gles_check_float_renderable(ctx, att)) {
1160 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1161 return;
1162 }
1163
Brian Paule4b23562005-05-04 20:11:35 +00001164 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001165 fbo_incomplete(ctx, "color attachment incomplete", i);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001166 return;
1167 }
1168 }
1169
Brian Paul989edea2009-01-22 15:05:13 -07001170 /* get width, height, format of the renderbuffer/texture
1171 */
Marek Olšák459f05c2018-06-11 18:30:34 -04001172 unsigned attNumSamples, attNumStorageSamples;
1173
Brian Paulf0bbbf62005-02-09 03:50:30 +00001174 if (att->Type == GL_TEXTURE) {
Eric Anholte98c39c2013-05-10 11:51:01 -07001175 const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
Paul Berry95140742013-11-19 15:55:51 -08001176 att_tex_target = att->Texture->Target;
Brian Paul989edea2009-01-22 15:05:13 -07001177 minWidth = MIN2(minWidth, texImg->Width);
1178 maxWidth = MAX2(maxWidth, texImg->Width);
1179 minHeight = MIN2(minHeight, texImg->Height);
1180 maxHeight = MAX2(maxHeight, texImg->Height);
Brian Paula9fc8ba2005-10-05 01:48:07 +00001181 f = texImg->_BaseFormat;
Kenneth Graunke69215882019-02-22 01:16:41 -08001182 baseFormat = f;
Brian Paulca1b5512011-02-28 18:23:23 -07001183 attFormat = texImg->TexFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001184 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001185
Brian Paulc1377ed2014-03-22 10:31:58 -06001186 if (!is_format_color_renderable(ctx, attFormat,
1187 texImg->InternalFormat) &&
Dave Airlie782e71c2015-04-05 13:19:18 +10001188 !is_legal_depth_format(ctx, f) &&
1189 f != GL_STENCIL_INDEX) {
Iago Toral Quirogab6819cd2014-12-15 09:29:55 +01001190 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001191 fbo_incomplete(ctx, "texture attachment incomplete", -1);
Brian Pauled7f3ae2005-06-07 15:03:40 +00001192 return;
1193 }
Chris Forbes61d42ff2012-12-16 20:58:00 +13001194
Chris Forbes61d42ff2012-12-16 20:58:00 +13001195 if (fixedSampleLocations < 0)
1196 fixedSampleLocations = texImg->FixedSampleLocations;
1197 else if (fixedSampleLocations != texImg->FixedSampleLocations) {
1198 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001199 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
Chris Forbes61d42ff2012-12-16 20:58:00 +13001200 return;
1201 }
Marek Olšák459f05c2018-06-11 18:30:34 -04001202
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08001203 if (att->NumSamples > 0)
1204 attNumSamples = att->NumSamples;
1205 else
1206 attNumSamples = texImg->NumSamples;
1207 attNumStorageSamples = attNumSamples;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001208 }
1209 else if (att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul989edea2009-01-22 15:05:13 -07001210 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
1211 maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
1212 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
1213 maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001214 f = att->Renderbuffer->InternalFormat;
Kenneth Graunke69215882019-02-22 01:16:41 -08001215 baseFormat = att->Renderbuffer->_BaseFormat;
Brian Paulca1b5512011-02-28 18:23:23 -07001216 attFormat = att->Renderbuffer->Format;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001217 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +13001218
Chris Forbes61d42ff2012-12-16 20:58:00 +13001219 /* RENDERBUFFER has fixedSampleLocations implicitly true */
1220 if (fixedSampleLocations < 0)
1221 fixedSampleLocations = GL_TRUE;
1222 else if (fixedSampleLocations != GL_TRUE) {
1223 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001224 fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
Chris Forbes61d42ff2012-12-16 20:58:00 +13001225 return;
1226 }
Marek Olšák459f05c2018-06-11 18:30:34 -04001227
1228 attNumSamples = att->Renderbuffer->NumSamples;
1229 attNumStorageSamples = att->Renderbuffer->NumStorageSamples;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001230 }
1231 else {
1232 assert(att->Type == GL_NONE);
1233 continue;
1234 }
1235
Marek Olšák459f05c2018-06-11 18:30:34 -04001236 if (i >= 0) {
1237 /* Color buffers. */
1238 if (numColorSamples < 0) {
1239 assert(numColorStorageSamples < 0);
1240 numColorSamples = attNumSamples;
1241 numColorStorageSamples = attNumStorageSamples;
1242 } else if (numColorSamples != attNumSamples ||
1243 numColorStorageSamples != attNumStorageSamples) {
1244 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1245 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1246 return;
1247 }
1248 } else {
1249 /* Depth/stencil buffers. */
1250 if (numDepthSamples < 0) {
1251 numDepthSamples = attNumSamples;
1252 } else if (numDepthSamples != attNumSamples) {
1253 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1254 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1255 return;
1256 }
1257 }
1258
Brian Paulff00ab72016-10-10 11:29:14 -06001259 /* Update flags describing color buffer datatypes */
Marek Olšák21d407c2013-03-28 01:50:21 +01001260 if (i >= 0) {
1261 GLenum type = _mesa_get_format_datatype(attFormat);
1262
Brian Paulff00ab72016-10-10 11:29:14 -06001263 /* check if integer color */
1264 if (_mesa_is_format_integer_color(attFormat))
1265 fb->_IntegerBuffers |= (1 << i);
1266
Kenneth Graunke69215882019-02-22 01:16:41 -08001267 if (baseFormat == GL_RGB)
Kenneth Graunke5b51d752018-07-21 23:40:16 -07001268 fb->_RGBBuffers |= (1 << i);
1269
Ilia Mirkin070a5e52019-02-12 21:32:27 -05001270 if (type == GL_FLOAT && _mesa_get_format_max_bits(attFormat) > 16)
1271 fb->_FP32Buffers |= (1 << i);
1272
Marek Olšák21d407c2013-03-28 01:50:21 +01001273 fb->_AllColorBuffersFixedPoint =
1274 fb->_AllColorBuffersFixedPoint &&
1275 (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
Marek Olšák755648c2013-03-28 01:56:01 +01001276
1277 fb->_HasSNormOrFloatColorBuffer =
1278 fb->_HasSNormOrFloatColorBuffer ||
1279 type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
Marek Olšák21d407c2013-03-28 01:50:21 +01001280 }
1281
Chris Forbes61d42ff2012-12-16 20:58:00 +13001282 /* Error-check width, height, format */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001283 if (numImages == 1) {
Chris Forbes61d42ff2012-12-16 20:58:00 +13001284 /* save format */
Brian Paul722d9762009-01-20 16:58:49 -07001285 if (i >= 0) {
Brian Paulf0bbbf62005-02-09 03:50:30 +00001286 intFormat = f;
Brian Paul722d9762009-01-20 16:58:49 -07001287 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001288 }
1289 else {
Brian Paul989edea2009-01-22 15:05:13 -07001290 if (!ctx->Extensions.ARB_framebuffer_object) {
1291 /* check that width, height, format are same */
1292 if (minWidth != maxWidth || minHeight != maxHeight) {
1293 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001294 fbo_incomplete(ctx, "width or height mismatch", -1);
Brian Paul989edea2009-01-22 15:05:13 -07001295 return;
1296 }
Brian Paul45bd5c42011-12-16 08:44:43 -07001297 /* check that all color buffers are the same format */
Brian Paul989edea2009-01-22 15:05:13 -07001298 if (intFormat != GL_NONE && f != intFormat) {
1299 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001300 fbo_incomplete(ctx, "format mismatch", -1);
Brian Paul989edea2009-01-22 15:05:13 -07001301 return;
1302 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001303 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001304 }
Marek Olšáka82227c2012-06-15 17:21:05 +02001305
1306 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1307 */
1308 if (att->Type == GL_RENDERBUFFER &&
1309 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1310 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001311 fbo_incomplete(ctx, "unsupported renderbuffer format", i);
Marek Olšáka82227c2012-06-15 17:21:05 +02001312 return;
1313 }
Jordan Justen5da82882013-04-18 10:20:05 -07001314
1315 /* Check that layered rendering is consistent. */
Paul Berry95140742013-11-19 15:55:51 -08001316 if (att->Layered) {
1317 if (att_tex_target == GL_TEXTURE_CUBE_MAP)
1318 att_layer_count = 6;
Kenneth Graunke5c399ca2014-05-07 14:35:42 -07001319 else if (att_tex_target == GL_TEXTURE_1D_ARRAY)
1320 att_layer_count = att->Renderbuffer->Height;
Paul Berry95140742013-11-19 15:55:51 -08001321 else
1322 att_layer_count = att->Renderbuffer->Depth;
1323 } else {
1324 att_layer_count = 0;
1325 }
Paul Berry28af1dc2013-11-19 19:01:37 -08001326 if (!layer_info_valid) {
Paul Berry532b1fe2014-01-07 06:29:47 -08001327 is_layered = att->Layered;
1328 max_layer_count = att_layer_count;
Paul Berry28af1dc2013-11-19 19:01:37 -08001329 layer_tex_target = att_tex_target;
1330 layer_info_valid = true;
Paul Berry532b1fe2014-01-07 06:29:47 -08001331 } else if (max_layer_count > 0 && layer_tex_target != att_tex_target) {
Paul Berry28af1dc2013-11-19 19:01:37 -08001332 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1333 fbo_incomplete(ctx, "layered framebuffer has mismatched targets", i);
1334 return;
Paul Berry532b1fe2014-01-07 06:29:47 -08001335 } else if (is_layered != att->Layered) {
1336 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
Brian Paulc1377ed2014-03-22 10:31:58 -06001337 fbo_incomplete(ctx,
1338 "framebuffer attachment layer mode is inconsistent",
1339 i);
Jordan Justen5da82882013-04-18 10:20:05 -07001340 return;
Paul Berry532b1fe2014-01-07 06:29:47 -08001341 } else if (att_layer_count > max_layer_count) {
1342 max_layer_count = att_layer_count;
Jordan Justen5da82882013-04-18 10:20:05 -07001343 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001344
1345 /*
1346 * The extension GL_ARB_framebuffer_no_attachments places additional
1347 * requirement on each attachment. Those additional requirements are
1348 * tighter that those of previous versions of GL. In interest of better
1349 * compatibility, we will not enforce these restrictions. For the record
1350 * those additional restrictions are quoted below:
1351 *
1352 * "The width and height of image are greater than zero and less than or
1353 * equal to the values of the implementation-dependent limits
1354 * MAX_FRAMEBUFFER_WIDTH and MAX_FRAMEBUFFER_HEIGHT, respectively."
1355 *
1356 * "If <image> is a three-dimensional texture or a one- or two-dimensional
1357 * array texture and the attachment is layered, the depth or layer count
1358 * of the texture is less than or equal to the implementation-dependent
1359 * limit MAX_FRAMEBUFFER_LAYERS."
1360 *
1361 * "If image has multiple samples, its sample count is less than or equal
1362 * to the value of the implementation-dependent limit
1363 * MAX_FRAMEBUFFER_SAMPLES."
1364 *
1365 * The same requirements are also in place for GL 4.5,
1366 * Section 9.4.1 "Framebuffer Attachment Completeness", pg 310-311
1367 */
Brian Paulf0bbbf62005-02-09 03:50:30 +00001368 }
1369
Marek Olšák459f05c2018-06-11 18:30:34 -04001370 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
1371 /* See if non-matching sample counts are supported. */
1372 if (numColorSamples >= 0 && numDepthSamples >= 0) {
1373 bool found = false;
1374
1375 assert(numColorStorageSamples != -1);
1376
1377 numColorSamples = MAX2(numColorSamples, 1);
1378 numColorStorageSamples = MAX2(numColorStorageSamples, 1);
1379 numDepthSamples = MAX2(numDepthSamples, 1);
1380
1381 if (numColorSamples == 1 && numColorStorageSamples == 1 &&
1382 numDepthSamples == 1) {
1383 found = true;
1384 } else {
1385 for (i = 0; i < ctx->Const.NumSupportedMultisampleModes; i++) {
1386 GLint *counts =
1387 &ctx->Const.SupportedMultisampleModes[i].NumColorSamples;
1388
1389 if (counts[0] == numColorSamples &&
1390 counts[1] == numColorStorageSamples &&
1391 counts[2] == numDepthSamples) {
1392 found = true;
1393 break;
1394 }
1395 }
1396 }
1397
1398 if (!found) {
1399 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1400 fbo_incomplete(ctx, "unsupported sample counts", -1);
1401 return;
1402 }
1403 }
1404 } else {
1405 /* If the extension is unsupported, all sample counts must be equal. */
1406 if (numColorSamples >= 0 &&
1407 (numColorSamples != numColorStorageSamples ||
1408 (numDepthSamples >= 0 && numColorSamples != numDepthSamples))) {
1409 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1410 fbo_incomplete(ctx, "inconsistent sample counts", -1);
1411 return;
1412 }
1413 }
1414
Paul Berry532b1fe2014-01-07 06:29:47 -08001415 fb->MaxNumLayers = max_layer_count;
Jordan Justen5da82882013-04-18 10:20:05 -07001416
Chris Forbesa419a1c2014-03-23 22:41:28 +13001417 if (numImages == 0) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001418 fb->_HasAttachments = false;
1419
1420 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
1421 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1422 fbo_incomplete(ctx, "no attachments", -1);
1423 return;
1424 }
1425
1426 if (fb->DefaultGeometry.Width == 0 || fb->DefaultGeometry.Height == 0) {
1427 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1428 fbo_incomplete(ctx, "no attachments and default width or height is 0", -1);
1429 return;
1430 }
Chris Forbesa419a1c2014-03-23 22:41:28 +13001431 }
1432
Jordan Justen09714c02012-07-19 11:27:16 -07001433 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001434 /* Check that all DrawBuffers are present */
1435 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001436 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1437 const struct gl_renderbuffer_attachment *att
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02001438 = get_attachment(ctx, fb, fb->ColorDrawBuffer[j], NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001439 assert(att);
1440 if (att->Type == GL_NONE) {
1441 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1442 fbo_incomplete(ctx, "missing drawbuffer", j);
1443 return;
1444 }
1445 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001446 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001447
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001448 /* Check that the ReadBuffer is present */
1449 if (fb->ColorReadBuffer != GL_NONE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001450 const struct gl_renderbuffer_attachment *att
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02001451 = get_attachment(ctx, fb, fb->ColorReadBuffer, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02001452 assert(att);
1453 if (att->Type == GL_NONE) {
1454 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001455 fbo_incomplete(ctx, "missing readbuffer", -1);
Martin Peres7bd8b482015-02-12 17:54:43 +02001456 return;
1457 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001458 }
1459 }
1460
Iago Toral Quirogad42e0902014-12-12 15:14:32 +01001461 /* The OpenGL ES3 spec, in chapter 9.4. FRAMEBUFFER COMPLETENESS, says:
1462 *
1463 * "Depth and stencil attachments, if present, are the same image."
1464 *
1465 * This restriction is not present in the OpenGL ES2 spec.
1466 */
1467 if (_mesa_is_gles3(ctx) &&
1468 has_stencil_attachment && has_depth_attachment &&
1469 !_mesa_has_depthstencil_combined(fb)) {
1470 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1471 fbo_incomplete(ctx, "Depth and stencil attachments must be the same image", -1);
1472 return;
1473 }
1474
Brian Paul3528f692009-01-22 15:13:18 -07001475 /* Provisionally set status = COMPLETE ... */
Brian Paule4b23562005-05-04 20:11:35 +00001476 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
Brian Paul3528f692009-01-22 15:13:18 -07001477
Brian Paul777a2ef2009-01-22 15:17:42 -07001478 /* ... but the driver may say the FB is incomplete.
1479 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1480 * if anything.
1481 */
Brian Paul3528f692009-01-22 15:13:18 -07001482 if (ctx->Driver.ValidateFramebuffer) {
1483 ctx->Driver.ValidateFramebuffer(ctx, fb);
Brian Paul1f32c412009-01-19 17:34:19 -07001484 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
Eric Anholt3c21a7d2013-06-06 11:13:02 -07001485 fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001486 return;
Brian Paul1f32c412009-01-19 17:34:19 -07001487 }
Brian Paul3528f692009-01-22 15:13:18 -07001488 }
1489
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001490 /*
1491 * Note that if ARB_framebuffer_object is supported and the attached
1492 * renderbuffers/textures are different sizes, the framebuffer
1493 * width/height will be set to the smallest width/height.
1494 */
1495 if (numImages != 0) {
1496 fb->Width = minWidth;
1497 fb->Height = minHeight;
Brian Paul3528f692009-01-22 15:13:18 -07001498 }
Erik Faye-Lund395b53d2015-12-16 17:09:50 +01001499
1500 /* finally, update the visual info for the framebuffer */
1501 _mesa_update_framebuffer_visual(ctx, fb);
Brian Paule4b23562005-05-04 20:11:35 +00001502}
Brian Paulf0bbbf62005-02-09 03:50:30 +00001503
1504
Brian Paul1864c7d2005-02-08 03:46:37 +00001505GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001506_mesa_IsRenderbuffer(GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001507{
Samuel Pitoiset78392432017-04-06 18:05:36 +02001508 struct gl_renderbuffer *rb;
1509
Brian Paulddc82ee2005-02-05 19:56:45 +00001510 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoiset78392432017-04-06 18:05:36 +02001511
Brian Paulddc82ee2005-02-05 19:56:45 +00001512 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Samuel Pitoiset78392432017-04-06 18:05:36 +02001513
1514 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1515 return rb != NULL && rb != &DummyRenderbuffer;
Brian Paulddc82ee2005-02-05 19:56:45 +00001516}
1517
1518
Martin Peresa34669b2015-02-12 18:52:10 +02001519static struct gl_renderbuffer *
Matt Turner015f2202015-07-30 14:31:04 -07001520allocate_renderbuffer_locked(struct gl_context *ctx, GLuint renderbuffer,
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02001521 bool isGenName,
Matt Turner015f2202015-07-30 14:31:04 -07001522 const char *func)
Martin Peresa34669b2015-02-12 18:52:10 +02001523{
1524 struct gl_renderbuffer *newRb;
1525
1526 /* create new renderbuffer object */
1527 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1528 if (!newRb) {
1529 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1530 return NULL;
1531 }
1532 assert(newRb->AllocStorage);
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02001533 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffer,
1534 newRb, isGenName);
Martin Peresa34669b2015-02-12 18:52:10 +02001535
1536 return newRb;
1537}
1538
1539
Ian Romanick97965e82013-07-18 17:38:16 -07001540static void
Timothy Arcerib54a2312018-09-08 14:20:17 +10001541bind_renderbuffer(GLenum target, GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001542{
Brian42aaa542007-03-25 10:39:36 -06001543 struct gl_renderbuffer *newRb;
Brian Paulddc82ee2005-02-05 19:56:45 +00001544 GET_CURRENT_CONTEXT(ctx);
1545
Brian Paul3deaa012005-02-07 05:08:24 +00001546 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul4de18fb2009-11-02 15:30:51 -07001547 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00001548 return;
1549 }
1550
Brian Paul800e5532009-11-02 15:39:39 -07001551 /* No need to flush here since the render buffer binding has no
1552 * effect on rendering state.
1553 */
Brian Paul474f28e2005-10-08 14:41:17 +00001554
Brian Paul3deaa012005-02-07 05:08:24 +00001555 if (renderbuffer) {
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02001556 bool isGenName = false;
Brian Paulea4fe662006-03-26 05:22:17 +00001557 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001558 if (newRb == &DummyRenderbuffer) {
1559 /* ID was reserved, but no real renderbuffer object made yet */
1560 newRb = NULL;
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02001561 isGenName = true;
Brian Paul1864c7d2005-02-08 03:46:37 +00001562 }
Timothy Arcerib54a2312018-09-08 14:20:17 +10001563 else if (!newRb && ctx->API == API_OPENGL_CORE) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07001564 /* All RB IDs must be Gen'd */
Timothy Arcerib54a2312018-09-08 14:20:17 +10001565 _mesa_error(ctx, GL_INVALID_OPERATION,
1566 "glBindRenderbuffer(non-gen name)");
Brian Paul1bc59bf2009-01-22 15:07:34 -07001567 return;
1568 }
1569
Brian Paul3deaa012005-02-07 05:08:24 +00001570 if (!newRb) {
Matt Turner015f2202015-07-30 14:31:04 -07001571 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
1572 newRb = allocate_renderbuffer_locked(ctx, renderbuffer,
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02001573 isGenName, "glBindRenderbufferEXT");
Matt Turner015f2202015-07-30 14:31:04 -07001574 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
Brian Paul3deaa012005-02-07 05:08:24 +00001575 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001576 }
Brian Paul463642c2005-02-08 02:06:00 +00001577 else {
1578 newRb = NULL;
1579 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001580
Matt Turnerbfcdb842015-02-20 20:18:47 -08001581 assert(newRb != &DummyRenderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001582
Brian42aaa542007-03-25 10:39:36 -06001583 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
Brian Paulddc82ee2005-02-05 19:56:45 +00001584}
1585
Ian Romanick97965e82013-07-18 17:38:16 -07001586void GLAPIENTRY
1587_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1588{
Ian Romanick97965e82013-07-18 17:38:16 -07001589 /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1590 * entry point, but they allow the use of user-generated names.
1591 */
Timothy Arcerib54a2312018-09-08 14:20:17 +10001592 bind_renderbuffer(target, renderbuffer);
Ian Romanick97965e82013-07-18 17:38:16 -07001593}
Brian Paulddc82ee2005-02-05 19:56:45 +00001594
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001595void GLAPIENTRY
1596_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1597{
Timothy Arcerib54a2312018-09-08 14:20:17 +10001598 bind_renderbuffer(target, renderbuffer);
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001599}
1600
Edward O'Callaghanb40375a2016-02-17 19:15:49 +11001601/**
Rhys Perry67f40da2018-06-14 19:56:28 -06001602 * ARB_framebuffer_no_attachment and ARB_sample_locations - Application passes
1603 * requested param's here. NOTE: NumSamples requested need not be _NumSamples
1604 * which is what the hw supports.
Edward O'Callaghanb40375a2016-02-17 19:15:49 +11001605 */
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001606static void
1607framebuffer_parameteri(struct gl_context *ctx, struct gl_framebuffer *fb,
1608 GLenum pname, GLint param, const char *func)
1609{
Rhys Perry67f40da2018-06-14 19:56:28 -06001610 bool cannot_be_winsys_fbo = false;
1611
1612 switch (pname) {
1613 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1614 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1615 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1616 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1617 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1618 if (!ctx->Extensions.ARB_framebuffer_no_attachments)
1619 goto invalid_pname_enum;
1620 cannot_be_winsys_fbo = true;
1621 break;
1622 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1623 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1624 if (!ctx->Extensions.ARB_sample_locations)
1625 goto invalid_pname_enum;
1626 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001627 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1628 if (!ctx->Extensions.MESA_framebuffer_flip_y)
1629 goto invalid_pname_enum;
1630 cannot_be_winsys_fbo = true;
Fritz Koenig60d0c0d2018-09-14 11:40:49 -07001631 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001632 default:
1633 goto invalid_pname_enum;
1634 }
1635
1636 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1637 _mesa_error(ctx, GL_INVALID_OPERATION,
1638 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1639 return;
1640 }
1641
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001642 switch (pname) {
1643 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1644 if (param < 0 || param > ctx->Const.MaxFramebufferWidth)
1645 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1646 else
1647 fb->DefaultGeometry.Width = param;
1648 break;
1649 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1650 if (param < 0 || param > ctx->Const.MaxFramebufferHeight)
1651 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1652 else
1653 fb->DefaultGeometry.Height = param;
1654 break;
1655 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001656 /*
1657 * According to the OpenGL ES 3.1 specification section 9.2.1, the
1658 * GL_FRAMEBUFFER_DEFAULT_LAYERS parameter name is not supported.
1659 */
Ilia Mirkin82d756f2016-05-21 20:26:47 -04001660 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001661 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1662 break;
1663 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001664 if (param < 0 || param > ctx->Const.MaxFramebufferLayers)
Marta Lofstedtf8a93882015-08-24 13:01:53 +02001665 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001666 else
1667 fb->DefaultGeometry.Layers = param;
1668 break;
1669 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1670 if (param < 0 || param > ctx->Const.MaxFramebufferSamples)
1671 _mesa_error(ctx, GL_INVALID_VALUE, "%s", func);
1672 else
1673 fb->DefaultGeometry.NumSamples = param;
1674 break;
1675 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1676 fb->DefaultGeometry.FixedSampleLocations = param;
1677 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001678 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1679 fb->ProgrammableSampleLocations = !!param;
1680 break;
1681 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1682 fb->SampleLocationPixelGrid = !!param;
1683 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001684 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1685 fb->FlipY = param;
1686 break;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001687 }
Ilia Mirkin095da3b2016-01-23 09:27:22 -05001688
Rhys Perry67f40da2018-06-14 19:56:28 -06001689 switch (pname) {
1690 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1691 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1692 if (fb == ctx->DrawBuffer)
1693 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
1694 break;
1695 default:
1696 invalidate_framebuffer(fb);
1697 ctx->NewState |= _NEW_BUFFERS;
1698 break;
1699 }
1700
1701 return;
1702
1703invalid_pname_enum:
1704 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001705}
1706
Fritz Koenig66937ab2019-07-30 14:53:30 -07001707static bool
1708validate_framebuffer_parameter_extensions(GLenum pname, const char *func)
1709{
1710 GET_CURRENT_CONTEXT(ctx);
1711
1712 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
1713 !ctx->Extensions.ARB_sample_locations &&
1714 !ctx->Extensions.MESA_framebuffer_flip_y) {
1715 _mesa_error(ctx, GL_INVALID_OPERATION,
1716 "%s not supported "
1717 "(none of ARB_framebuffer_no_attachments,"
1718 " ARB_sample_locations, or"
1719 " MESA_framebuffer_flip_y extensions are available)",
1720 func);
1721 return false;
1722 }
1723
1724 /*
1725 * If only the MESA_framebuffer_flip_y extension is enabled
1726 * pname can only be GL_FRAMEBUFFER_FLIP_Y_MESA
1727 */
1728 if (ctx->Extensions.MESA_framebuffer_flip_y &&
1729 pname != GL_FRAMEBUFFER_FLIP_Y_MESA &&
1730 !(ctx->Extensions.ARB_framebuffer_no_attachments ||
1731 ctx->Extensions.ARB_sample_locations)) {
1732 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1733 return false;
1734 }
1735
1736 return true;
1737}
1738
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001739void GLAPIENTRY
1740_mesa_FramebufferParameteri(GLenum target, GLenum pname, GLint param)
1741{
1742 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001743 struct gl_framebuffer *fb;
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001744
Fritz Koenig66937ab2019-07-30 14:53:30 -07001745 if (!validate_framebuffer_parameter_extensions(pname,
1746 "glFramebufferParameteri")) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001747 return;
1748 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001749
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001750 fb = get_framebuffer_target(ctx, target);
1751 if (!fb) {
1752 _mesa_error(ctx, GL_INVALID_ENUM,
1753 "glFramebufferParameteri(target=0x%x)", target);
1754 return;
1755 }
1756
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001757 framebuffer_parameteri(ctx, fb, pname, param, "glFramebufferParameteri");
1758}
1759
Fritz Koenig66937ab2019-07-30 14:53:30 -07001760void GLAPIENTRY
1761_mesa_FramebufferParameteriMESA(GLenum target, GLenum pname, GLint param)
1762{
1763 _mesa_FramebufferParameteri(target, pname, param);
1764}
1765
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001766static bool
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001767validate_get_framebuffer_parameteriv_pname(struct gl_context *ctx,
1768 struct gl_framebuffer *fb,
1769 GLuint pname, const char *func)
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001770{
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001771 bool cannot_be_winsys_fbo = true;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001772
1773 switch (pname) {
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001774 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1775 /*
1776 * According to the OpenGL ES 3.1 specification section 9.2.3, the
1777 * GL_FRAMEBUFFER_LAYERS parameter name is not supported.
1778 */
1779 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader) {
1780 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1781 return false;
1782 }
1783 break;
1784 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1785 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1786 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1787 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1788 break;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001789 case GL_DOUBLEBUFFER:
1790 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1791 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1792 case GL_SAMPLES:
1793 case GL_SAMPLE_BUFFERS:
1794 case GL_STEREO:
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001795 /* From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries:
1796 *
1797 * "An INVALID_OPERATION error is generated by GetFramebufferParameteriv
1798 * if the default framebuffer is bound to target and pname is not one
1799 * of the accepted values from table 23.73, other than
1800 * SAMPLE_POSITION."
1801 *
1802 * For OpenGL ES, using default framebuffer raises INVALID_OPERATION
1803 * for any pname.
1804 */
1805 cannot_be_winsys_fbo = !_mesa_is_desktop_gl(ctx);
1806 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001807 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1808 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1809 if (!ctx->Extensions.ARB_sample_locations)
1810 goto invalid_pname_enum;
1811 cannot_be_winsys_fbo = false;
1812 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001813 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1814 if (!ctx->Extensions.MESA_framebuffer_flip_y) {
1815 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1816 return false;
1817 }
1818 break;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001819 default:
Rhys Perry67f40da2018-06-14 19:56:28 -06001820 goto invalid_pname_enum;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001821 }
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001822
1823 if (cannot_be_winsys_fbo && _mesa_is_winsys_fbo(fb)) {
1824 _mesa_error(ctx, GL_INVALID_OPERATION,
1825 "%s(invalid pname=0x%x for default framebuffer)", func, pname);
1826 return false;
1827 }
1828
1829 return true;
Rhys Perry67f40da2018-06-14 19:56:28 -06001830
1831invalid_pname_enum:
1832 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
1833 return false;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001834}
1835
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001836static void
1837get_framebuffer_parameteriv(struct gl_context *ctx, struct gl_framebuffer *fb,
1838 GLenum pname, GLint *params, const char *func)
1839{
Rhys Perry5ac16ed2018-05-04 23:27:51 +01001840 if (!validate_get_framebuffer_parameteriv_pname(ctx, fb, pname, func))
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001841 return;
Alejandro Piñeirodfb1b542017-01-13 15:53:13 -02001842
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001843 switch (pname) {
1844 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1845 *params = fb->DefaultGeometry.Width;
1846 break;
1847 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1848 *params = fb->DefaultGeometry.Height;
1849 break;
1850 case GL_FRAMEBUFFER_DEFAULT_LAYERS:
1851 *params = fb->DefaultGeometry.Layers;
1852 break;
1853 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1854 *params = fb->DefaultGeometry.NumSamples;
1855 break;
1856 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1857 *params = fb->DefaultGeometry.FixedSampleLocations;
1858 break;
Alejandro Piñeiro0fb0c572017-01-13 16:23:05 -02001859 case GL_DOUBLEBUFFER:
1860 *params = fb->Visual.doubleBufferMode;
1861 break;
1862 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1863 *params = _mesa_get_color_read_format(ctx, fb, func);
1864 break;
1865 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1866 *params = _mesa_get_color_read_type(ctx, fb, func);
1867 break;
1868 case GL_SAMPLES:
1869 *params = _mesa_geometric_samples(fb);
1870 break;
1871 case GL_SAMPLE_BUFFERS:
1872 *params = _mesa_geometric_samples(fb) > 0;
1873 break;
1874 case GL_STEREO:
1875 *params = fb->Visual.stereoMode;
1876 break;
Rhys Perry67f40da2018-06-14 19:56:28 -06001877 case GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB:
1878 *params = fb->ProgrammableSampleLocations;
1879 break;
1880 case GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB:
1881 *params = fb->SampleLocationPixelGrid;
1882 break;
Fritz Koenig318c2652018-07-23 10:10:54 -07001883 case GL_FRAMEBUFFER_FLIP_Y_MESA:
1884 *params = fb->FlipY;
1885 break;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001886 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001887}
1888
1889void GLAPIENTRY
1890_mesa_GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
1891{
1892 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001893 struct gl_framebuffer *fb;
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001894
Fritz Koenig66937ab2019-07-30 14:53:30 -07001895 if (!validate_framebuffer_parameter_extensions(pname,
1896 "glGetFramebufferParameteriv")) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001897 return;
1898 }
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001899
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001900 fb = get_framebuffer_target(ctx, target);
1901 if (!fb) {
1902 _mesa_error(ctx, GL_INVALID_ENUM,
1903 "glGetFramebufferParameteriv(target=0x%x)", target);
1904 return;
1905 }
1906
Kevin Rogovin6aa12992015-06-17 13:29:52 +03001907 get_framebuffer_parameteriv(ctx, fb, pname, params,
1908 "glGetFramebufferParameteriv");
Kevin Rogovinc9d26f22015-06-17 13:29:51 +03001909}
1910
Fritz Koenig66937ab2019-07-30 14:53:30 -07001911void GLAPIENTRY
1912_mesa_GetFramebufferParameterivMESA(GLenum target, GLenum pname, GLint *params)
1913{
1914 _mesa_GetFramebufferParameteriv(target, pname, params);
1915}
Tomasz Lis9f07ca12013-07-16 20:57:26 +02001916
Brian Pauld0f13fa2009-01-21 11:17:45 -07001917/**
Ian Romanickef83bd22013-08-08 15:41:36 -07001918 * Remove the specified renderbuffer or texture from any attachment point in
1919 * the framebuffer.
Ian Romanick438cc6b2013-08-08 15:26:36 -07001920 *
1921 * \returns
1922 * \c true if the renderbuffer was detached from an attachment point. \c
1923 * false otherwise.
Brian Pauld0f13fa2009-01-21 11:17:45 -07001924 */
Ian Romanick438cc6b2013-08-08 15:26:36 -07001925bool
1926_mesa_detach_renderbuffer(struct gl_context *ctx,
1927 struct gl_framebuffer *fb,
1928 const void *att)
Brian Pauld0f13fa2009-01-21 11:17:45 -07001929{
Ian Romanick438cc6b2013-08-08 15:26:36 -07001930 unsigned i;
1931 bool progress = false;
1932
Brian Pauld0f13fa2009-01-21 11:17:45 -07001933 for (i = 0; i < BUFFER_COUNT; i++) {
Ian Romanickef83bd22013-08-08 15:41:36 -07001934 if (fb->Attachment[i].Texture == att
1935 || fb->Attachment[i].Renderbuffer == att) {
Brian Paul94512812014-02-01 08:58:43 -07001936 remove_attachment(ctx, &fb->Attachment[i]);
Ian Romanick438cc6b2013-08-08 15:26:36 -07001937 progress = true;
Brian Pauld0f13fa2009-01-21 11:17:45 -07001938 }
1939 }
Ian Romanick438cc6b2013-08-08 15:26:36 -07001940
1941 /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1942 * Completeness," of the OpenGL 3.1 spec says:
1943 *
1944 * "Performing any of the following actions may change whether the
1945 * framebuffer is considered complete or incomplete:
1946 *
1947 * ...
1948 *
1949 * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1950 * containing an image that is attached to a framebuffer object
1951 * that is bound to the framebuffer."
1952 */
1953 if (progress)
1954 invalidate_framebuffer(fb);
1955
1956 return progress;
Brian Pauld0f13fa2009-01-21 11:17:45 -07001957}
1958
1959
Brian Paul1864c7d2005-02-08 03:46:37 +00001960void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001961_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001962{
1963 GLint i;
1964 GET_CURRENT_CONTEXT(ctx);
1965
Eduardo Lima Mitev2012f622014-12-11 23:34:18 +01001966 if (n < 0) {
1967 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteRenderbuffers(n < 0)");
1968 return;
1969 }
1970
Brian Paul474f28e2005-10-08 14:41:17 +00001971 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00001972
1973 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001974 if (renderbuffers[i] > 0) {
Martin Peres7bd8b482015-02-12 17:54:43 +02001975 struct gl_renderbuffer *rb;
1976 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
1977 if (rb) {
Brian Paul91802fd2005-10-04 16:01:02 +00001978 /* check if deleting currently bound renderbuffer object */
1979 if (rb == ctx->CurrentRenderbuffer) {
1980 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08001981 assert(rb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001982 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
Brian Paul91802fd2005-10-04 16:01:02 +00001983 }
1984
Ian Romanickef83bd22013-08-08 15:41:36 -07001985 /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
Brian Paulc1377ed2014-03-22 10:31:58 -06001986 * subsection "Attaching Renderbuffer Images to a Framebuffer,"
1987 * of the OpenGL 3.1 spec says:
Ian Romanickef83bd22013-08-08 15:41:36 -07001988 *
1989 * "If a renderbuffer object is deleted while its image is
1990 * attached to one or more attachment points in the currently
1991 * bound framebuffer, then it is as if FramebufferRenderbuffer
1992 * had been called, with a renderbuffer of 0, for each
1993 * attachment point to which this image was attached in the
1994 * currently bound framebuffer. In other words, this
1995 * renderbuffer image is first detached from all attachment
1996 * points in the currently bound framebuffer. Note that the
1997 * renderbuffer image is specifically not detached from any
1998 * non-bound framebuffers. Detaching the image from any
1999 * non-bound framebuffers is the responsibility of the
2000 * application.
2001 */
Brian Paul36ede892012-01-12 09:17:23 -07002002 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
Ian Romanick438cc6b2013-08-08 15:26:36 -07002003 _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07002004 }
Brian Paul36ede892012-01-12 09:17:23 -07002005 if (_mesa_is_user_fbo(ctx->ReadBuffer)
Brian Paulfc8c4a32011-06-16 07:31:58 -06002006 && ctx->ReadBuffer != ctx->DrawBuffer) {
Ian Romanick438cc6b2013-08-08 15:26:36 -07002007 _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07002008 }
2009
Martin Peres7bd8b482015-02-12 17:54:43 +02002010 /* Remove from hash table immediately, to free the ID.
Brian42aaa542007-03-25 10:39:36 -06002011 * But the object will not be freed until it's no longer
2012 * referenced anywhere else.
2013 */
Martin Peres7bd8b482015-02-12 17:54:43 +02002014 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00002015
Brian Paul1864c7d2005-02-08 03:46:37 +00002016 if (rb != &DummyRenderbuffer) {
Brian42aaa542007-03-25 10:39:36 -06002017 /* no longer referenced by hash table */
2018 _mesa_reference_renderbuffer(&rb, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02002019 }
2020 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002021 }
2022 }
2023}
2024
Martin Peresa34669b2015-02-12 18:52:10 +02002025static void
2026create_render_buffers(struct gl_context *ctx, GLsizei n, GLuint *renderbuffers,
2027 bool dsa)
Brian Paulddc82ee2005-02-05 19:56:45 +00002028{
Martin Peresa34669b2015-02-12 18:52:10 +02002029 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
Brian Paulddc82ee2005-02-05 19:56:45 +00002030 GLint i;
2031
Brian Paulddc82ee2005-02-05 19:56:45 +00002032 if (!renderbuffers)
2033 return;
2034
Matt Turner015f2202015-07-30 14:31:04 -07002035 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
2036
Pierre-Eric Pelloux-Prayera56849d2020-08-17 15:12:03 +02002037 _mesa_HashFindFreeKeys(ctx->Shared->RenderBuffers, renderbuffers, n);
Brian Paulddc82ee2005-02-05 19:56:45 +00002038
2039 for (i = 0; i < n; i++) {
Martin Peresa34669b2015-02-12 18:52:10 +02002040 if (dsa) {
Pierre-Eric Pelloux-Prayera56849d2020-08-17 15:12:03 +02002041 allocate_renderbuffer_locked(ctx, renderbuffers[i], true, func);
Martin Peresa34669b2015-02-12 18:52:10 +02002042 } else {
Martin Peresfa383212015-03-25 16:28:03 +02002043 /* insert a dummy renderbuffer into the hash table */
Pierre-Eric Pelloux-Prayera56849d2020-08-17 15:12:03 +02002044 _mesa_HashInsertLocked(ctx->Shared->RenderBuffers, renderbuffers[i],
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02002045 &DummyRenderbuffer, true);
Martin Peresa34669b2015-02-12 18:52:10 +02002046 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002047 }
Matt Turner015f2202015-07-30 14:31:04 -07002048
2049 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
Brian Paulddc82ee2005-02-05 19:56:45 +00002050}
2051
2052
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02002053static void
2054create_render_buffers_err(struct gl_context *ctx, GLsizei n,
2055 GLuint *renderbuffers, bool dsa)
2056{
2057 const char *func = dsa ? "glCreateRenderbuffers" : "glGenRenderbuffers";
2058
2059 if (n < 0) {
2060 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n<0)", func);
2061 return;
2062 }
2063
2064 create_render_buffers(ctx, n, renderbuffers, dsa);
2065}
2066
2067
Martin Peresa34669b2015-02-12 18:52:10 +02002068void GLAPIENTRY
Samuel Pitoisetb87a2cb2017-06-26 18:27:49 +02002069_mesa_GenRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
2070{
2071 GET_CURRENT_CONTEXT(ctx);
2072 create_render_buffers(ctx, n, renderbuffers, false);
2073}
2074
2075
2076void GLAPIENTRY
Martin Peresa34669b2015-02-12 18:52:10 +02002077_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
2078{
2079 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02002080 create_render_buffers_err(ctx, n, renderbuffers, false);
Martin Peresa34669b2015-02-12 18:52:10 +02002081}
2082
2083
2084void GLAPIENTRY
Samuel Pitoisetb87a2cb2017-06-26 18:27:49 +02002085_mesa_CreateRenderbuffers_no_error(GLsizei n, GLuint *renderbuffers)
2086{
2087 GET_CURRENT_CONTEXT(ctx);
2088 create_render_buffers(ctx, n, renderbuffers, true);
2089}
2090
2091
2092void GLAPIENTRY
Martin Peresa34669b2015-02-12 18:52:10 +02002093_mesa_CreateRenderbuffers(GLsizei n, GLuint *renderbuffers)
2094{
2095 GET_CURRENT_CONTEXT(ctx);
Samuel Pitoisetbeb74c92017-06-26 18:25:10 +02002096 create_render_buffers_err(ctx, n, renderbuffers, true);
Martin Peresa34669b2015-02-12 18:52:10 +02002097}
2098
2099
Brian Pauld9468c92005-02-10 16:08:07 +00002100/**
Brian Paulf41bbc72011-01-24 19:38:52 -07002101 * Given an internal format token for a render buffer, return the
Brian Paul976ea9d2011-01-24 19:38:52 -07002102 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
2103 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
2104 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
Brian Paulf41bbc72011-01-24 19:38:52 -07002105 *
Brian Paul976ea9d2011-01-24 19:38:52 -07002106 * This is similar to _mesa_base_tex_format() but the set of valid
2107 * internal formats is different.
Brian Paulf41bbc72011-01-24 19:38:52 -07002108 *
Brian Paul976ea9d2011-01-24 19:38:52 -07002109 * Note that even if a format is determined to be legal here, validation
Brian Paulb3cfcdf2011-01-28 20:25:26 -07002110 * of the FBO may fail if the format is not supported by the driver/GPU.
Brian Paul976ea9d2011-01-24 19:38:52 -07002111 *
2112 * \param internalFormat as passed to glRenderbufferStorage()
2113 * \return the base internal format, or 0 if internalFormat is illegal
Brian Pauld9468c92005-02-10 16:08:07 +00002114 */
Brian Paul59e0faa2006-03-15 17:48:00 +00002115GLenum
Brian Paulca78b6b2017-12-05 12:05:18 -07002116_mesa_base_fbo_format(const struct gl_context *ctx, GLenum internalFormat)
Brian Paul463642c2005-02-08 02:06:00 +00002117{
Brian Paul976ea9d2011-01-24 19:38:52 -07002118 /*
2119 * Notes: some formats such as alpha, luminance, etc. were added
2120 * with GL_ARB_framebuffer_object.
2121 */
Brian Paul463642c2005-02-08 02:06:00 +00002122 switch (internalFormat) {
Brian Paulf41bbc72011-01-24 19:38:52 -07002123 case GL_ALPHA:
2124 case GL_ALPHA4:
2125 case GL_ALPHA8:
2126 case GL_ALPHA12:
2127 case GL_ALPHA16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002128 return (ctx->API == API_OPENGL_COMPAT &&
2129 ctx->Extensions.ARB_framebuffer_object) ? GL_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002130 case GL_LUMINANCE:
2131 case GL_LUMINANCE4:
2132 case GL_LUMINANCE8:
2133 case GL_LUMINANCE12:
2134 case GL_LUMINANCE16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002135 return (ctx->API == API_OPENGL_COMPAT &&
2136 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002137 case GL_LUMINANCE_ALPHA:
2138 case GL_LUMINANCE4_ALPHA4:
2139 case GL_LUMINANCE6_ALPHA2:
2140 case GL_LUMINANCE8_ALPHA8:
2141 case GL_LUMINANCE12_ALPHA4:
2142 case GL_LUMINANCE12_ALPHA12:
2143 case GL_LUMINANCE16_ALPHA16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002144 return (ctx->API == API_OPENGL_COMPAT &&
2145 ctx->Extensions.ARB_framebuffer_object) ? GL_LUMINANCE_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07002146 case GL_INTENSITY:
2147 case GL_INTENSITY4:
2148 case GL_INTENSITY8:
2149 case GL_INTENSITY12:
2150 case GL_INTENSITY16:
Brian Paulc1377ed2014-03-22 10:31:58 -06002151 return (ctx->API == API_OPENGL_COMPAT &&
2152 ctx->Extensions.ARB_framebuffer_object) ? GL_INTENSITY : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002153 case GL_RGB8:
2154 return GL_RGB;
Brian Paulf41bbc72011-01-24 19:38:52 -07002155 case GL_RGB:
2156 case GL_R3_G3_B2:
2157 case GL_RGB4:
2158 case GL_RGB5:
Brian Paulf41bbc72011-01-24 19:38:52 -07002159 case GL_RGB10:
2160 case GL_RGB12:
2161 case GL_RGB16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002162 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002163 case GL_SRGB8_EXT:
Matt Turnercbef5372012-11-20 13:45:03 -08002164 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002165 case GL_RGBA4:
2166 case GL_RGB5_A1:
2167 case GL_RGBA8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002168 return GL_RGBA;
2169 case GL_RGBA:
2170 case GL_RGBA2:
Brian Paulf41bbc72011-01-24 19:38:52 -07002171 case GL_RGBA12:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002172 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
Tapani Pällice80abb2018-07-24 08:58:20 +03002173 case GL_RGBA16:
2174 return _mesa_is_desktop_gl(ctx) || _mesa_has_EXT_texture_norm16(ctx)
2175 ? GL_RGBA : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002176 case GL_RGB10_A2:
Brian Paulf41bbc72011-01-24 19:38:52 -07002177 case GL_SRGB8_ALPHA8_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002178 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00002179 case GL_STENCIL_INDEX:
2180 case GL_STENCIL_INDEX1_EXT:
2181 case GL_STENCIL_INDEX4_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002182 case GL_STENCIL_INDEX16_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002183 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
2184 * OpenGL ES, but Mesa does not currently support them.
2185 */
2186 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
2187 case GL_STENCIL_INDEX8_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002188 return GL_STENCIL_INDEX;
2189 case GL_DEPTH_COMPONENT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002190 case GL_DEPTH_COMPONENT32:
2191 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
Brian Paul2c6f9112005-02-24 05:47:06 +00002192 case GL_DEPTH_COMPONENT16:
2193 case GL_DEPTH_COMPONENT24:
Brian Paulf0bbbf62005-02-09 03:50:30 +00002194 return GL_DEPTH_COMPONENT;
Ian Romanick49493222013-11-13 14:15:11 -08002195 case GL_DEPTH_STENCIL:
2196 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_STENCIL : 0;
2197 case GL_DEPTH24_STENCIL8:
2198 return GL_DEPTH_STENCIL;
Marek Olšák11652802011-06-01 15:48:51 +02002199 case GL_DEPTH_COMPONENT32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002200 return ctx->Version >= 30
Brian Paulc1377ed2014-03-22 10:31:58 -06002201 || (ctx->API == API_OPENGL_COMPAT &&
2202 ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002203 ? GL_DEPTH_COMPONENT : 0;
Marek Olšák11652802011-06-01 15:48:51 +02002204 case GL_DEPTH32F_STENCIL8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002205 return ctx->Version >= 30
Brian Paulc1377ed2014-03-22 10:31:58 -06002206 || (ctx->API == API_OPENGL_COMPAT &&
2207 ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002208 ? GL_DEPTH_STENCIL : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002209 case GL_RED:
Tapani Pällice80abb2018-07-24 08:58:20 +03002210 return _mesa_has_ARB_texture_rg(ctx) ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002211 case GL_R16:
Tapani Pällice80abb2018-07-24 08:58:20 +03002212 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002213 ? GL_RED : 0;
2214 case GL_R8:
2215 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2216 ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002217 case GL_RG:
Tapani Pällice80abb2018-07-24 08:58:20 +03002218 return _mesa_has_ARB_texture_rg(ctx) ? GL_RG : 0;
Brian Pauld3015652011-01-24 19:38:52 -07002219 case GL_RG16:
Tapani Pällice80abb2018-07-24 08:58:20 +03002220 return _mesa_has_ARB_texture_rg(ctx) || _mesa_has_EXT_texture_norm16(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002221 ? GL_RG : 0;
2222 case GL_RG8:
2223 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
2224 ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002225 /* signed normalized texture formats */
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002226 case GL_R8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002227 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002228 ? GL_RED : 0;
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002229 case GL_RED_SNORM:
2230 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RED : 0;
2231 case GL_R16_SNORM:
2232 return _mesa_has_EXT_texture_snorm(ctx) ||
2233 (_mesa_has_EXT_render_snorm(ctx) &&
2234 _mesa_has_EXT_texture_norm16(ctx))
2235 ? GL_RED : 0;
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002236 case GL_RG8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002237 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2238 ? GL_RG : 0;
2239 case GL_RG_SNORM:
Danylo Piliaiev2b98a022018-09-06 17:01:07 +03002240 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002241 case GL_RG16_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002242 return _mesa_has_EXT_texture_snorm(ctx) ||
2243 (_mesa_has_EXT_render_snorm(ctx) &&
2244 _mesa_has_EXT_texture_norm16(ctx))
Ian Romanickf0c99d02012-07-27 08:31:12 -07002245 ? GL_RG : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07002246 case GL_RGB_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002247 case GL_RGB8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01002248 case GL_RGB16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002249 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2250 ? GL_RGB : 0;
Ian Romanick2aae3ab2012-12-04 10:36:10 -08002251 case GL_RGBA8_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002252 return _mesa_has_EXT_texture_snorm(ctx) || _mesa_has_EXT_render_snorm(ctx)
2253 ? GL_RGBA : 0;
2254 case GL_RGBA_SNORM:
2255 return _mesa_has_EXT_texture_snorm(ctx) ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002256 case GL_RGBA16_SNORM:
Tapani Pälli0d356cf2018-05-24 14:05:27 +03002257 return _mesa_has_EXT_texture_snorm(ctx) ||
2258 (_mesa_has_EXT_render_snorm(ctx) &&
2259 _mesa_has_EXT_texture_norm16(ctx))
Ian Romanickf0c99d02012-07-27 08:31:12 -07002260 ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01002261 case GL_ALPHA_SNORM:
2262 case GL_ALPHA8_SNORM:
2263 case GL_ALPHA16_SNORM:
Paul Berrydbd61352012-11-27 12:26:51 -08002264 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002265 ctx->Extensions.EXT_texture_snorm &&
Marek Olšák0be36992011-03-18 13:44:51 +01002266 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
Brian Paul513a3242014-01-08 09:05:29 -07002267 case GL_LUMINANCE_SNORM:
2268 case GL_LUMINANCE8_SNORM:
2269 case GL_LUMINANCE16_SNORM:
2270 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2271 ? GL_LUMINANCE : 0;
2272 case GL_LUMINANCE_ALPHA_SNORM:
2273 case GL_LUMINANCE8_ALPHA8_SNORM:
2274 case GL_LUMINANCE16_ALPHA16_SNORM:
2275 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2276 ? GL_LUMINANCE_ALPHA : 0;
2277 case GL_INTENSITY_SNORM:
2278 case GL_INTENSITY8_SNORM:
2279 case GL_INTENSITY16_SNORM:
2280 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
2281 ? GL_INTENSITY : 0;
2282
Marek Olšák15f99d12011-02-16 00:35:44 +01002283 case GL_R16F:
2284 case GL_R32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002285 return ((_mesa_is_desktop_gl(ctx) &&
2286 ctx->Extensions.ARB_texture_rg &&
2287 ctx->Extensions.ARB_texture_float) ||
2288 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2289 ? GL_RED : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002290 case GL_RG16F:
2291 case GL_RG32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002292 return ((_mesa_is_desktop_gl(ctx) &&
2293 ctx->Extensions.ARB_texture_rg &&
2294 ctx->Extensions.ARB_texture_float) ||
2295 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
2296 ? GL_RG : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002297 case GL_RGB16F:
Tapani Pälli8447b0f2020-09-01 14:20:27 +03002298 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float) ||
2299 (_mesa_is_gles(ctx) && _mesa_has_EXT_color_buffer_half_float(ctx))
2300 ? GL_RGB : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002301 case GL_RGB32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002302 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07002303 ? GL_RGB : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002304 case GL_RGBA16F:
2305 case GL_RGBA32F:
Jordan Justen119002a2013-01-10 17:29:27 -08002306 return ((_mesa_is_desktop_gl(ctx) &&
2307 ctx->Extensions.ARB_texture_float) ||
2308 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Ian Romanickf0c99d02012-07-27 08:31:12 -07002309 ? GL_RGBA : 0;
Juan A. Suarez Romeroe1623b32018-01-15 10:58:50 +00002310 case GL_RGB9_E5:
2311 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_shared_exponent)
2312 ? GL_RGB: 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01002313 case GL_ALPHA16F_ARB:
2314 case GL_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002315 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002316 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002317 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2318 case GL_LUMINANCE16F_ARB:
2319 case GL_LUMINANCE32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002320 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002321 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002322 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2323 case GL_LUMINANCE_ALPHA16F_ARB:
2324 case GL_LUMINANCE_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002325 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002326 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002327 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
2328 case GL_INTENSITY16F_ARB:
2329 case GL_INTENSITY32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08002330 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002331 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01002332 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
Marek Olšák631d23d2011-04-26 02:27:25 +02002333 case GL_R11F_G11F_B10F:
Jordan Justen119002a2013-01-10 17:29:27 -08002334 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
2335 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Matt Turnercbef5372012-11-20 13:45:03 -08002336 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002337
2338 case GL_RGBA8UI_EXT:
2339 case GL_RGBA16UI_EXT:
2340 case GL_RGBA32UI_EXT:
2341 case GL_RGBA8I_EXT:
2342 case GL_RGBA16I_EXT:
2343 case GL_RGBA32I_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002344 return ctx->Version >= 30
2345 || (_mesa_is_desktop_gl(ctx) &&
2346 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002347
2348 case GL_RGB8UI_EXT:
2349 case GL_RGB16UI_EXT:
2350 case GL_RGB32UI_EXT:
2351 case GL_RGB8I_EXT:
2352 case GL_RGB16I_EXT:
2353 case GL_RGB32I_EXT:
Ian Romanicka86d6292012-12-03 11:55:12 -08002354 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
2355 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002356 case GL_R8UI:
2357 case GL_R8I:
2358 case GL_R16UI:
2359 case GL_R16I:
2360 case GL_R32UI:
2361 case GL_R32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002362 return ctx->Version >= 30
2363 || (_mesa_is_desktop_gl(ctx) &&
2364 ctx->Extensions.ARB_texture_rg &&
2365 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01002366
2367 case GL_RG8UI:
2368 case GL_RG8I:
2369 case GL_RG16UI:
2370 case GL_RG16I:
2371 case GL_RG32UI:
2372 case GL_RG32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002373 return ctx->Version >= 30
2374 || (_mesa_is_desktop_gl(ctx) &&
2375 ctx->Extensions.ARB_texture_rg &&
2376 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
Brian Paul45bd5c42011-12-16 08:44:43 -07002377
Dave Airlie9c697a92011-10-04 20:59:40 +01002378 case GL_INTENSITY8I_EXT:
2379 case GL_INTENSITY8UI_EXT:
2380 case GL_INTENSITY16I_EXT:
2381 case GL_INTENSITY16UI_EXT:
2382 case GL_INTENSITY32I_EXT:
2383 case GL_INTENSITY32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002384 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002385 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002386 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
2387
2388 case GL_LUMINANCE8I_EXT:
2389 case GL_LUMINANCE8UI_EXT:
2390 case GL_LUMINANCE16I_EXT:
2391 case GL_LUMINANCE16UI_EXT:
2392 case GL_LUMINANCE32I_EXT:
2393 case GL_LUMINANCE32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002394 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002395 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002396 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
2397
2398 case GL_LUMINANCE_ALPHA8I_EXT:
2399 case GL_LUMINANCE_ALPHA8UI_EXT:
2400 case GL_LUMINANCE_ALPHA16I_EXT:
2401 case GL_LUMINANCE_ALPHA16UI_EXT:
2402 case GL_LUMINANCE_ALPHA32I_EXT:
2403 case GL_LUMINANCE_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002404 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002405 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01002406 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
Dave Airlief449be62011-11-27 16:21:02 +00002407
Marek Olšák636802f2012-01-22 20:21:36 +01002408 case GL_ALPHA8I_EXT:
2409 case GL_ALPHA8UI_EXT:
2410 case GL_ALPHA16I_EXT:
2411 case GL_ALPHA16UI_EXT:
2412 case GL_ALPHA32I_EXT:
2413 case GL_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08002414 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07002415 ctx->Extensions.EXT_texture_integer &&
Marek Olšák636802f2012-01-22 20:21:36 +01002416 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
2417
Dave Airlief449be62011-11-27 16:21:02 +00002418 case GL_RGB10_A2UI:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002419 return (_mesa_is_desktop_gl(ctx) &&
2420 ctx->Extensions.ARB_texture_rgb10_a2ui)
2421 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Marek Olšák1a06e842012-07-12 14:07:41 +02002422
2423 case GL_RGB565:
Ian Romanickf0c99d02012-07-27 08:31:12 -07002424 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
2425 ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002426 default:
Eric Anholt65c41d52011-01-13 10:05:50 -08002427 return 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07002428 }
Brian Paul463642c2005-02-08 02:06:00 +00002429}
2430
2431
Marek Olšákdf818d52011-03-06 05:26:12 +01002432/**
2433 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
2434 */
2435static void
Ian Romanickcc6dcc62020-10-12 16:52:09 -07002436invalidate_rb(void *data, void *userData)
Marek Olšákdf818d52011-03-06 05:26:12 +01002437{
2438 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2439 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
2440
2441 /* If this is a user-created FBO */
Brian Paul36ede892012-01-12 09:17:23 -07002442 if (_mesa_is_user_fbo(fb)) {
Marek Olšákdf818d52011-03-06 05:26:12 +01002443 GLuint i;
2444 for (i = 0; i < BUFFER_COUNT; i++) {
2445 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2446 if (att->Type == GL_RENDERBUFFER &&
2447 att->Renderbuffer == rb) {
2448 /* Mark fb status as indeterminate to force re-validation */
2449 fb->_Status = 0;
Marek Olšáka674ef72011-03-07 23:33:36 +01002450 return;
Marek Olšákdf818d52011-03-06 05:26:12 +01002451 }
2452 }
2453 }
2454}
2455
2456
Brian Paul4f3514e2009-01-22 15:19:56 -07002457/** sentinal value, see below */
2458#define NO_SAMPLES 1000
2459
Ian Romanickeb5bc622015-11-12 09:11:20 -08002460void
2461_mesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2462 GLenum internalFormat, GLsizei width,
Marek Olšák2d115052018-06-11 15:26:41 -04002463 GLsizei height, GLsizei samples,
2464 GLsizei storageSamples)
Ian Romanickeb5bc622015-11-12 09:11:20 -08002465{
2466 const GLenum baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
2467
2468 assert(baseFormat != 0);
2469 assert(width >= 0 && width <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2470 assert(height >= 0 && height <= (GLsizei) ctx->Const.MaxRenderbufferSize);
2471 assert(samples != NO_SAMPLES);
2472 if (samples != 0) {
2473 assert(samples > 0);
2474 assert(_mesa_check_sample_count(ctx, GL_RENDERBUFFER,
Marek Olšák2d115052018-06-11 15:26:41 -04002475 internalFormat, samples,
2476 storageSamples) == GL_NO_ERROR);
Ian Romanickeb5bc622015-11-12 09:11:20 -08002477 }
2478
2479 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2480
2481 if (rb->InternalFormat == internalFormat &&
2482 rb->Width == (GLuint) width &&
2483 rb->Height == (GLuint) height &&
Marek Olšák328c1c82018-06-11 17:24:16 -04002484 rb->NumSamples == samples &&
2485 rb->NumStorageSamples == storageSamples) {
Ian Romanickeb5bc622015-11-12 09:11:20 -08002486 /* no change in allocation needed */
2487 return;
2488 }
2489
2490 /* These MUST get set by the AllocStorage func */
2491 rb->Format = MESA_FORMAT_NONE;
2492 rb->NumSamples = samples;
Marek Olšák328c1c82018-06-11 17:24:16 -04002493 rb->NumStorageSamples = storageSamples;
Ian Romanickeb5bc622015-11-12 09:11:20 -08002494
2495 /* Now allocate the storage */
2496 assert(rb->AllocStorage);
2497 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
2498 /* No error - check/set fields now */
2499 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
2500 assert(rb->Width == (GLuint) width);
2501 assert(rb->Height == (GLuint) height);
2502 rb->InternalFormat = internalFormat;
2503 rb->_BaseFormat = baseFormat;
2504 assert(rb->_BaseFormat != 0);
2505 }
2506 else {
2507 /* Probably ran out of memory - clear the fields */
2508 rb->Width = 0;
2509 rb->Height = 0;
2510 rb->Format = MESA_FORMAT_NONE;
2511 rb->InternalFormat = GL_NONE;
2512 rb->_BaseFormat = GL_NONE;
2513 rb->NumSamples = 0;
Marek Olšák328c1c82018-06-11 17:24:16 -04002514 rb->NumStorageSamples = 0;
Ian Romanickeb5bc622015-11-12 09:11:20 -08002515 }
2516
2517 /* Invalidate the framebuffers the renderbuffer is attached in. */
2518 if (rb->AttachedAnytime) {
2519 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
2520 }
2521}
Brian Paul4f3514e2009-01-22 15:19:56 -07002522
2523/**
Martin Peresbf11c192015-02-13 15:35:48 +02002524 * Helper function used by renderbuffer_storage_direct() and
2525 * renderbuffer_storage_target().
2526 * samples will be NO_SAMPLES if called by a non-multisample function.
Brian Paul4f3514e2009-01-22 15:19:56 -07002527 */
2528static void
Martin Peresbf11c192015-02-13 15:35:48 +02002529renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
2530 GLenum internalFormat, GLsizei width,
Marek Olšák2d115052018-06-11 15:26:41 -04002531 GLsizei height, GLsizei samples, GLsizei storageSamples,
2532 const char *func)
Brian Paulddc82ee2005-02-05 19:56:45 +00002533{
Brian Paul463642c2005-02-08 02:06:00 +00002534 GLenum baseFormat;
Chris Forbes90b5a242013-02-06 20:42:53 +13002535 GLenum sample_count_error;
Brian Paulddc82ee2005-02-05 19:56:45 +00002536
Brian Paul59e0faa2006-03-15 17:48:00 +00002537 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
Brian Paul463642c2005-02-08 02:06:00 +00002538 if (baseFormat == 0) {
Jordan Justen119002a2013-01-10 17:29:27 -08002539 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002540 func, _mesa_enum_to_string(internalFormat));
Brian Paulddc82ee2005-02-05 19:56:45 +00002541 return;
2542 }
2543
Yuanhan Liu49f84472011-10-25 15:36:59 +08002544 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Martin Peresbf11c192015-02-13 15:35:48 +02002545 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid width %d)", func,
2546 width);
Brian Paulddc82ee2005-02-05 19:56:45 +00002547 return;
2548 }
2549
Yuanhan Liu49f84472011-10-25 15:36:59 +08002550 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Martin Peresbf11c192015-02-13 15:35:48 +02002551 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid height %d)", func,
2552 height);
Brian Paul4f3514e2009-01-22 15:19:56 -07002553 return;
2554 }
2555
2556 if (samples == NO_SAMPLES) {
2557 /* NumSamples == 0 indicates non-multisampling */
2558 samples = 0;
Marek Olšák2d115052018-06-11 15:26:41 -04002559 storageSamples = 0;
Brian Paul4f3514e2009-01-22 15:19:56 -07002560 }
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002561 else {
2562 /* check the sample count;
2563 * note: driver may choose to use more samples than what's requested
2564 */
Martin Peresbf11c192015-02-13 15:35:48 +02002565 sample_count_error = _mesa_check_sample_count(ctx, GL_RENDERBUFFER,
Marek Olšák2d115052018-06-11 15:26:41 -04002566 internalFormat, samples, storageSamples);
Timothy Arceri46684d32015-08-13 18:44:51 +10002567
2568 /* Section 2.5 (GL Errors) of OpenGL 3.0 specification, page 16:
2569 *
2570 * "If a negative number is provided where an argument of type sizei or
2571 * sizeiptr is specified, the error INVALID VALUE is generated."
2572 */
Marek Olšák2d115052018-06-11 15:26:41 -04002573 if (samples < 0 || storageSamples < 0) {
Timothy Arceri46684d32015-08-13 18:44:51 +10002574 sample_count_error = GL_INVALID_VALUE;
2575 }
2576
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002577 if (sample_count_error != GL_NO_ERROR) {
Marek Olšák2d115052018-06-11 15:26:41 -04002578 _mesa_error(ctx, sample_count_error,
2579 "%s(samples=%d, storageSamples=%d)", func, samples,
2580 storageSamples);
Chris Forbes21a2dfa2013-03-25 23:19:07 +13002581 return;
2582 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002583 }
2584
Marek Olšák2d115052018-06-11 15:26:41 -04002585 _mesa_renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2586 storageSamples);
Brian Paulddc82ee2005-02-05 19:56:45 +00002587}
2588
Martin Peresbf11c192015-02-13 15:35:48 +02002589/**
2590 * Helper function used by _mesa_NamedRenderbufferStorage*().
2591 * samples will be NO_SAMPLES if called by a non-multisample function.
2592 */
2593static void
2594renderbuffer_storage_named(GLuint renderbuffer, GLenum internalFormat,
2595 GLsizei width, GLsizei height, GLsizei samples,
Marek Olšák2d115052018-06-11 15:26:41 -04002596 GLsizei storageSamples, const char *func)
Martin Peresbf11c192015-02-13 15:35:48 +02002597{
2598 GET_CURRENT_CONTEXT(ctx);
2599
2600 if (MESA_VERBOSE & VERBOSE_API) {
2601 if (samples == NO_SAMPLES)
2602 _mesa_debug(ctx, "%s(%u, %s, %d, %d)\n",
2603 func, renderbuffer,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002604 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002605 width, height);
2606 else
2607 _mesa_debug(ctx, "%s(%u, %s, %d, %d, %d)\n",
2608 func, renderbuffer,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002609 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002610 width, height, samples);
2611 }
2612
2613 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2614 if (!rb || rb == &DummyRenderbuffer) {
2615 /* ID was reserved, but no real renderbuffer object made yet */
2616 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid renderbuffer %u)",
2617 func, renderbuffer);
2618 return;
2619 }
2620
Marek Olšák2d115052018-06-11 15:26:41 -04002621 renderbuffer_storage(ctx, rb, internalFormat, width, height, samples,
2622 storageSamples, func);
Martin Peresbf11c192015-02-13 15:35:48 +02002623}
2624
2625/**
2626 * Helper function used by _mesa_RenderbufferStorage() and
2627 * _mesa_RenderbufferStorageMultisample().
2628 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
2629 */
2630static void
2631renderbuffer_storage_target(GLenum target, GLenum internalFormat,
2632 GLsizei width, GLsizei height, GLsizei samples,
Marek Olšák2d115052018-06-11 15:26:41 -04002633 GLsizei storageSamples, const char *func)
Martin Peresbf11c192015-02-13 15:35:48 +02002634{
2635 GET_CURRENT_CONTEXT(ctx);
2636
2637 if (MESA_VERBOSE & VERBOSE_API) {
2638 if (samples == NO_SAMPLES)
2639 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
2640 func,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002641 _mesa_enum_to_string(target),
2642 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002643 width, height);
2644 else
2645 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
2646 func,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07002647 _mesa_enum_to_string(target),
2648 _mesa_enum_to_string(internalFormat),
Martin Peresbf11c192015-02-13 15:35:48 +02002649 width, height, samples);
2650 }
2651
2652 if (target != GL_RENDERBUFFER_EXT) {
2653 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
2654 return;
2655 }
2656
2657 if (!ctx->CurrentRenderbuffer) {
2658 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no renderbuffer bound)",
2659 func);
2660 return;
2661 }
2662
2663 renderbuffer_storage(ctx, ctx->CurrentRenderbuffer, internalFormat, width,
Marek Olšák2d115052018-06-11 15:26:41 -04002664 height, samples, storageSamples, func);
Martin Peresbf11c192015-02-13 15:35:48 +02002665}
2666
Brian Paul23c5b212010-05-28 13:33:03 -06002667
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002668void GLAPIENTRY
Brian Paul23c5b212010-05-28 13:33:03 -06002669_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002670{
Brian Paul51b79922010-02-24 11:57:26 -07002671 struct gl_renderbuffer *rb;
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002672 GET_CURRENT_CONTEXT(ctx);
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002673
Chia-I Wu2002e4d02010-04-06 17:46:17 +08002674 if (!ctx->Extensions.OES_EGL_image) {
2675 _mesa_error(ctx, GL_INVALID_OPERATION,
2676 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
2677 return;
2678 }
2679
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002680 if (target != GL_RENDERBUFFER) {
Brian Paul23c5b212010-05-28 13:33:03 -06002681 _mesa_error(ctx, GL_INVALID_ENUM,
2682 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002683 return;
2684 }
2685
2686 rb = ctx->CurrentRenderbuffer;
2687 if (!rb) {
Brian Paul23c5b212010-05-28 13:33:03 -06002688 _mesa_error(ctx, GL_INVALID_OPERATION,
2689 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05002690 return;
2691 }
2692
2693 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2694
2695 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
2696}
Brian Paulddc82ee2005-02-05 19:56:45 +00002697
Brian Paul23c5b212010-05-28 13:33:03 -06002698
Brian Paul45e76d22009-10-08 20:27:27 -06002699/**
Paul Berry1a1db172012-11-06 08:57:59 -08002700 * Helper function for _mesa_GetRenderbufferParameteriv() and
2701 * _mesa_GetFramebufferAttachmentParameteriv()
Brian Paul45e76d22009-10-08 20:27:27 -06002702 * We have to be careful to respect the base format. For example, if a
2703 * renderbuffer/texture was created with internalFormat=GL_RGB but the
2704 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
2705 * we need to return zero.
2706 */
2707static GLint
Mark Mueller71fe9432014-01-04 14:11:43 -08002708get_component_bits(GLenum pname, GLenum baseFormat, mesa_format format)
Brian Paul45e76d22009-10-08 20:27:27 -06002709{
Brian Paulf0b6e9a2011-11-23 15:33:45 -07002710 if (_mesa_base_format_has_channel(baseFormat, pname))
2711 return _mesa_get_format_bits(format, pname);
2712 else
Brian Paul45e76d22009-10-08 20:27:27 -06002713 return 0;
Brian Paul45e76d22009-10-08 20:27:27 -06002714}
2715
2716
2717
Brian Paul1864c7d2005-02-08 03:46:37 +00002718void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002719_mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
Brian Paul4f3514e2009-01-22 15:19:56 -07002720 GLsizei width, GLsizei height)
2721{
Brian Paul722d9762009-01-20 16:58:49 -07002722 /* GL_ARB_fbo says calling this function is equivalent to calling
2723 * glRenderbufferStorageMultisample() with samples=0. We pass in
2724 * a token value here just for error reporting purposes.
2725 */
Martin Peresbf11c192015-02-13 15:35:48 +02002726 renderbuffer_storage_target(target, internalFormat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002727 NO_SAMPLES, 0, "glRenderbufferStorage");
Brian Paul4f3514e2009-01-22 15:19:56 -07002728}
2729
2730
2731void GLAPIENTRY
Brian Paul777a2ef2009-01-22 15:17:42 -07002732_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
Brian Paul4f3514e2009-01-22 15:19:56 -07002733 GLenum internalFormat,
Brian Paul777a2ef2009-01-22 15:17:42 -07002734 GLsizei width, GLsizei height)
2735{
Martin Peresbf11c192015-02-13 15:35:48 +02002736 renderbuffer_storage_target(target, internalFormat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002737 samples, samples,
2738 "glRenderbufferStorageMultisample");
Brian Paul777a2ef2009-01-22 15:17:42 -07002739}
2740
Brian Paul23c5b212010-05-28 13:33:03 -06002741
Marek Olšák3d6900d2018-06-28 02:05:12 -04002742void GLAPIENTRY
2743_mesa_RenderbufferStorageMultisampleAdvancedAMD(
2744 GLenum target, GLsizei samples, GLsizei storageSamples,
2745 GLenum internalFormat, GLsizei width, GLsizei height)
2746{
2747 renderbuffer_storage_target(target, internalFormat, width, height,
2748 samples, storageSamples,
2749 "glRenderbufferStorageMultisampleAdvancedAMD");
2750}
2751
2752
Brian Paul23c5b212010-05-28 13:33:03 -06002753/**
2754 * OpenGL ES version of glRenderBufferStorage.
2755 */
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002756void GLAPIENTRY
2757_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
Martin Peres7bd8b482015-02-12 17:54:43 +02002758 GLsizei width, GLsizei height)
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002759{
2760 switch (internalFormat) {
2761 case GL_RGB565:
2762 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
2763 /* choose a closest format */
2764 internalFormat = GL_RGB5;
2765 break;
2766 default:
2767 break;
2768 }
Brian Paul777a2ef2009-01-22 15:17:42 -07002769
Marek Olšák2d115052018-06-11 15:26:41 -04002770 renderbuffer_storage_target(target, internalFormat, width, height, 0, 0,
Martin Peresbf11c192015-02-13 15:35:48 +02002771 "glRenderbufferStorageEXT");
2772}
2773
2774void GLAPIENTRY
2775_mesa_NamedRenderbufferStorage(GLuint renderbuffer, GLenum internalformat,
2776 GLsizei width, GLsizei height)
2777{
2778 /* GL_ARB_fbo says calling this function is equivalent to calling
2779 * glRenderbufferStorageMultisample() with samples=0. We pass in
2780 * a token value here just for error reporting purposes.
2781 */
2782 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002783 NO_SAMPLES, 0, "glNamedRenderbufferStorage");
Martin Peresbf11c192015-02-13 15:35:48 +02002784}
2785
2786void GLAPIENTRY
Pierre-Eric Pelloux-Prayer01666ad2019-05-23 16:34:16 +02002787_mesa_NamedRenderbufferStorageEXT(GLuint renderbuffer, GLenum internalformat,
2788 GLsizei width, GLsizei height)
2789{
2790 GET_CURRENT_CONTEXT(ctx);
2791 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2792 if (!rb || rb == &DummyRenderbuffer) {
2793 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02002794 rb = allocate_renderbuffer_locked(ctx, renderbuffer, rb != NULL,
2795 "glNamedRenderbufferStorageEXT");
Pierre-Eric Pelloux-Prayer01666ad2019-05-23 16:34:16 +02002796 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2797 }
2798 renderbuffer_storage(ctx, rb, internalformat, width, height, NO_SAMPLES,
2799 0, "glNamedRenderbufferStorageEXT");
2800}
2801
2802
2803void GLAPIENTRY
Martin Peresbf11c192015-02-13 15:35:48 +02002804_mesa_NamedRenderbufferStorageMultisample(GLuint renderbuffer, GLsizei samples,
2805 GLenum internalformat,
2806 GLsizei width, GLsizei height)
2807{
2808 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
Marek Olšák2d115052018-06-11 15:26:41 -04002809 samples, samples,
Martin Peresbf11c192015-02-13 15:35:48 +02002810 "glNamedRenderbufferStorageMultisample");
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04002811}
Brian Paul777a2ef2009-01-22 15:17:42 -07002812
Brian Paul23c5b212010-05-28 13:33:03 -06002813
Marek Olšák3d6900d2018-06-28 02:05:12 -04002814void GLAPIENTRY
Pierre-Eric Pelloux-Prayerda214352019-09-11 10:13:21 +02002815_mesa_NamedRenderbufferStorageMultisampleEXT(GLuint renderbuffer, GLsizei samples,
2816 GLenum internalformat,
2817 GLsizei width, GLsizei height)
2818{
2819 GET_CURRENT_CONTEXT(ctx);
2820 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2821 if (!rb || rb == &DummyRenderbuffer) {
2822 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02002823 rb = allocate_renderbuffer_locked(ctx, renderbuffer, rb != NULL,
Pierre-Eric Pelloux-Prayerda214352019-09-11 10:13:21 +02002824 "glNamedRenderbufferStorageMultisampleEXT");
2825 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2826 }
2827 renderbuffer_storage(ctx, rb, internalformat, width, height,
2828 samples, samples,
2829 "glNamedRenderbufferStorageMultisample");
2830}
2831
2832
2833void GLAPIENTRY
Marek Olšák3d6900d2018-06-28 02:05:12 -04002834_mesa_NamedRenderbufferStorageMultisampleAdvancedAMD(
2835 GLuint renderbuffer, GLsizei samples, GLsizei storageSamples,
2836 GLenum internalformat, GLsizei width, GLsizei height)
2837{
2838 renderbuffer_storage_named(renderbuffer, internalformat, width, height,
2839 samples, storageSamples,
2840 "glNamedRenderbufferStorageMultisampleAdvancedAMD");
2841}
2842
2843
Martin Peres245e5c42015-02-13 15:46:55 +02002844static void
2845get_render_buffer_parameteriv(struct gl_context *ctx,
2846 struct gl_renderbuffer *rb, GLenum pname,
2847 GLint *params, const char *func)
Brian Paulddc82ee2005-02-05 19:56:45 +00002848{
Brian Paul800e5532009-11-02 15:39:39 -07002849 /* No need to flush here since we're just quering state which is
2850 * not effected by rendering.
2851 */
Brian Paul474f28e2005-10-08 14:41:17 +00002852
Brian Paul463642c2005-02-08 02:06:00 +00002853 switch (pname) {
2854 case GL_RENDERBUFFER_WIDTH_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002855 *params = rb->Width;
Brian Paul463642c2005-02-08 02:06:00 +00002856 return;
2857 case GL_RENDERBUFFER_HEIGHT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002858 *params = rb->Height;
Brian Paul463642c2005-02-08 02:06:00 +00002859 return;
2860 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07002861 *params = rb->InternalFormat;
Brian Paul463642c2005-02-08 02:06:00 +00002862 return;
Brian Paul1b939532005-05-31 23:55:21 +00002863 case GL_RENDERBUFFER_RED_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002864 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002865 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002866 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002867 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00002868 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
Brian Paul45e76d22009-10-08 20:27:27 -06002869 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
Marek Olšák328c1c82018-06-11 17:24:16 -04002870 return;
Brian Paul722d9762009-01-20 16:58:49 -07002871 case GL_RENDERBUFFER_SAMPLES:
Ian Romanickae86ebf2012-07-27 07:49:49 -07002872 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
2873 || _mesa_is_gles3(ctx)) {
Brian Paul722d9762009-01-20 16:58:49 -07002874 *params = rb->NumSamples;
Marek Olšák328c1c82018-06-11 17:24:16 -04002875 return;
Brian Paul722d9762009-01-20 16:58:49 -07002876 }
Marek Olšák328c1c82018-06-11 17:24:16 -04002877 break;
2878 case GL_RENDERBUFFER_STORAGE_SAMPLES_AMD:
2879 if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
2880 *params = rb->NumStorageSamples;
2881 return;
2882 }
2883 break;
Martin Peres245e5c42015-02-13 15:46:55 +02002884 }
Marek Olšák328c1c82018-06-11 17:24:16 -04002885
2886 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname=%s)", func,
2887 _mesa_enum_to_string(pname));
Martin Peres245e5c42015-02-13 15:46:55 +02002888}
2889
2890
2891void GLAPIENTRY
2892_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
2893{
2894 GET_CURRENT_CONTEXT(ctx);
2895
2896 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul463642c2005-02-08 02:06:00 +00002897 _mesa_error(ctx, GL_INVALID_ENUM,
2898 "glGetRenderbufferParameterivEXT(target)");
2899 return;
2900 }
Martin Peres245e5c42015-02-13 15:46:55 +02002901
2902 if (!ctx->CurrentRenderbuffer) {
2903 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetRenderbufferParameterivEXT"
2904 "(no renderbuffer bound)");
2905 return;
2906 }
2907
2908 get_render_buffer_parameteriv(ctx, ctx->CurrentRenderbuffer, pname,
2909 params, "glGetRenderbufferParameteriv");
2910}
2911
2912
2913void GLAPIENTRY
2914_mesa_GetNamedRenderbufferParameteriv(GLuint renderbuffer, GLenum pname,
2915 GLint *params)
2916{
2917 GET_CURRENT_CONTEXT(ctx);
2918
2919 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2920 if (!rb || rb == &DummyRenderbuffer) {
2921 /* ID was reserved, but no real renderbuffer object made yet */
2922 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetNamedRenderbufferParameteriv"
2923 "(invalid renderbuffer %i)", renderbuffer);
2924 return;
2925 }
2926
2927 get_render_buffer_parameteriv(ctx, rb, pname, params,
2928 "glGetNamedRenderbufferParameteriv");
Brian Paulddc82ee2005-02-05 19:56:45 +00002929}
2930
2931
Pierre-Eric Pelloux-Prayer01666ad2019-05-23 16:34:16 +02002932void GLAPIENTRY
2933_mesa_GetNamedRenderbufferParameterivEXT(GLuint renderbuffer, GLenum pname,
2934 GLint *params)
2935{
2936 GET_CURRENT_CONTEXT(ctx);
2937
2938 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2939 if (!rb || rb == &DummyRenderbuffer) {
2940 _mesa_HashLockMutex(ctx->Shared->RenderBuffers);
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02002941 rb = allocate_renderbuffer_locked(ctx, renderbuffer, rb != NULL,
2942 "glGetNamedRenderbufferParameterivEXT");
Pierre-Eric Pelloux-Prayer01666ad2019-05-23 16:34:16 +02002943 _mesa_HashUnlockMutex(ctx->Shared->RenderBuffers);
2944 }
2945
2946 get_render_buffer_parameteriv(ctx, rb, pname, params,
2947 "glGetNamedRenderbufferParameterivEXT");
2948}
2949
2950
Brian Paul1864c7d2005-02-08 03:46:37 +00002951GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002952_mesa_IsFramebuffer(GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00002953{
Brian Paulddc82ee2005-02-05 19:56:45 +00002954 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +00002955 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Brian Paulbc6cced2005-10-04 15:01:27 +00002956 if (framebuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00002957 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
Brian Paulbc6cced2005-10-04 15:01:27 +00002958 if (rb != NULL && rb != &DummyFramebuffer)
2959 return GL_TRUE;
2960 }
2961 return GL_FALSE;
Brian Paulddc82ee2005-02-05 19:56:45 +00002962}
2963
2964
briana492ab72009-11-10 15:33:31 -07002965/**
2966 * Check if any of the attachments of the given framebuffer are textures
2967 * (render to texture). Call ctx->Driver.RenderTexture() for such
2968 * attachments.
2969 */
Brian Paulea4fe662006-03-26 05:22:17 +00002970static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002971check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paulea4fe662006-03-26 05:22:17 +00002972{
2973 GLuint i;
Matt Turnerbfcdb842015-02-20 20:18:47 -08002974 assert(ctx->Driver.RenderTexture);
briana65b84d2009-11-10 18:02:03 -07002975
Brian Paul36ede892012-01-12 09:17:23 -07002976 if (_mesa_is_winsys_fbo(fb))
briana65b84d2009-11-10 18:02:03 -07002977 return; /* can't render to texture with winsys framebuffers */
2978
Brian Paulea4fe662006-03-26 05:22:17 +00002979 for (i = 0; i < BUFFER_COUNT; i++) {
2980 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Ian Romanickfb497132013-07-27 12:04:20 -07002981 if (att->Texture && att->Renderbuffer->TexImage
2982 && driver_RenderTexture_is_safe(att)) {
Brian Paulea4fe662006-03-26 05:22:17 +00002983 ctx->Driver.RenderTexture(ctx, fb, att);
2984 }
2985 }
2986}
2987
2988
Brian Paul0e31e022005-12-01 00:25:00 +00002989/**
2990 * Examine all the framebuffer's attachments to see if any are textures.
2991 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
2992 * notify the device driver that the texture image may have changed.
2993 */
2994static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002995check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paul0e31e022005-12-01 00:25:00 +00002996{
Eric Anholt7ccb26f2014-03-03 09:16:48 -08002997 /* Skip if we know NeedsFinishRenderTexture won't be set. */
2998 if (_mesa_is_winsys_fbo(fb) && !ctx->Driver.BindRenderbufferTexImage)
2999 return;
briana65b84d2009-11-10 18:02:03 -07003000
Brian Paul0e31e022005-12-01 00:25:00 +00003001 if (ctx->Driver.FinishRenderTexture) {
3002 GLuint i;
3003 for (i = 0; i < BUFFER_COUNT; i++) {
3004 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Eric Anholtc810e672013-05-10 12:36:43 -07003005 struct gl_renderbuffer *rb = att->Renderbuffer;
3006 if (rb && rb->NeedsFinishRenderTexture) {
Eric Anholta5b04522013-05-10 12:17:52 -07003007 ctx->Driver.FinishRenderTexture(ctx, rb);
Brian Paul0e31e022005-12-01 00:25:00 +00003008 }
3009 }
3010 }
3011}
3012
3013
Ian Romanick4a9522a2013-07-18 17:39:22 -07003014static void
Timothy Arcerib54a2312018-09-08 14:20:17 +10003015bind_framebuffer(GLenum target, GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00003016{
briane6f60d32009-11-10 15:47:34 -07003017 struct gl_framebuffer *newDrawFb, *newReadFb;
Brian Paul0bffb112005-11-08 14:45:48 +00003018 GLboolean bindReadBuf, bindDrawBuf;
Brian Paulddc82ee2005-02-05 19:56:45 +00003019 GET_CURRENT_CONTEXT(ctx);
3020
Brian Paul0bffb112005-11-08 14:45:48 +00003021 switch (target) {
Brian Paul0bffb112005-11-08 14:45:48 +00003022 case GL_DRAW_FRAMEBUFFER_EXT:
Brian Paul0bffb112005-11-08 14:45:48 +00003023 bindDrawBuf = GL_TRUE;
3024 bindReadBuf = GL_FALSE;
3025 break;
3026 case GL_READ_FRAMEBUFFER_EXT:
Brian Paul0bffb112005-11-08 14:45:48 +00003027 bindDrawBuf = GL_FALSE;
3028 bindReadBuf = GL_TRUE;
3029 break;
Brian Paul0bffb112005-11-08 14:45:48 +00003030 case GL_FRAMEBUFFER_EXT:
3031 bindDrawBuf = GL_TRUE;
3032 bindReadBuf = GL_TRUE;
3033 break;
3034 default:
Brian Pauleba4ff62005-09-06 21:22:16 +00003035 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00003036 return;
3037 }
3038
Brian Paul3deaa012005-02-07 05:08:24 +00003039 if (framebuffer) {
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02003040 bool isGenName = false;
Brian Paule4b23562005-05-04 20:11:35 +00003041 /* Binding a user-created framebuffer object */
briane6f60d32009-11-10 15:47:34 -07003042 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
3043 if (newDrawFb == &DummyFramebuffer) {
Brian Paul923b6fc2005-02-08 04:08:56 +00003044 /* ID was reserved, but no real framebuffer object made yet */
briane6f60d32009-11-10 15:47:34 -07003045 newDrawFb = NULL;
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02003046 isGenName = true;
Brian Paul1864c7d2005-02-08 03:46:37 +00003047 }
Timothy Arcerib54a2312018-09-08 14:20:17 +10003048 else if (!newDrawFb && ctx->API == API_OPENGL_CORE) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07003049 /* All FBO IDs must be Gen'd */
Timothy Arcerib54a2312018-09-08 14:20:17 +10003050 _mesa_error(ctx, GL_INVALID_OPERATION,
3051 "glBindFramebuffer(non-gen name)");
Brian Paul1bc59bf2009-01-22 15:07:34 -07003052 return;
3053 }
3054
briane6f60d32009-11-10 15:47:34 -07003055 if (!newDrawFb) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003056 /* create new framebuffer object */
3057 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
3058 if (!newDrawFb) {
3059 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
3060 return;
3061 }
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02003062 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb, isGenName);
Brian Paul3deaa012005-02-07 05:08:24 +00003063 }
briane6f60d32009-11-10 15:47:34 -07003064 newReadFb = newDrawFb;
Brian Paul3deaa012005-02-07 05:08:24 +00003065 }
Brian Paul463642c2005-02-08 02:06:00 +00003066 else {
Brian Paule4b23562005-05-04 20:11:35 +00003067 /* Binding the window system framebuffer (which was originally set
3068 * with MakeCurrent).
3069 */
briane6f60d32009-11-10 15:47:34 -07003070 newDrawFb = ctx->WinSysDrawBuffer;
3071 newReadFb = ctx->WinSysReadBuffer;
Brian Paul3deaa012005-02-07 05:08:24 +00003072 }
3073
Ian Romanickfed9b0e2015-11-13 10:46:40 -08003074 _mesa_bind_framebuffers(ctx,
3075 bindDrawBuf ? newDrawFb : ctx->DrawBuffer,
3076 bindReadBuf ? newReadFb : ctx->ReadBuffer);
3077}
3078
3079void
3080_mesa_bind_framebuffers(struct gl_context *ctx,
3081 struct gl_framebuffer *newDrawFb,
3082 struct gl_framebuffer *newReadFb)
3083{
3084 struct gl_framebuffer *const oldDrawFb = ctx->DrawBuffer;
3085 struct gl_framebuffer *const oldReadFb = ctx->ReadBuffer;
3086 const bool bindDrawBuf = oldDrawFb != newDrawFb;
3087 const bool bindReadBuf = oldReadFb != newReadFb;
3088
Matt Turnerbfcdb842015-02-20 20:18:47 -08003089 assert(newDrawFb);
3090 assert(newDrawFb != &DummyFramebuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00003091
Brian Paulea4fe662006-03-26 05:22:17 +00003092 /*
Brian Paul16144632009-02-26 14:49:24 -07003093 * OK, now bind the new Draw/Read framebuffers, if they're changing.
briana65b84d2009-11-10 18:02:03 -07003094 *
3095 * We also check if we're beginning and/or ending render-to-texture.
3096 * When a framebuffer with texture attachments is unbound, call
3097 * ctx->Driver.FinishRenderTexture().
3098 * When a framebuffer with texture attachments is bound, call
3099 * ctx->Driver.RenderTexture().
3100 *
3101 * Note that if the ReadBuffer has texture attachments we don't consider
3102 * that a render-to-texture case.
Brian Paulea4fe662006-03-26 05:22:17 +00003103 */
Brian Paul0bffb112005-11-08 14:45:48 +00003104 if (bindReadBuf) {
briana65b84d2009-11-10 18:02:03 -07003105 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
brianbc569cd2009-11-10 16:00:35 -07003106
briana65b84d2009-11-10 18:02:03 -07003107 /* check if old readbuffer was render-to-texture */
3108 check_end_texture_render(ctx, oldReadFb);
3109
3110 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
Brian Paul0bffb112005-11-08 14:45:48 +00003111 }
3112
3113 if (bindDrawBuf) {
briana65b84d2009-11-10 18:02:03 -07003114 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Rhys Perry67f40da2018-06-14 19:56:28 -06003115 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
Brian32d86eb2007-08-16 18:52:48 +01003116
Eric Anholta1fd13f2012-02-10 12:05:16 -08003117 /* check if old framebuffer had any texture attachments */
3118 if (oldDrawFb)
briana65b84d2009-11-10 18:02:03 -07003119 check_end_texture_render(ctx, oldDrawFb);
brianbc569cd2009-11-10 16:00:35 -07003120
briana65b84d2009-11-10 18:02:03 -07003121 /* check if newly bound framebuffer has any texture attachments */
3122 check_begin_texture_render(ctx, newDrawFb);
3123
3124 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
Marek Olšák8c053e52020-01-30 18:56:22 -05003125 _mesa_update_allow_draw_out_of_order(ctx);
Brian Paul0bffb112005-11-08 14:45:48 +00003126 }
Brian Paul59e0faa2006-03-15 17:48:00 +00003127
Brian Paul16144632009-02-26 14:49:24 -07003128 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
Ian Romanickfed9b0e2015-11-13 10:46:40 -08003129 /* The few classic drivers that actually hook this function really only
3130 * want to know if the draw framebuffer changed.
3131 */
3132 ctx->Driver.BindFramebuffer(ctx,
3133 bindDrawBuf ? GL_FRAMEBUFFER : GL_READ_FRAMEBUFFER,
3134 newDrawFb, newReadFb);
Brian Paul59e0faa2006-03-15 17:48:00 +00003135 }
Brian Paulddc82ee2005-02-05 19:56:45 +00003136}
3137
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003138void GLAPIENTRY
Ian Romanick4a9522a2013-07-18 17:39:22 -07003139_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003140{
Ian Romanick4a9522a2013-07-18 17:39:22 -07003141 /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
3142 * point, but they allow the use of user-generated names.
3143 */
Timothy Arcerib54a2312018-09-08 14:20:17 +10003144 bind_framebuffer(target, framebuffer);
Tomasz Lis9f07ca12013-07-16 20:57:26 +02003145}
3146
Brian Paulc1377ed2014-03-22 10:31:58 -06003147
Ian Romanick4a9522a2013-07-18 17:39:22 -07003148void GLAPIENTRY
3149_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
3150{
Timothy Arcerib54a2312018-09-08 14:20:17 +10003151 bind_framebuffer(target, framebuffer);
Ian Romanick4a9522a2013-07-18 17:39:22 -07003152}
Brian Paulddc82ee2005-02-05 19:56:45 +00003153
Brian Paulc1377ed2014-03-22 10:31:58 -06003154
Brian Paul1864c7d2005-02-08 03:46:37 +00003155void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003156_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00003157{
3158 GLint i;
3159 GET_CURRENT_CONTEXT(ctx);
3160
Eduardo Lima Mitevf77a4732014-12-11 23:34:17 +01003161 if (n < 0) {
3162 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteFramebuffers(n < 0)");
3163 return;
3164 }
3165
Brian Paul800e5532009-11-02 15:39:39 -07003166 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00003167
3168 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00003169 if (framebuffers[i] > 0) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003170 struct gl_framebuffer *fb;
3171 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
3172 if (fb) {
Matt Turnerbfcdb842015-02-20 20:18:47 -08003173 assert(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
Brian Paul91802fd2005-10-04 16:01:02 +00003174
3175 /* check if deleting currently bound framebuffer object */
Ian Romanick764be9f2013-11-13 14:00:06 -08003176 if (fb == ctx->DrawBuffer) {
3177 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08003178 assert(fb->RefCount >= 2);
Ian Romanick764be9f2013-11-13 14:00:06 -08003179 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3180 }
3181 if (fb == ctx->ReadBuffer) {
3182 /* bind default */
Matt Turnerbfcdb842015-02-20 20:18:47 -08003183 assert(fb->RefCount >= 2);
Ian Romanick764be9f2013-11-13 14:00:06 -08003184 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
3185 }
Brian Paul91802fd2005-10-04 16:01:02 +00003186
Martin Peres7bd8b482015-02-12 17:54:43 +02003187 /* remove from hash table immediately, to free the ID */
3188 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00003189
Brian Paul1864c7d2005-02-08 03:46:37 +00003190 if (fb != &DummyFramebuffer) {
3191 /* But the object will not be freed until it's no longer
3192 * bound in any context.
3193 */
Brian Pauld5229442009-02-09 08:30:55 -07003194 _mesa_reference_framebuffer(&fb, NULL);
Martin Peres7bd8b482015-02-12 17:54:43 +02003195 }
3196 }
Brian Paulddc82ee2005-02-05 19:56:45 +00003197 }
3198 }
3199}
3200
3201
Laura Ekstrandf868de72015-01-23 14:54:48 -08003202/**
3203 * This is the implementation for glGenFramebuffers and glCreateFramebuffers.
3204 * It is not exposed to the rest of Mesa to encourage the use of
3205 * nameless buffers in driver internals.
3206 */
3207static void
3208create_framebuffers(GLsizei n, GLuint *framebuffers, bool dsa)
Brian Paulddc82ee2005-02-05 19:56:45 +00003209{
3210 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +00003211 GLint i;
Laura Ekstrandf868de72015-01-23 14:54:48 -08003212 struct gl_framebuffer *fb;
3213
3214 const char *func = dsa ? "glCreateFramebuffers" : "glGenFramebuffers";
Brian Paulddc82ee2005-02-05 19:56:45 +00003215
Brian Paulddc82ee2005-02-05 19:56:45 +00003216 if (n < 0) {
Laura Ekstrandf868de72015-01-23 14:54:48 -08003217 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00003218 return;
3219 }
3220
3221 if (!framebuffers)
3222 return;
3223
Matt Turner015f2202015-07-30 14:31:04 -07003224 _mesa_HashLockMutex(ctx->Shared->FrameBuffers);
3225
Pierre-Eric Pelloux-Prayera56849d2020-08-17 15:12:03 +02003226 _mesa_HashFindFreeKeys(ctx->Shared->FrameBuffers, framebuffers, n);
Brian Paulddc82ee2005-02-05 19:56:45 +00003227
3228 for (i = 0; i < n; i++) {
Laura Ekstrandf868de72015-01-23 14:54:48 -08003229 if (dsa) {
3230 fb = ctx->Driver.NewFramebuffer(ctx, framebuffers[i]);
3231 if (!fb) {
Matt Turnerbdc9c202016-05-22 07:00:34 -07003232 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
Laura Ekstrandf868de72015-01-23 14:54:48 -08003233 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
3234 return;
3235 }
3236 }
3237 else
3238 fb = &DummyFramebuffer;
3239
Pierre-Eric Pelloux-Prayera56849d2020-08-17 15:12:03 +02003240 _mesa_HashInsertLocked(ctx->Shared->FrameBuffers, framebuffers[i],
3241 fb, true);
Brian Paulddc82ee2005-02-05 19:56:45 +00003242 }
Matt Turner015f2202015-07-30 14:31:04 -07003243
3244 _mesa_HashUnlockMutex(ctx->Shared->FrameBuffers);
Brian Paulddc82ee2005-02-05 19:56:45 +00003245}
3246
3247
Laura Ekstrandf868de72015-01-23 14:54:48 -08003248void GLAPIENTRY
3249_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
3250{
3251 create_framebuffers(n, framebuffers, false);
3252}
3253
3254
3255void GLAPIENTRY
3256_mesa_CreateFramebuffers(GLsizei n, GLuint *framebuffers)
3257{
3258 create_framebuffers(n, framebuffers, true);
3259}
3260
3261
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003262GLenum
3263_mesa_check_framebuffer_status(struct gl_context *ctx,
3264 struct gl_framebuffer *buffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00003265{
Brian Paule4b23562005-05-04 20:11:35 +00003266 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00003267
Brian Paul36ede892012-01-12 09:17:23 -07003268 if (_mesa_is_winsys_fbo(buffer)) {
Matt Turner8dd15e62013-07-26 16:36:19 -07003269 /* EGL_KHR_surfaceless_context allows the winsys FBO to be incomplete. */
3270 if (buffer != &IncompleteFramebuffer) {
3271 return GL_FRAMEBUFFER_COMPLETE_EXT;
3272 } else {
3273 return GL_FRAMEBUFFER_UNDEFINED;
3274 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00003275 }
3276
Brian Paul800e5532009-11-02 15:39:39 -07003277 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00003278
Brian Paul72966362009-01-21 16:28:38 -07003279 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
3280 _mesa_test_framebuffer_completeness(ctx, buffer);
3281 }
3282
Brian Paul0bffb112005-11-08 14:45:48 +00003283 return buffer->_Status;
Brian Paulddc82ee2005-02-05 19:56:45 +00003284}
3285
Brian Paul45bd5c42011-12-16 08:44:43 -07003286
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003287GLenum GLAPIENTRY
Samuel Pitoiset78d35102017-06-26 14:16:41 +02003288_mesa_CheckFramebufferStatus_no_error(GLenum target)
3289{
3290 GET_CURRENT_CONTEXT(ctx);
3291
3292 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3293 return _mesa_check_framebuffer_status(ctx, fb);
3294}
3295
3296
3297GLenum GLAPIENTRY
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003298_mesa_CheckFramebufferStatus(GLenum target)
3299{
3300 struct gl_framebuffer *fb;
3301 GET_CURRENT_CONTEXT(ctx);
3302
3303 if (MESA_VERBOSE & VERBOSE_API)
3304 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003305 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003306
3307 fb = get_framebuffer_target(ctx, target);
3308 if (!fb) {
3309 _mesa_error(ctx, GL_INVALID_ENUM,
3310 "glCheckFramebufferStatus(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003311 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003312 return 0;
3313 }
3314
3315 return _mesa_check_framebuffer_status(ctx, fb);
3316}
3317
3318
3319GLenum GLAPIENTRY
3320_mesa_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target)
3321{
3322 struct gl_framebuffer *fb;
3323 GET_CURRENT_CONTEXT(ctx);
3324
3325 /* Validate the target (for conformance's sake) and grab a reference to the
3326 * default framebuffer in case framebuffer = 0.
3327 * Section 9.4 Framebuffer Completeness of the OpenGL 4.5 core spec
3328 * (30.10.2014, PDF page 336) says:
3329 * "If framebuffer is zero, then the status of the default read or
3330 * draw framebuffer (as determined by target) is returned."
3331 */
3332 switch (target) {
3333 case GL_DRAW_FRAMEBUFFER:
3334 case GL_FRAMEBUFFER:
3335 fb = ctx->WinSysDrawBuffer;
3336 break;
3337 case GL_READ_FRAMEBUFFER:
3338 fb = ctx->WinSysReadBuffer;
3339 break;
3340 default:
3341 _mesa_error(ctx, GL_INVALID_ENUM,
3342 "glCheckNamedFramebufferStatus(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003343 _mesa_enum_to_string(target));
Laura Ekstrandf93f9592015-01-29 13:15:37 -08003344 return 0;
3345 }
3346
3347 if (framebuffer) {
3348 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
3349 "glCheckNamedFramebufferStatus");
3350 if (!fb)
3351 return 0;
3352 }
3353
3354 return _mesa_check_framebuffer_status(ctx, fb);
3355}
3356
3357
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003358GLenum GLAPIENTRY
3359_mesa_CheckNamedFramebufferStatusEXT(GLuint framebuffer, GLenum target)
3360{
3361 struct gl_framebuffer *fb;
3362 GET_CURRENT_CONTEXT(ctx);
3363
3364 switch (target) {
3365 case GL_DRAW_FRAMEBUFFER:
3366 case GL_FRAMEBUFFER:
3367 case GL_READ_FRAMEBUFFER:
3368 break;
3369 default:
3370 _mesa_error(ctx, GL_INVALID_ENUM,
3371 "glCheckNamedFramebufferStatusEXT(invalid target %s)",
3372 _mesa_enum_to_string(target));
3373 return 0;
3374 }
3375
3376 if (framebuffer == 0) {
3377 return _mesa_CheckNamedFramebufferStatus(0, target);
3378 }
3379
3380 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
3381 "glCheckNamedFramebufferStatusEXT");
3382 if (!fb)
3383 return 0;
3384
3385 return _mesa_check_framebuffer_status(ctx, fb);
3386}
3387
3388
Chad Versacebf8ad172011-11-10 10:19:20 -08003389/**
3390 * Replicate the src attachment point. Used by framebuffer_texture() when
3391 * the same texture is attached at GL_DEPTH_ATTACHMENT and
3392 * GL_STENCIL_ATTACHMENT.
3393 */
3394static void
3395reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
3396 gl_buffer_index dst,
3397 gl_buffer_index src)
3398{
3399 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
3400 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
Brian Paulddc82ee2005-02-05 19:56:45 +00003401
Chad Versacebf8ad172011-11-10 10:19:20 -08003402 assert(src_att->Texture != NULL);
Brian Paul45bd5c42011-12-16 08:44:43 -07003403 assert(src_att->Renderbuffer != NULL);
Chad Versacebf8ad172011-11-10 10:19:20 -08003404
3405 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
3406 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
3407 dst_att->Type = src_att->Type;
3408 dst_att->Complete = src_att->Complete;
3409 dst_att->TextureLevel = src_att->TextureLevel;
Nanley Chery63318d32016-11-15 16:42:23 -08003410 dst_att->CubeMapFace = src_att->CubeMapFace;
Chad Versacebf8ad172011-11-10 10:19:20 -08003411 dst_att->Zoffset = src_att->Zoffset;
Dave Airlie35859d52016-02-29 17:16:10 +10003412 dst_att->Layered = src_att->Layered;
Chad Versacebf8ad172011-11-10 10:19:20 -08003413}
Brian Paulddc82ee2005-02-05 19:56:45 +00003414
Brian Paul45bd5c42011-12-16 08:44:43 -07003415
Timothy Arceri304058a2017-05-05 16:25:11 +10003416static struct gl_texture_object *
3417get_texture_for_framebuffer(struct gl_context *ctx, GLuint texture)
3418{
3419 if (!texture)
3420 return NULL;
3421
3422 return _mesa_lookup_texture(ctx, texture);
3423}
3424
3425
Brian Paulddc82ee2005-02-05 19:56:45 +00003426/**
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003427 * Common code called by gl*FramebufferTexture*() to retrieve the correct
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003428 * texture object pointer.
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003429 *
3430 * \param texObj where the pointer to the texture object is returned. Note
3431 * that a successful call may return texObj = NULL.
3432 *
3433 * \return true if no errors, false if errors
Brian Paulddc82ee2005-02-05 19:56:45 +00003434 */
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003435static bool
Timothy Arceri304058a2017-05-05 16:25:11 +10003436get_texture_for_framebuffer_err(struct gl_context *ctx, GLuint texture,
3437 bool layered, const char *caller,
3438 struct gl_texture_object **texObj)
Brian Paulddc82ee2005-02-05 19:56:45 +00003439{
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003440 *texObj = NULL; /* This will get returned if texture = 0. */
Brian Paulea4fe662006-03-26 05:22:17 +00003441
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003442 if (!texture)
3443 return true;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003444
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003445 *texObj = _mesa_lookup_texture(ctx, texture);
3446 if (*texObj == NULL || (*texObj)->Target == 0) {
3447 /* Can't render to a non-existent texture object.
3448 *
3449 * The OpenGL 4.5 core spec (02.02.2015) in Section 9.2 Binding and
3450 * Managing Framebuffer Objects specifies a different error
3451 * depending upon the calling function (PDF pages 325-328).
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003452 * *FramebufferTexture (where layered = GL_TRUE) throws invalid
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003453 * value, while the other commands throw invalid operation (where
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003454 * layered = GL_FALSE).
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003455 */
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003456 const GLenum error = layered ? GL_INVALID_VALUE :
Laura Ekstranda9f73f72015-03-02 13:41:13 -08003457 GL_INVALID_OPERATION;
3458 _mesa_error(ctx, error,
3459 "%s(non-existent texture %u)", caller, texture);
3460 return false;
3461 }
3462
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003463 return true;
3464}
3465
3466
3467/**
3468 * Common code called by gl*FramebufferTexture() to verify the texture target
3469 * and decide whether or not the attachment should truly be considered
3470 * layered.
3471 *
3472 * \param layered true if attachment should be considered layered, false if
3473 * not
3474 *
3475 * \return true if no errors, false if errors
3476 */
3477static bool
3478check_layered_texture_target(struct gl_context *ctx, GLenum target,
3479 const char *caller, GLboolean *layered)
3480{
3481 *layered = GL_TRUE;
3482
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003483 switch (target) {
3484 case GL_TEXTURE_3D:
3485 case GL_TEXTURE_1D_ARRAY_EXT:
3486 case GL_TEXTURE_2D_ARRAY_EXT:
3487 case GL_TEXTURE_CUBE_MAP:
3488 case GL_TEXTURE_CUBE_MAP_ARRAY:
3489 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3490 return true;
3491 case GL_TEXTURE_1D:
3492 case GL_TEXTURE_2D:
3493 case GL_TEXTURE_RECTANGLE:
3494 case GL_TEXTURE_2D_MULTISAMPLE:
3495 /* These texture types are valid to pass to
3496 * glFramebufferTexture(), but since they aren't layered, it
3497 * is equivalent to calling glFramebufferTexture{1D,2D}().
3498 */
3499 *layered = GL_FALSE;
3500 return true;
3501 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003502
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003503 _mesa_error(ctx, GL_INVALID_OPERATION,
3504 "%s(invalid texture target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003505 _mesa_enum_to_string(target));
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003506 return false;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003507}
3508
3509
3510/**
3511 * Common code called by gl*FramebufferTextureLayer() to verify the texture
3512 * target.
3513 *
3514 * \return true if no errors, false if errors
3515 */
3516static bool
3517check_texture_target(struct gl_context *ctx, GLenum target,
3518 const char *caller)
3519{
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003520 /* We're being called by glFramebufferTextureLayer().
3521 * The only legal texture types for that function are 3D,
3522 * cube-map, and 1D/2D/cube-map array textures.
Ian Romanick832ea232015-05-20 17:19:29 -07003523 *
3524 * We don't need to check for GL_ARB_texture_cube_map_array because the
3525 * application wouldn't have been able to create a texture with a
3526 * GL_TEXTURE_CUBE_MAP_ARRAY target if the extension were not enabled.
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003527 */
3528 switch (target) {
3529 case GL_TEXTURE_3D:
3530 case GL_TEXTURE_1D_ARRAY:
3531 case GL_TEXTURE_2D_ARRAY:
3532 case GL_TEXTURE_CUBE_MAP_ARRAY:
3533 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3534 return true;
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003535 case GL_TEXTURE_CUBE_MAP:
Timothy Arceri781a7892018-08-29 12:40:12 +10003536 /* GL_TEXTURE_CUBE_MAP is only allowed by OpenGL 4.5 here, which
3537 * includes the DSA API.
3538 *
3539 * Because DSA is only enabled for GL 3.1+ and this can be called
3540 * from _mesa_FramebufferTextureLayer in compatibility profile,
3541 * we need to check the version.
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003542 */
Timothy Arceri781a7892018-08-29 12:40:12 +10003543 return _mesa_is_desktop_gl(ctx) && ctx->Version >= 31;
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003544 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003545
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003546 _mesa_error(ctx, GL_INVALID_OPERATION,
3547 "%s(invalid texture target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003548 _mesa_enum_to_string(target));
Laura Ekstrand80e9bf22015-03-02 16:52:55 -08003549 return false;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003550}
3551
3552
3553/**
3554 * Common code called by glFramebufferTexture*D() to verify the texture
3555 * target.
3556 *
3557 * \return true if no errors, false if errors
3558 */
3559static bool
3560check_textarget(struct gl_context *ctx, int dims, GLenum target,
3561 GLenum textarget, const char *caller)
3562{
3563 bool err = false;
3564
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003565 switch (textarget) {
3566 case GL_TEXTURE_1D:
3567 err = dims != 1;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003568 break;
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003569 case GL_TEXTURE_1D_ARRAY:
3570 err = dims != 1 || !ctx->Extensions.EXT_texture_array;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003571 break;
Kenneth Graunkeaecdb212016-10-03 16:37:25 -07003572 case GL_TEXTURE_2D:
3573 err = dims != 2;
3574 break;
3575 case GL_TEXTURE_2D_ARRAY:
3576 err = dims != 2 || !ctx->Extensions.EXT_texture_array ||
3577 (_mesa_is_gles(ctx) && ctx->Version < 30);
3578 break;
3579 case GL_TEXTURE_2D_MULTISAMPLE:
3580 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
3581 err = dims != 2 ||
3582 !ctx->Extensions.ARB_texture_multisample ||
3583 (_mesa_is_gles(ctx) && ctx->Version < 31);
3584 break;
3585 case GL_TEXTURE_RECTANGLE:
3586 err = dims != 2 || _mesa_is_gles(ctx) ||
3587 !ctx->Extensions.NV_texture_rectangle;
3588 break;
3589 case GL_TEXTURE_CUBE_MAP:
3590 case GL_TEXTURE_CUBE_MAP_ARRAY:
3591 err = true;
3592 break;
3593 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3594 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3595 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3596 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3597 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3598 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3599 err = dims != 2 || !ctx->Extensions.ARB_texture_cube_map;
3600 break;
3601 case GL_TEXTURE_3D:
3602 err = dims != 3;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003603 break;
3604 default:
Kenneth Graunkea40640f2016-10-03 16:37:26 -07003605 _mesa_error(ctx, GL_INVALID_ENUM,
3606 "%s(unknown textarget 0x%x)", caller, textarget);
3607 return false;
Laura Ekstranda602b212015-03-02 13:43:09 -08003608 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003609
Laura Ekstranda602b212015-03-02 13:43:09 -08003610 if (err) {
3611 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003612 "%s(invalid textarget %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003613 caller, _mesa_enum_to_string(textarget));
Laura Ekstranda602b212015-03-02 13:43:09 -08003614 return false;
3615 }
3616
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003617 /* Make sure textarget is consistent with the texture's type */
3618 err = (target == GL_TEXTURE_CUBE_MAP) ?
3619 !_mesa_is_cube_face(textarget): (target != textarget);
3620
3621 if (err) {
3622 _mesa_error(ctx, GL_INVALID_OPERATION,
3623 "%s(mismatched texture target)", caller);
3624 return false;
3625 }
3626
3627 return true;
3628}
3629
3630
3631/**
3632 * Common code called by gl*FramebufferTextureLayer() and
3633 * glFramebufferTexture3D() to validate the layer.
3634 *
3635 * \return true if no errors, false if errors
3636 */
3637static bool
3638check_layer(struct gl_context *ctx, GLenum target, GLint layer,
3639 const char *caller)
3640{
Laura Ekstranda602b212015-03-02 13:43:09 -08003641 /* Page 306 (page 328 of the PDF) of the OpenGL 4.5 (Core Profile)
3642 * spec says:
3643 *
3644 * "An INVALID_VALUE error is generated if texture is non-zero
3645 * and layer is negative."
3646 */
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003647 if (layer < 0) {
Brian Paul08ba4a12017-12-05 09:57:23 -07003648 _mesa_error(ctx, GL_INVALID_VALUE, "%s(layer %d < 0)", caller, layer);
Laura Ekstranda602b212015-03-02 13:43:09 -08003649 return false;
3650 }
3651
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003652 if (target == GL_TEXTURE_3D) {
Laura Ekstranda602b212015-03-02 13:43:09 -08003653 const GLuint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003654 if (layer >= maxSize) {
Fredrik Höglund8ba7ad82015-05-09 15:31:45 +02003655 _mesa_error(ctx, GL_INVALID_VALUE,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003656 "%s(invalid layer %u)", caller, layer);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003657 return false;
Fredrik Höglund8ba7ad82015-05-09 15:31:45 +02003658 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003659 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003660 else if ((target == GL_TEXTURE_1D_ARRAY) ||
3661 (target == GL_TEXTURE_2D_ARRAY) ||
3662 (target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
3663 (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
3664 if (layer >= ctx->Const.MaxArrayTextureLayers) {
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003665 _mesa_error(ctx, GL_INVALID_VALUE,
Laura Ekstranda602b212015-03-02 13:43:09 -08003666 "%s(layer %u >= GL_MAX_ARRAY_TEXTURE_LAYERS)",
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003667 caller, layer);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003668 return false;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003669 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003670 }
Fredrik Höglund03420ea2015-04-29 19:44:06 +02003671 else if (target == GL_TEXTURE_CUBE_MAP) {
3672 if (layer >= 6) {
3673 _mesa_error(ctx, GL_INVALID_VALUE,
3674 "%s(layer %u >= 6)", caller, layer);
3675 return false;
3676 }
3677 }
Laura Ekstranda602b212015-03-02 13:43:09 -08003678
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003679 return true;
3680}
3681
3682
3683/**
3684 * Common code called by all gl*FramebufferTexture*() entry points to verify
3685 * the level.
3686 *
3687 * \return true if no errors, false if errors
3688 */
3689static bool
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003690check_level(struct gl_context *ctx, struct gl_texture_object *texObj,
3691 GLenum target, GLint level, const char *caller)
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003692{
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003693 /* Section 9.2.8 of the OpenGL 4.6 specification says:
3694 *
3695 * "If texture refers to an immutable-format texture, level must be
3696 * greater than or equal to zero and smaller than the value of
3697 * TEXTURE_VIEW_NUM_LEVELS for texture."
3698 */
3699 const int max_levels = texObj->Immutable ? texObj->ImmutableLevels :
3700 _mesa_max_texture_levels(ctx, target);
3701
3702 if (level < 0 || level >= max_levels) {
Laura Ekstranda602b212015-03-02 13:43:09 -08003703 _mesa_error(ctx, GL_INVALID_VALUE,
3704 "%s(invalid level %d)", caller, level);
3705 return false;
3706 }
Brian Paulea4fe662006-03-26 05:22:17 +00003707
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003708 return true;
3709}
3710
3711
Timothy Arcerid90ced42017-05-05 16:46:03 +10003712struct gl_renderbuffer_attachment *
3713_mesa_get_and_validate_attachment(struct gl_context *ctx,
3714 struct gl_framebuffer *fb,
3715 GLenum attachment, const char *caller)
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003716{
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003717 /* The window-system framebuffer object is immutable */
3718 if (_mesa_is_winsys_fbo(fb)) {
3719 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(window-system framebuffer)",
3720 caller);
Timothy Arcerid90ced42017-05-05 16:46:03 +10003721 return NULL;
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003722 }
3723
3724 /* Not a hash lookup, so we can afford to get the attachment here. */
Timothy Arcerid90ced42017-05-05 16:46:03 +10003725 bool is_color_attachment;
3726 struct gl_renderbuffer_attachment *att =
3727 get_attachment(ctx, fb, attachment, &is_color_attachment);
Brian Paul3deaa012005-02-07 05:08:24 +00003728 if (att == NULL) {
Ilia Mirkin62b8f492017-01-24 00:26:29 -05003729 if (is_color_attachment) {
3730 _mesa_error(ctx, GL_INVALID_OPERATION,
3731 "%s(invalid color attachment %s)", caller,
3732 _mesa_enum_to_string(attachment));
3733 } else {
3734 _mesa_error(ctx, GL_INVALID_ENUM,
3735 "%s(invalid attachment %s)", caller,
3736 _mesa_enum_to_string(attachment));
3737 }
Timothy Arcerid90ced42017-05-05 16:46:03 +10003738 return NULL;
Brian Paul3deaa012005-02-07 05:08:24 +00003739 }
3740
Timothy Arcerid90ced42017-05-05 16:46:03 +10003741 return att;
3742}
3743
3744
3745void
3746_mesa_framebuffer_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
3747 GLenum attachment,
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003748 struct gl_renderbuffer_attachment *att,
Timothy Arcerid90ced42017-05-05 16:46:03 +10003749 struct gl_texture_object *texObj, GLenum textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003750 GLint level, GLsizei samples,
3751 GLuint layer, GLboolean layered)
Timothy Arcerid90ced42017-05-05 16:46:03 +10003752{
Brian Paul800e5532009-11-02 15:39:39 -07003753 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paul474f28e2005-10-08 14:41:17 +00003754
Timothy Arcerif0857fe2017-10-16 11:59:31 +11003755 simple_mtx_lock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +00003756 if (texObj) {
Chad Versacebf8ad172011-11-10 10:19:20 -08003757 if (attachment == GL_DEPTH_ATTACHMENT &&
Paul Berryb9819a02012-04-13 21:50:08 -07003758 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
3759 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
3760 _mesa_tex_target_to_face(textarget) ==
3761 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003762 samples == fb->Attachment[BUFFER_STENCIL].NumSamples &&
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003763 layer == fb->Attachment[BUFFER_STENCIL].Zoffset) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003764 /* The texture object is already attached to the stencil attachment
3765 * point. Don't create a new renderbuffer; just reuse the stencil
3766 * attachment's. This is required to prevent a GL error in
3767 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
3768 */
3769 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
3770 BUFFER_STENCIL);
Chad Versacebf8ad172011-11-10 10:19:20 -08003771 } else if (attachment == GL_STENCIL_ATTACHMENT &&
Martin Peres7bd8b482015-02-12 17:54:43 +02003772 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
Paul Berryb9819a02012-04-13 21:50:08 -07003773 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
3774 _mesa_tex_target_to_face(textarget) ==
3775 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003776 samples == fb->Attachment[BUFFER_DEPTH].NumSamples &&
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003777 layer == fb->Attachment[BUFFER_DEPTH].Zoffset) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003778 /* As above, but with depth and stencil transposed. */
3779 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
3780 BUFFER_DEPTH);
Chad Versacebf8ad172011-11-10 10:19:20 -08003781 } else {
Martin Peres7bd8b482015-02-12 17:54:43 +02003782 set_texture_attachment(ctx, fb, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003783 level, samples, layer, layered);
Laura Ekstrand8f78c682015-01-27 14:11:13 -08003784
Martin Peres7bd8b482015-02-12 17:54:43 +02003785 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
3786 /* Above we created a new renderbuffer and attached it to the
3787 * depth attachment point. Now attach it to the stencil attachment
3788 * point too.
3789 */
3790 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3791 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
3792 BUFFER_DEPTH);
3793 }
Chad Versacebf8ad172011-11-10 10:19:20 -08003794 }
3795
Brian Paul2897cee2009-01-29 09:20:18 -07003796 /* Set the render-to-texture flag. We'll check this flag in
3797 * glTexImage() and friends to determine if we need to revalidate
3798 * any FBOs that might be rendering into this texture.
3799 * This flag never gets cleared since it's non-trivial to determine
3800 * when all FBOs might be done rendering to this texture. That's OK
3801 * though since it's uncommon to render to a texture then repeatedly
3802 * call glTexImage() to change images in the texture.
3803 */
3804 texObj->_RenderToTexture = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +00003805 }
3806 else {
Brian Paul94512812014-02-01 08:58:43 -07003807 remove_attachment(ctx, att);
Chad Versacebf8ad172011-11-10 10:19:20 -08003808 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Martin Peres7bd8b482015-02-12 17:54:43 +02003809 assert(att == &fb->Attachment[BUFFER_DEPTH]);
3810 remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
Chad Versacebf8ad172011-11-10 10:19:20 -08003811 }
Brian Paul3deaa012005-02-07 05:08:24 +00003812 }
Brian Paul72966362009-01-21 16:28:38 -07003813
3814 invalidate_framebuffer(fb);
3815
Timothy Arcerif0857fe2017-10-16 11:59:31 +11003816 simple_mtx_unlock(&fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +00003817}
3818
3819
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003820static void
Timothy Arceri20cabc22017-05-08 10:59:15 +10003821framebuffer_texture_with_dims_no_error(GLenum target, GLenum attachment,
3822 GLenum textarget, GLuint texture,
3823 GLint level, GLint layer)
3824{
3825 GET_CURRENT_CONTEXT(ctx);
3826
3827 /* Get the framebuffer object */
3828 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
3829
3830 /* Get the texture object */
3831 struct gl_texture_object *texObj =
3832 get_texture_for_framebuffer(ctx, texture);
3833
3834 struct gl_renderbuffer_attachment *att =
3835 get_attachment(ctx, fb, attachment, NULL);
3836
3837 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003838 level, 0, layer, GL_FALSE);
Timothy Arceri20cabc22017-05-08 10:59:15 +10003839}
3840
3841
3842static void
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003843framebuffer_texture_with_dims(int dims, GLenum target, GLuint framebuffer,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003844 GLenum attachment, GLenum textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003845 GLuint texture, GLint level, GLsizei samples,
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003846 GLint layer, const char *caller, bool dsa)
Brian Paulea4fe662006-03-26 05:22:17 +00003847{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003848 GET_CURRENT_CONTEXT(ctx);
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003849 struct gl_framebuffer *fb;
3850 struct gl_texture_object *texObj;
Ian Romanickb0fe0d82007-05-15 13:42:25 -07003851
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003852 /* Get the framebuffer object */
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003853 if (dsa) {
3854 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer, caller);
3855 } else {
3856 fb = get_framebuffer_target(ctx, target);
3857 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003858 if (!fb) {
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003859 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07003860 _mesa_enum_to_string(target));
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003861 return;
3862 }
3863
3864 /* Get the texture object */
Timothy Arceri304058a2017-05-05 16:25:11 +10003865 if (!get_texture_for_framebuffer_err(ctx, texture, false, caller, &texObj))
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003866 return;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003867
3868 if (texObj) {
3869 if (!check_textarget(ctx, dims, texObj->Target, textarget, caller))
3870 return;
3871
3872 if ((dims == 3) && !check_layer(ctx, texObj->Target, layer, caller))
3873 return;
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003874
Kenneth Graunke37e128b2017-10-07 11:19:42 -07003875 if (!check_level(ctx, texObj, textarget, level, caller))
Marek Olšák04a78062016-05-27 21:40:19 +02003876 return;
3877 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003878
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10003879 struct gl_renderbuffer_attachment *att =
3880 _mesa_get_and_validate_attachment(ctx, fb, attachment, caller);
3881 if (!att)
3882 return;
3883
3884 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003885 level, samples, layer, GL_FALSE);
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003886}
3887
3888
3889void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003890_mesa_FramebufferTexture1D_no_error(GLenum target, GLenum attachment,
3891 GLenum textarget, GLuint texture,
3892 GLint level)
3893{
3894 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3895 texture, level, 0);
3896}
3897
3898
3899void GLAPIENTRY
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003900_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
3901 GLenum textarget, GLuint texture, GLint level)
3902{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003903 framebuffer_texture_with_dims(1, target, 0, attachment, textarget, texture,
3904 level, 0, 0, "glFramebufferTexture1D", false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003905}
3906
3907
Brian Paul1864c7d2005-02-08 03:46:37 +00003908void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003909_mesa_FramebufferTexture2D_no_error(GLenum target, GLenum attachment,
3910 GLenum textarget, GLuint texture,
3911 GLint level)
3912{
3913 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3914 texture, level, 0);
3915}
3916
3917
3918void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003919_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
Brian Paulc1377ed2014-03-22 10:31:58 -06003920 GLenum textarget, GLuint texture, GLint level)
Brian Paulddc82ee2005-02-05 19:56:45 +00003921{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003922 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3923 level, 0, 0, "glFramebufferTexture2D", false);
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08003924}
3925
3926
3927void GLAPIENTRY
3928_mesa_FramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment,
3929 GLenum textarget, GLuint texture,
3930 GLint level, GLsizei samples)
3931{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003932 framebuffer_texture_with_dims(2, target, 0, attachment, textarget, texture,
3933 level, samples, 0,
3934 "glFramebufferTexture2DMultisampleEXT",
3935 false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003936}
3937
3938
Brian Paul1864c7d2005-02-08 03:46:37 +00003939void GLAPIENTRY
Timothy Arceri276166c2017-05-08 11:10:58 +10003940_mesa_FramebufferTexture3D_no_error(GLenum target, GLenum attachment,
3941 GLenum textarget, GLuint texture,
3942 GLint level, GLint layer)
3943{
3944 framebuffer_texture_with_dims_no_error(target, attachment, textarget,
3945 texture, level, layer);
3946}
3947
3948
3949void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08003950_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
Brian Paulc1377ed2014-03-22 10:31:58 -06003951 GLenum textarget, GLuint texture,
Laura Ekstrand085c67d2015-03-02 16:48:59 -08003952 GLint level, GLint layer)
Brian Paulddc82ee2005-02-05 19:56:45 +00003953{
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02003954 framebuffer_texture_with_dims(3, target, 0, attachment, textarget, texture,
3955 level, 0, layer, "glFramebufferTexture3D", false);
Brian Paulddc82ee2005-02-05 19:56:45 +00003956}
3957
3958
Timothy Arceri01081c62017-05-10 11:22:47 +10003959static ALWAYS_INLINE void
Timothy Arcerif6229282017-05-10 11:44:54 +10003960frame_buffer_texture(GLuint framebuffer, GLenum target,
3961 GLenum attachment, GLuint texture,
3962 GLint level, GLint layer, const char *func,
3963 bool dsa, bool no_error, bool check_layered)
Ian Romanickbb372f12007-05-16 15:34:22 -07003964{
3965 GET_CURRENT_CONTEXT(ctx);
Timothy Arcerif6229282017-05-10 11:44:54 +10003966 GLboolean layered = GL_FALSE;
3967
3968 if (!no_error && check_layered) {
3969 if (!_mesa_has_geometry_shaders(ctx)) {
3970 _mesa_error(ctx, GL_INVALID_OPERATION,
3971 "unsupported function (%s) called", func);
3972 return;
3973 }
3974 }
Ian Romanickbb372f12007-05-16 15:34:22 -07003975
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003976 /* Get the framebuffer object */
Timothy Arceri01081c62017-05-10 11:22:47 +10003977 struct gl_framebuffer *fb;
Timothy Arcerif6198e92017-05-11 15:43:44 +10003978 if (no_error) {
3979 if (dsa) {
3980 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
3981 } else {
3982 fb = get_framebuffer_target(ctx, target);
3983 }
Timothy Arceri01081c62017-05-10 11:22:47 +10003984 } else {
Timothy Arcerif6198e92017-05-11 15:43:44 +10003985 if (dsa) {
3986 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer, func);
3987 if (!fb)
3988 return;
3989 } else {
3990 fb = get_framebuffer_target(ctx, target);
3991 if (!fb) {
3992 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)",
3993 func, _mesa_enum_to_string(target));
3994 return;
3995 }
Timothy Arceri01081c62017-05-10 11:22:47 +10003996 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08003997 }
3998
Timothy Arcerif6198e92017-05-11 15:43:44 +10003999 /* Get the texture object and framebuffer attachment*/
4000 struct gl_renderbuffer_attachment *att;
Timothy Arceri01081c62017-05-10 11:22:47 +10004001 struct gl_texture_object *texObj;
Timothy Arcerif6198e92017-05-11 15:43:44 +10004002 if (no_error) {
4003 texObj = get_texture_for_framebuffer(ctx, texture);
4004 att = get_attachment(ctx, fb, attachment, NULL);
4005 } else {
Timothy Arcerif6229282017-05-10 11:44:54 +10004006 if (!get_texture_for_framebuffer_err(ctx, texture, check_layered, func,
Timothy Arcerif6198e92017-05-11 15:43:44 +10004007 &texObj))
4008 return;
4009
4010 att = _mesa_get_and_validate_attachment(ctx, fb, attachment, func);
4011 if (!att)
4012 return;
4013 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08004014
Timothy Arceri01081c62017-05-10 11:22:47 +10004015 GLenum textarget = 0;
Laura Ekstrand085c67d2015-03-02 16:48:59 -08004016 if (texObj) {
Timothy Arcerif6229282017-05-10 11:44:54 +10004017 if (check_layered) {
4018 /* We do this regardless of no_error because this sets layered */
4019 if (!check_layered_texture_target(ctx, texObj->Target, func,
4020 &layered))
Timothy Arcerif6198e92017-05-11 15:43:44 +10004021 return;
Timothy Arcerif6229282017-05-10 11:44:54 +10004022 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08004023
Timothy Arcerif6229282017-05-10 11:44:54 +10004024 if (!no_error) {
4025 if (!check_layered) {
4026 if (!check_texture_target(ctx, texObj->Target, func))
4027 return;
4028
4029 if (!check_layer(ctx, texObj->Target, layer, func))
4030 return;
4031 }
Laura Ekstrand085c67d2015-03-02 16:48:59 -08004032
Kenneth Graunke37e128b2017-10-07 11:19:42 -07004033 if (!check_level(ctx, texObj, texObj->Target, level, func))
Timothy Arcerif6198e92017-05-11 15:43:44 +10004034 return;
4035 }
Fredrik Höglund03420ea2015-04-29 19:44:06 +02004036
Timothy Arcerif6229282017-05-10 11:44:54 +10004037 if (!check_layered && texObj->Target == GL_TEXTURE_CUBE_MAP) {
Fredrik Höglund03420ea2015-04-29 19:44:06 +02004038 assert(layer >= 0 && layer < 6);
4039 textarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
4040 layer = 0;
4041 }
Laura Ekstranda245e3b2015-01-27 16:11:52 -08004042 }
4043
Timothy Arceri69ca1ef2017-05-05 17:00:34 +10004044 _mesa_framebuffer_texture(ctx, fb, attachment, att, texObj, textarget,
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08004045 level, 0, layer, layered);
Ian Romanickbb372f12007-05-16 15:34:22 -07004046}
4047
Timothy Arcerie75e8d62017-05-08 11:24:07 +10004048void GLAPIENTRY
4049_mesa_FramebufferTextureLayer_no_error(GLenum target, GLenum attachment,
4050 GLuint texture, GLint level,
4051 GLint layer)
4052{
Timothy Arcerif6229282017-05-10 11:44:54 +10004053 frame_buffer_texture(0, target, attachment, texture, level, layer,
4054 "glFramebufferTextureLayer", false, true, false);
Timothy Arcerie75e8d62017-05-08 11:24:07 +10004055}
4056
Ian Romanickbb372f12007-05-16 15:34:22 -07004057
4058void GLAPIENTRY
Timothy Arceri01081c62017-05-10 11:22:47 +10004059_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
4060 GLuint texture, GLint level, GLint layer)
4061{
Timothy Arcerif6229282017-05-10 11:44:54 +10004062 frame_buffer_texture(0, target, attachment, texture, level, layer,
4063 "glFramebufferTextureLayer", false, false, false);
Timothy Arceri01081c62017-05-10 11:22:47 +10004064}
4065
4066
4067void GLAPIENTRY
Timothy Arceri4e125c42017-05-08 11:37:33 +10004068_mesa_NamedFramebufferTextureLayer_no_error(GLuint framebuffer,
4069 GLenum attachment,
4070 GLuint texture, GLint level,
4071 GLint layer)
4072{
Timothy Arcerif6229282017-05-10 11:44:54 +10004073 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
4074 "glNamedFramebufferTextureLayer", true, true, false);
Timothy Arceri4e125c42017-05-08 11:37:33 +10004075}
4076
4077
4078void GLAPIENTRY
Laura Ekstrandd78c8312015-01-28 13:19:57 -08004079_mesa_NamedFramebufferTextureLayer(GLuint framebuffer, GLenum attachment,
4080 GLuint texture, GLint level, GLint layer)
4081{
Timothy Arcerif6229282017-05-10 11:44:54 +10004082 frame_buffer_texture(framebuffer, 0, attachment, texture, level, layer,
4083 "glNamedFramebufferTextureLayer", true, false, false);
Laura Ekstrandd78c8312015-01-28 13:19:57 -08004084}
4085
4086
4087void GLAPIENTRY
Timothy Arceri4e8aa4b2017-05-08 11:52:45 +10004088_mesa_FramebufferTexture_no_error(GLenum target, GLenum attachment,
4089 GLuint texture, GLint level)
4090{
4091 frame_buffer_texture(0, target, attachment, texture, level, 0,
4092 "glFramebufferTexture", false, true, true);
4093}
4094
4095
4096void GLAPIENTRY
Jordan Justen02f2bce2013-04-18 10:46:12 -07004097_mesa_FramebufferTexture(GLenum target, GLenum attachment,
4098 GLuint texture, GLint level)
4099{
Timothy Arcerif6229282017-05-10 11:44:54 +10004100 frame_buffer_texture(0, target, attachment, texture, level, 0,
4101 "glFramebufferTexture", false, false, true);
Jordan Justen02f2bce2013-04-18 10:46:12 -07004102}
4103
Timothy Arceri3336d242017-05-08 12:01:33 +10004104void GLAPIENTRY
4105_mesa_NamedFramebufferTexture_no_error(GLuint framebuffer, GLenum attachment,
4106 GLuint texture, GLint level)
4107{
4108 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4109 "glNamedFramebufferTexture", true, true, true);
4110}
4111
Jordan Justen02f2bce2013-04-18 10:46:12 -07004112
Laura Ekstrandd78c8312015-01-28 13:19:57 -08004113void GLAPIENTRY
4114_mesa_NamedFramebufferTexture(GLuint framebuffer, GLenum attachment,
4115 GLuint texture, GLint level)
4116{
Timothy Arcerif6229282017-05-10 11:44:54 +10004117 frame_buffer_texture(framebuffer, 0, attachment, texture, level, 0,
4118 "glNamedFramebufferTexture", true, false, true);
Laura Ekstrandd78c8312015-01-28 13:19:57 -08004119}
4120
4121
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004122void GLAPIENTRY
4123_mesa_NamedFramebufferTexture1DEXT(GLuint framebuffer, GLenum attachment,
4124 GLenum textarget, GLuint texture, GLint level)
4125{
4126 framebuffer_texture_with_dims(1, GL_FRAMEBUFFER, framebuffer, attachment,
4127 textarget, texture, level, 0, 0,
4128 "glNamedFramebufferTexture1DEXT", true);
4129}
4130
4131
4132void GLAPIENTRY
4133_mesa_NamedFramebufferTexture2DEXT(GLuint framebuffer, GLenum attachment,
4134 GLenum textarget, GLuint texture, GLint level)
4135{
4136 framebuffer_texture_with_dims(2, GL_FRAMEBUFFER, framebuffer, attachment,
4137 textarget, texture, level, 0, 0,
4138 "glNamedFramebufferTexture2DEXT", true);
4139}
4140
4141
4142void GLAPIENTRY
4143_mesa_NamedFramebufferTexture3DEXT(GLuint framebuffer, GLenum attachment,
4144 GLenum textarget, GLuint texture,
4145 GLint level, GLint zoffset)
4146{
4147 framebuffer_texture_with_dims(3, GL_FRAMEBUFFER, framebuffer, attachment,
4148 textarget, texture, level, 0, zoffset,
4149 "glNamedFramebufferTexture3DEXT", true);
4150}
4151
4152
Laura Ekstranda29318b2015-02-27 17:27:30 -08004153void
4154_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
4155 struct gl_framebuffer *fb,
4156 GLenum attachment,
Ian Romanick9ae42ab2015-11-11 16:30:41 -08004157 struct gl_renderbuffer *rb)
4158{
4159 assert(!_mesa_is_winsys_fbo(fb));
4160
4161 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
4162
4163 assert(ctx->Driver.FramebufferRenderbuffer);
4164 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
4165
4166 /* Some subsequent GL commands may depend on the framebuffer's visual
4167 * after the binding is updated. Update visual info now.
4168 */
4169 _mesa_update_framebuffer_visual(ctx, fb);
4170}
4171
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004172static ALWAYS_INLINE void
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004173framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
4174 GLenum attachment, GLenum renderbuffertarget,
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004175 GLuint renderbuffer, const char *func, bool no_error)
Brian Paulddc82ee2005-02-05 19:56:45 +00004176{
Brian Paul2c6f9112005-02-24 05:47:06 +00004177 struct gl_renderbuffer_attachment *att;
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004178 struct gl_renderbuffer *rb;
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004179 bool is_color_attachment;
Brian Paul3deaa012005-02-07 05:08:24 +00004180
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004181 if (!no_error && renderbuffertarget != GL_RENDERBUFFER) {
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004182 _mesa_error(ctx, GL_INVALID_ENUM,
4183 "%s(renderbuffertarget is not GL_RENDERBUFFER)", func);
4184 return;
4185 }
4186
4187 if (renderbuffer) {
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004188 if (!no_error) {
4189 rb = _mesa_lookup_renderbuffer_err(ctx, renderbuffer, func);
4190 if (!rb)
4191 return;
4192 } else {
4193 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
4194 }
Samuel Pitoiset1ebe4302017-07-20 11:53:03 +02004195 } else {
4196 /* remove renderbuffer attachment */
4197 rb = NULL;
4198 }
4199
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004200 if (!no_error) {
4201 if (_mesa_is_winsys_fbo(fb)) {
4202 /* Can't attach new renderbuffers to a window system framebuffer */
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004203 _mesa_error(ctx, GL_INVALID_OPERATION,
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004204 "%s(window-system framebuffer)", func);
4205 return;
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004206 }
4207
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004208 att = get_attachment(ctx, fb, attachment, &is_color_attachment);
4209 if (att == NULL) {
4210 /*
4211 * From OpenGL 4.5 spec, section 9.2.7 "Attaching Renderbuffer Images
4212 * to a Framebuffer":
4213 *
4214 * "An INVALID_OPERATION error is generated if attachment is
4215 * COLOR_- ATTACHMENTm where m is greater than or equal to the
4216 * value of MAX_COLOR_- ATTACHMENTS ."
4217 *
4218 * If we are at this point, is because the attachment is not valid, so
4219 * if is_color_attachment is true, is because of the previous reason.
4220 */
4221 if (is_color_attachment) {
4222 _mesa_error(ctx, GL_INVALID_OPERATION,
4223 "%s(invalid color attachment %s)", func,
4224 _mesa_enum_to_string(attachment));
4225 } else {
4226 _mesa_error(ctx, GL_INVALID_ENUM,
4227 "%s(invalid attachment %s)", func,
4228 _mesa_enum_to_string(attachment));
4229 }
Brian Paulddc82ee2005-02-05 19:56:45 +00004230
Brian Paul30590072009-01-21 11:06:11 -07004231 return;
4232 }
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004233
4234 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
4235 rb && rb->Format != MESA_FORMAT_NONE) {
4236 /* make sure the renderbuffer is a depth/stencil format */
4237 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
4238 if (baseFormat != GL_DEPTH_STENCIL) {
4239 _mesa_error(ctx, GL_INVALID_OPERATION,
4240 "%s(renderbuffer is not DEPTH_STENCIL format)", func);
4241 return;
4242 }
4243 }
Brian Paul30590072009-01-21 11:06:11 -07004244 }
4245
Ian Romanick9ae42ab2015-11-11 16:30:41 -08004246 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
Brian Paulddc82ee2005-02-05 19:56:45 +00004247}
4248
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004249static void
4250framebuffer_renderbuffer_error(struct gl_context *ctx,
4251 struct gl_framebuffer *fb, GLenum attachment,
4252 GLenum renderbuffertarget,
4253 GLuint renderbuffer, const char *func)
4254{
4255 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4256 renderbuffer, func, false);
4257}
4258
Samuel Pitoiset0a20e432017-07-19 12:28:21 +02004259static void
4260framebuffer_renderbuffer_no_error(struct gl_context *ctx,
4261 struct gl_framebuffer *fb, GLenum attachment,
4262 GLenum renderbuffertarget,
4263 GLuint renderbuffer, const char *func)
4264{
4265 framebuffer_renderbuffer(ctx, fb, attachment, renderbuffertarget,
4266 renderbuffer, func, true);
4267}
4268
4269void GLAPIENTRY
4270_mesa_FramebufferRenderbuffer_no_error(GLenum target, GLenum attachment,
4271 GLenum renderbuffertarget,
4272 GLuint renderbuffer)
4273{
4274 GET_CURRENT_CONTEXT(ctx);
4275
4276 struct gl_framebuffer *fb = get_framebuffer_target(ctx, target);
4277 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4278 renderbuffer, "glFramebufferRenderbuffer");
4279}
4280
Brian Paul1864c7d2005-02-08 03:46:37 +00004281void GLAPIENTRY
Laura Ekstranda29318b2015-02-27 17:27:30 -08004282_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
4283 GLenum renderbuffertarget,
4284 GLuint renderbuffer)
4285{
4286 struct gl_framebuffer *fb;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004287 GET_CURRENT_CONTEXT(ctx);
4288
4289 fb = get_framebuffer_target(ctx, target);
4290 if (!fb) {
4291 _mesa_error(ctx, GL_INVALID_ENUM,
4292 "glFramebufferRenderbuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004293 _mesa_enum_to_string(target));
Laura Ekstranda29318b2015-02-27 17:27:30 -08004294 return;
4295 }
4296
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004297 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4298 renderbuffer, "glFramebufferRenderbuffer");
Laura Ekstranda29318b2015-02-27 17:27:30 -08004299}
4300
Samuel Pitoiset7bc50df2017-07-19 12:32:42 +02004301void GLAPIENTRY
4302_mesa_NamedFramebufferRenderbuffer_no_error(GLuint framebuffer,
4303 GLenum attachment,
4304 GLenum renderbuffertarget,
4305 GLuint renderbuffer)
4306{
4307 GET_CURRENT_CONTEXT(ctx);
4308
4309 struct gl_framebuffer *fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4310 framebuffer_renderbuffer_no_error(ctx, fb, attachment, renderbuffertarget,
4311 renderbuffer,
4312 "glNamedFramebufferRenderbuffer");
4313}
Laura Ekstranda29318b2015-02-27 17:27:30 -08004314
4315void GLAPIENTRY
4316_mesa_NamedFramebufferRenderbuffer(GLuint framebuffer, GLenum attachment,
4317 GLenum renderbuffertarget,
4318 GLuint renderbuffer)
4319{
4320 struct gl_framebuffer *fb;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004321 GET_CURRENT_CONTEXT(ctx);
4322
4323 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4324 "glNamedFramebufferRenderbuffer");
Fredrik Höglund5a55f682015-05-16 19:43:39 +02004325 if (!fb)
4326 return;
Laura Ekstranda29318b2015-02-27 17:27:30 -08004327
Samuel Pitoiset55188f72017-07-19 12:24:31 +02004328 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4329 renderbuffer,
4330 "glNamedFramebufferRenderbuffer");
Laura Ekstranda29318b2015-02-27 17:27:30 -08004331}
4332
4333
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004334void GLAPIENTRY
4335_mesa_NamedFramebufferRenderbufferEXT(GLuint framebuffer, GLenum attachment,
4336 GLenum renderbuffertarget,
4337 GLuint renderbuffer)
4338{
4339 struct gl_framebuffer *fb;
4340 GET_CURRENT_CONTEXT(ctx);
4341
4342 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4343 "glNamedFramebufferRenderbufferEXT");
4344 if (!fb)
4345 return;
4346
4347 framebuffer_renderbuffer_error(ctx, fb, attachment, renderbuffertarget,
4348 renderbuffer,
4349 "glNamedFramebufferRenderbuffer");
4350}
4351
4352
Timothy Arceri8b006302017-05-05 15:21:22 +10004353static void
4354get_framebuffer_attachment_parameter(struct gl_context *ctx,
4355 struct gl_framebuffer *buffer,
4356 GLenum attachment, GLenum pname,
4357 GLint *params, const char *caller)
Brian Paulddc82ee2005-02-05 19:56:45 +00004358{
Brian Paul2c6f9112005-02-24 05:47:06 +00004359 const struct gl_renderbuffer_attachment *att;
Robert Foss88becf72017-03-01 19:14:39 -05004360 bool is_color_attachment = false;
Marek Olšák000896c2011-07-19 03:05:07 +02004361 GLenum err;
Brian Paulddc82ee2005-02-05 19:56:45 +00004362
Kenneth Graunke19f13b22016-03-07 16:43:35 -08004363 /* The error code for an attachment type of GL_NONE differs between APIs.
4364 *
4365 * From the ES 2.0.25 specification, page 127:
4366 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4367 * querying any other pname will generate INVALID_ENUM."
4368 *
4369 * From the OpenGL 3.0 specification, page 337, or identically,
4370 * the OpenGL ES 3.0.4 specification, page 240:
4371 *
4372 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no
4373 * framebuffer is bound to target. In this case querying pname
4374 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero, and all other
4375 * queries will generate an INVALID_OPERATION error."
4376 */
4377 err = ctx->API == API_OPENGLES2 && ctx->Version < 30 ?
4378 GL_INVALID_ENUM : GL_INVALID_OPERATION;
Marek Olšák000896c2011-07-19 03:05:07 +02004379
Brian Paul36ede892012-01-12 09:17:23 -07004380 if (_mesa_is_winsys_fbo(buffer)) {
Ian Romanickda2e41c2011-10-03 12:04:09 -07004381 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
4382 * says:
4383 *
4384 * "If the framebuffer currently bound to target is zero, then
4385 * INVALID_OPERATION is generated."
4386 *
4387 * The EXT_framebuffer_object spec has the same wording, and the
4388 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
4389 * spec.
4390 */
Brian Paulc1377ed2014-03-22 10:31:58 -06004391 if ((!_mesa_is_desktop_gl(ctx) ||
4392 !ctx->Extensions.ARB_framebuffer_object)
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004393 && !_mesa_is_gles3(ctx)) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004394 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004395 "%s(window-system framebuffer)", caller);
Martin Peres7bd8b482015-02-12 17:54:43 +02004396 return;
Ian Romanickda2e41c2011-10-03 12:04:09 -07004397 }
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004398
4399 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
4400 attachment != GL_DEPTH && attachment != GL_STENCIL) {
Samuel Iglesias Gonsalvez284bd1e2015-01-16 16:00:13 +01004401 _mesa_error(ctx, GL_INVALID_ENUM,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004402 "%s(invalid attachment %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004403 _mesa_enum_to_string(attachment));
Anuj Phogat2f2801f2012-12-11 20:08:13 -08004404 return;
4405 }
Kenneth Graunke789e0962016-03-08 23:59:37 -08004406
4407 /* The specs are not clear about how to handle
4408 * GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME with the default framebuffer,
4409 * but dEQP-GLES3 expects an INVALID_ENUM error. This has also been
4410 * discussed in:
4411 *
4412 * https://cvs.khronos.org/bugzilla/show_bug.cgi?id=12928#c1
4413 * and https://bugs.freedesktop.org/show_bug.cgi?id=31947
4414 */
4415 if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
4416 _mesa_error(ctx, GL_INVALID_ENUM,
4417 "%s(requesting GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME "
4418 "when GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is "
4419 "GL_FRAMEBUFFER_DEFAULT is not allowed)", caller);
4420 return;
4421 }
4422
Brian Paul61ec2052010-06-22 08:37:44 -06004423 /* the default / window-system FBO */
Timothy Arcerie6187612017-05-05 15:02:20 +10004424 att = get_fb0_attachment(ctx, buffer, attachment);
Brian Paul61ec2052010-06-22 08:37:44 -06004425 }
4426 else {
4427 /* user-created framebuffer FBO */
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004428 att = get_attachment(ctx, buffer, attachment, &is_color_attachment);
Brian Paul61ec2052010-06-22 08:37:44 -06004429 }
4430
Brian Paul3deaa012005-02-07 05:08:24 +00004431 if (att == NULL) {
Alejandro Piñeiro84e3e122017-01-12 16:09:17 -02004432 /*
4433 * From OpenGL 4.5 spec, section 9.2.3 "Framebuffer Object Queries":
4434 *
4435 * "An INVALID_OPERATION error is generated if a framebuffer object
4436 * is bound to target and attachment is COLOR_ATTACHMENTm where m is
4437 * greater than or equal to the value of MAX_COLOR_ATTACHMENTS."
4438 *
4439 * If we are at this point, is because the attachment is not valid, so
4440 * if is_color_attachment is true, is because of the previous reason.
4441 */
4442 if (is_color_attachment) {
4443 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid color attachment %s)",
4444 caller, _mesa_enum_to_string(attachment));
4445 } else {
4446 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", caller,
4447 _mesa_enum_to_string(attachment));
4448 }
Brian Paulddc82ee2005-02-05 19:56:45 +00004449 return;
4450 }
4451
Brian Paul30590072009-01-21 11:06:11 -07004452 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Brian Paule9592742014-04-21 13:24:25 -06004453 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
Anuj Phogatbd1880d2014-03-11 17:04:11 -07004454 if (pname == GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) {
4455 /* This behavior is first specified in OpenGL 4.4 specification.
4456 *
4457 * From the OpenGL 4.4 spec page 275:
4458 * "This query cannot be performed for a combined depth+stencil
4459 * attachment, since it does not have a single format."
4460 */
4461 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004462 "%s(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE"
4463 " is invalid for depth+stencil attachment)", caller);
Anuj Phogatbd1880d2014-03-11 17:04:11 -07004464 return;
4465 }
Brian Paul30590072009-01-21 11:06:11 -07004466 /* the depth and stencil attachments must point to the same buffer */
Alejandro Piñeiroc6eb3ae2017-01-12 16:03:00 -02004467 depthAtt = get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT, NULL);
4468 stencilAtt = get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT, NULL);
Brian Paul30590072009-01-21 11:06:11 -07004469 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
4470 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004471 "%s(DEPTH/STENCIL attachments differ)", caller);
Brian Paul30590072009-01-21 11:06:11 -07004472 return;
4473 }
4474 }
4475
Brian Paul800e5532009-11-02 15:39:39 -07004476 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00004477
Brian Paulddc82ee2005-02-05 19:56:45 +00004478 switch (pname) {
4479 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
Iago Toral Quirogacf439952015-02-24 19:02:56 +01004480 /* From the OpenGL spec, 9.2. Binding and Managing Framebuffer Objects:
4481 *
4482 * "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, then
4483 * either no framebuffer is bound to target; or the default framebuffer
4484 * is bound, attachment is DEPTH or STENCIL, and the number of depth or
4485 * stencil bits, respectively, is zero."
Alejandro Piñeiro90596142017-01-13 11:39:24 -02004486 *
4487 * Note that we don't need explicit checks on DEPTH and STENCIL, because
4488 * on the case the spec is pointing, att->Type is already NONE, so we
4489 * just need to check att->Type.
Iago Toral Quirogacf439952015-02-24 19:02:56 +01004490 */
Alejandro Piñeiro90596142017-01-13 11:39:24 -02004491 *params = (_mesa_is_winsys_fbo(buffer) && att->Type != GL_NONE) ?
4492 GL_FRAMEBUFFER_DEFAULT : att->Type;
Brian Paul3deaa012005-02-07 05:08:24 +00004493 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004494 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004495 if (att->Type == GL_RENDERBUFFER_EXT) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004496 *params = att->Renderbuffer->Name;
Brian Paul3deaa012005-02-07 05:08:24 +00004497 }
4498 else if (att->Type == GL_TEXTURE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004499 *params = att->Texture->Name;
Brian Paul3deaa012005-02-07 05:08:24 +00004500 }
4501 else {
Brian Paul20cf1852010-12-03 08:23:31 -07004502 assert(att->Type == GL_NONE);
Ian Romanick0cdaa472012-07-27 07:47:28 -07004503 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
Marek Olšák000896c2011-07-19 03:05:07 +02004504 *params = 0;
4505 } else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004506 goto invalid_pname_enum;
Marek Olšák000896c2011-07-19 03:05:07 +02004507 }
Brian Paul3deaa012005-02-07 05:08:24 +00004508 }
4509 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004510 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004511 if (att->Type == GL_TEXTURE) {
Martin Peres7bd8b482015-02-12 17:54:43 +02004512 *params = att->TextureLevel;
Brian Paul3deaa012005-02-07 05:08:24 +00004513 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004514 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004515 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004516 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004517 }
Brian Paul3deaa012005-02-07 05:08:24 +00004518 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004519 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004520 }
4521 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004522 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00004523 if (att->Type == GL_TEXTURE) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06004524 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
4525 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
4526 }
4527 else {
4528 *params = 0;
4529 }
Brian Paul3deaa012005-02-07 05:08:24 +00004530 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004531 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004532 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004533 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004534 }
Brian Paul3deaa012005-02-07 05:08:24 +00004535 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004536 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004537 }
4538 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004539 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
Ian Romanick0cdaa472012-07-27 07:47:28 -07004540 if (ctx->API == API_OPENGLES) {
4541 goto invalid_pname_enum;
4542 } else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004543 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004544 _mesa_enum_to_string(pname));
Ian Romanick0cdaa472012-07-27 07:47:28 -07004545 } else if (att->Type == GL_TEXTURE) {
Samuel Iglesias Gonsalvez8e49a3e2014-12-11 23:34:13 +01004546 if (att->Texture && (att->Texture->Target == GL_TEXTURE_3D ||
4547 att->Texture->Target == GL_TEXTURE_2D_ARRAY)) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06004548 *params = att->Zoffset;
4549 }
4550 else {
4551 *params = 0;
4552 }
Brian Paul3deaa012005-02-07 05:08:24 +00004553 }
4554 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07004555 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00004556 }
4557 return;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004558 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Brian Paulc1377ed2014-03-22 10:31:58 -06004559 if ((!_mesa_is_desktop_gl(ctx) ||
4560 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004561 && !_mesa_is_gles3(ctx)) {
4562 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004563 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004564 else if (att->Type == GL_NONE) {
Kenneth Graunke713cd232016-12-09 16:16:53 -08004565 if (_mesa_is_winsys_fbo(buffer) &&
4566 (attachment == GL_DEPTH || attachment == GL_STENCIL)) {
4567 *params = GL_LINEAR;
4568 } else {
4569 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4570 _mesa_enum_to_string(pname));
4571 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004572 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004573 else {
Gert Wollny76c3f6f2018-11-14 10:58:40 +01004574 if (ctx->Extensions.EXT_sRGB) {
Eric Anholt4d231572019-07-01 15:43:19 -07004575 *params = (_mesa_is_format_srgb(att->Renderbuffer->Format) ?
4576 GL_SRGB : GL_LINEAR);
Marek Olšák81ae8c62011-01-23 13:26:43 +01004577 }
4578 else {
4579 /* According to ARB_framebuffer_sRGB, we should return LINEAR
4580 * if the sRGB conversion is unsupported. */
4581 *params = GL_LINEAR;
4582 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004583 }
4584 return;
4585 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Brian Paulc1377ed2014-03-22 10:31:58 -06004586 if ((ctx->API != API_OPENGL_COMPAT ||
4587 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004588 && ctx->API != API_OPENGL_CORE
4589 && !_mesa_is_gles3(ctx)) {
4590 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004591 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02004592 else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004593 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004594 _mesa_enum_to_string(pname));
Marek Olšákb9e9df72011-05-31 20:36:07 +02004595 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004596 else {
Mark Mueller71fe9432014-01-04 14:11:43 -08004597 mesa_format format = att->Renderbuffer->Format;
Ian Romanickd7475c72013-01-18 17:25:57 -08004598
4599 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
4600 * 3.0.1 spec says:
4601 *
4602 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
4603 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
4604 * generate an INVALID_OPERATION error.
4605 */
Brian Paulc1377ed2014-03-22 10:31:58 -06004606 if (_mesa_is_gles3(ctx) &&
4607 attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
Ian Romanickd7475c72013-01-18 17:25:57 -08004608 _mesa_error(ctx, GL_INVALID_OPERATION,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004609 "%s(cannot query "
Ian Romanickd7475c72013-01-18 17:25:57 -08004610 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004611 "GL_DEPTH_STENCIL_ATTACHMENT)", caller);
Ian Romanickd7475c72013-01-18 17:25:57 -08004612 return;
4613 }
4614
Mark Mueller50a01d22014-01-20 19:08:54 -08004615 if (format == MESA_FORMAT_S_UINT8) {
Brian Paul45e76d22009-10-08 20:27:27 -06004616 /* special cases */
4617 *params = GL_INDEX;
4618 }
Mark Muellereeed49f2014-01-26 15:12:56 -08004619 else if (format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) {
Marek Olšák11652802011-06-01 15:48:51 +02004620 /* depends on the attachment parameter */
4621 if (attachment == GL_STENCIL_ATTACHMENT) {
4622 *params = GL_INDEX;
4623 }
4624 else {
4625 *params = GL_FLOAT;
4626 }
4627 }
Brian Paul45e76d22009-10-08 20:27:27 -06004628 else {
4629 *params = _mesa_get_format_datatype(format);
4630 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004631 }
4632 return;
4633 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004634 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004635 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004636 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004637 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07004638 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Brian Paulc1377ed2014-03-22 10:31:58 -06004639 if ((!_mesa_is_desktop_gl(ctx) ||
4640 !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07004641 && !_mesa_is_gles3(ctx)) {
4642 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07004643 }
Brian Paul45e76d22009-10-08 20:27:27 -06004644 else if (att->Texture) {
4645 const struct gl_texture_image *texImage =
Brian Paulf262ed62015-01-02 16:56:12 -07004646 _mesa_select_tex_image(att->Texture, att->Texture->Target,
Brian Paul45e76d22009-10-08 20:27:27 -06004647 att->TextureLevel);
4648 if (texImage) {
4649 *params = get_component_bits(pname, texImage->_BaseFormat,
4650 texImage->TexFormat);
4651 }
4652 else {
4653 *params = 0;
4654 }
4655 }
4656 else if (att->Renderbuffer) {
4657 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
4658 att->Renderbuffer->Format);
4659 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07004660 else {
Timothy Arceri786b9ad2017-05-05 15:39:15 +10004661 assert(att->Type == GL_NONE);
4662 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4663 _mesa_enum_to_string(pname));
Brian Paul1bc59bf2009-01-22 15:07:34 -07004664 }
4665 return;
Paul Berryec79c052013-11-19 21:17:19 -08004666 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED:
4667 if (!_mesa_has_geometry_shaders(ctx)) {
4668 goto invalid_pname_enum;
4669 } else if (att->Type == GL_TEXTURE) {
4670 *params = att->Layered;
4671 } else if (att->Type == GL_NONE) {
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004672 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004673 _mesa_enum_to_string(pname));
Paul Berryec79c052013-11-19 21:17:19 -08004674 } else {
4675 goto invalid_pname_enum;
4676 }
4677 return;
Kristian H. Kristensen1b331ae2018-11-05 21:19:21 -08004678 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4679 if (!ctx->Extensions.EXT_multisampled_render_to_texture) {
4680 goto invalid_pname_enum;
4681 } else if (att->Type == GL_TEXTURE) {
4682 *params = att->NumSamples;
4683 } else if (att->Type == GL_NONE) {
4684 _mesa_error(ctx, err, "%s(invalid pname %s)", caller,
4685 _mesa_enum_to_string(pname));
4686 } else {
4687 goto invalid_pname_enum;
4688 }
4689 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004690 default:
Ian Romanick0cdaa472012-07-27 07:47:28 -07004691 goto invalid_pname_enum;
Brian Paulddc82ee2005-02-05 19:56:45 +00004692 }
Ian Romanick0cdaa472012-07-27 07:47:28 -07004693
4694 return;
4695
4696invalid_pname_enum:
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004697 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname %s)", caller,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004698 _mesa_enum_to_string(pname));
Ian Romanick0cdaa472012-07-27 07:47:28 -07004699 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00004700}
4701
4702
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004703void GLAPIENTRY
4704_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
4705 GLenum pname, GLint *params)
4706{
4707 GET_CURRENT_CONTEXT(ctx);
4708 struct gl_framebuffer *buffer;
4709
4710 buffer = get_framebuffer_target(ctx, target);
4711 if (!buffer) {
4712 _mesa_error(ctx, GL_INVALID_ENUM,
4713 "glGetFramebufferAttachmentParameteriv(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07004714 _mesa_enum_to_string(target));
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004715 return;
4716 }
4717
Timothy Arceri8b006302017-05-05 15:21:22 +10004718 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4719 params,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004720 "glGetFramebufferAttachmentParameteriv");
4721}
4722
4723
4724void GLAPIENTRY
4725_mesa_GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer,
4726 GLenum attachment,
4727 GLenum pname, GLint *params)
4728{
4729 GET_CURRENT_CONTEXT(ctx);
4730 struct gl_framebuffer *buffer;
4731
4732 if (framebuffer) {
4733 buffer = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4734 "glGetNamedFramebufferAttachmentParameteriv");
4735 if (!buffer)
4736 return;
4737 }
4738 else {
4739 /*
4740 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4741 * 4.5 core spec (30.10.2014, PDF page 314):
4742 * "If framebuffer is zero, then the default draw framebuffer is
4743 * queried."
4744 */
4745 buffer = ctx->WinSysDrawBuffer;
4746 }
4747
Timothy Arceri8b006302017-05-05 15:21:22 +10004748 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4749 params,
Laura Ekstrandf22fa302015-01-29 17:11:37 -08004750 "glGetNamedFramebufferAttachmentParameteriv");
4751}
4752
4753
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004754void GLAPIENTRY
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004755_mesa_GetNamedFramebufferAttachmentParameterivEXT(GLuint framebuffer,
4756 GLenum attachment,
4757 GLenum pname, GLint *params)
4758{
4759 GET_CURRENT_CONTEXT(ctx);
4760 struct gl_framebuffer *buffer;
4761
4762 if (framebuffer) {
4763 buffer = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4764 "glGetNamedFramebufferAttachmentParameterivEXT");
4765 if (!buffer)
4766 return;
4767 }
4768 else {
4769 /*
4770 * Section 9.2 Binding and Managing Framebuffer Objects of the OpenGL
4771 * 4.5 core spec (30.10.2014, PDF page 314):
4772 * "If framebuffer is zero, then the default draw framebuffer is
4773 * queried."
4774 */
4775 buffer = ctx->WinSysDrawBuffer;
4776 }
4777
4778 get_framebuffer_attachment_parameter(ctx, buffer, attachment, pname,
4779 params,
4780 "glGetNamedFramebufferAttachmentParameterivEXT");
4781}
4782
4783
4784void GLAPIENTRY
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004785_mesa_NamedFramebufferParameteri(GLuint framebuffer, GLenum pname,
4786 GLint param)
4787{
4788 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004789 struct gl_framebuffer *fb = NULL;
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004790
Rhys Perry67f40da2018-06-14 19:56:28 -06004791 if (!ctx->Extensions.ARB_framebuffer_no_attachments &&
4792 !ctx->Extensions.ARB_sample_locations) {
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004793 _mesa_error(ctx, GL_INVALID_OPERATION,
4794 "glNamedFramebufferParameteri("
Rhys Perry67f40da2018-06-14 19:56:28 -06004795 "neither ARB_framebuffer_no_attachments nor "
4796 "ARB_sample_locations is available)");
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004797 return;
4798 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004799
Rhys Perry67f40da2018-06-14 19:56:28 -06004800 if (framebuffer) {
4801 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4802 "glNamedFramebufferParameteri");
4803 } else {
4804 fb = ctx->WinSysDrawBuffer;
4805 }
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004806
4807 if (fb) {
4808 framebuffer_parameteri(ctx, fb, pname, param,
4809 "glNamedFramebufferParameteriv");
4810 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004811}
4812
4813
Pierre-Eric Pelloux-Prayer8cfb3e42019-11-05 14:47:53 +01004814/* Helper function for ARB_framebuffer_no_attachments functions interacting with EXT_direct_state_access */
4815static struct gl_framebuffer *
4816lookup_named_framebuffer_ext_dsa(struct gl_context *ctx, GLuint framebuffer, const char* caller)
4817{
4818 struct gl_framebuffer *fb = NULL;
4819
4820 if (framebuffer) {
4821 /* The ARB_framebuffer_no_attachments spec says:
4822 *
4823 * "The error INVALID_VALUE is generated if <framebuffer> is not
4824 * a name returned by GenFramebuffers. If a framebuffer object
4825 * named <framebuffer> does not yet exist, it will be created."
4826 *
4827 * This is different from the EXT_direct_state_access spec which says:
4828 *
4829 * "If the framebuffer object named by the framebuffer parameter has not
4830 * been previously bound or has been deleted since the last binding,
4831 * the GL first creates a new state vector in the same manner as when
4832 * BindFramebuffer creates a new framebuffer object"
4833 *
4834 * So first we verify that the name exists.
4835 */
4836 fb = _mesa_lookup_framebuffer(ctx, framebuffer);
4837 if (!fb) {
4838 _mesa_error(ctx, GL_INVALID_VALUE, "%s(frameBuffer)", caller);
4839 return NULL;
4840 }
4841 /* Then, make sure it's initialized */
4842 if (fb == &DummyFramebuffer) {
4843 fb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
Pierre-Eric Pelloux-Prayer34852122020-09-04 14:07:04 +02004844 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, fb, true);
Pierre-Eric Pelloux-Prayer8cfb3e42019-11-05 14:47:53 +01004845 }
4846 }
4847 else
4848 fb = ctx->WinSysDrawBuffer;
4849
4850 return fb;
4851}
4852
4853
4854void GLAPIENTRY
4855_mesa_NamedFramebufferParameteriEXT(GLuint framebuffer, GLenum pname,
4856 GLint param)
4857{
4858 GET_CURRENT_CONTEXT(ctx);
4859 struct gl_framebuffer *fb =
4860 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
4861 "glNamedFramebufferParameteriEXT");
4862
4863 if (!fb)
4864 return;
4865
4866 framebuffer_parameteri(ctx, fb, pname, param,
4867 "glNamedFramebufferParameteriEXT");
4868}
4869
4870
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004871void GLAPIENTRY
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004872_mesa_GetFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4873 GLint *param)
4874{
4875 GET_CURRENT_CONTEXT(ctx);
4876 struct gl_framebuffer *fb;
4877
4878 if (framebuffer)
4879 fb = _mesa_lookup_framebuffer_dsa(ctx, framebuffer,
4880 "glGetFramebufferParameterivEXT");
4881 else
4882 fb = ctx->WinSysDrawBuffer;
4883
4884 if (fb) {
4885 /* The GL_EXT_direct_state_access says:
4886 *
4887 * The pname parameter must be one of framebuffer dependent values
4888 * listed in either table 4.nnn (namely DRAW_BUFFER, READ_BUFFER,
4889 * or DRAW_BUFFER0 through DRAW_BUFFER15).
4890 */
4891 if (pname == GL_DRAW_BUFFER) {
4892 *param = fb->ColorDrawBuffer[0];
4893
4894 }
4895 else if (pname == GL_READ_BUFFER) {
4896 *param = fb->ColorReadBuffer;
4897 }
4898 else if (GL_DRAW_BUFFER0 <= pname && pname <= GL_DRAW_BUFFER15) {
Marcin Ślusarz0906d5d2020-07-24 19:19:07 +02004899 unsigned buffer = pname - GL_DRAW_BUFFER0;
4900 if (buffer < ARRAY_SIZE(fb->ColorDrawBuffer))
4901 *param = fb->ColorDrawBuffer[buffer];
4902 else
4903 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
Pierre-Eric Pelloux-Prayer7534c532019-04-29 13:53:29 +02004904 }
4905 else {
4906 _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferParameterivEXT(pname)");
4907 }
4908 }
4909}
4910
4911
4912void GLAPIENTRY
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004913_mesa_GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname,
4914 GLint *param)
4915{
4916 GET_CURRENT_CONTEXT(ctx);
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004917 struct gl_framebuffer *fb;
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004918
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004919 if (!ctx->Extensions.ARB_framebuffer_no_attachments) {
4920 _mesa_error(ctx, GL_INVALID_OPERATION,
4921 "glNamedFramebufferParameteriv("
Rhys Perry67f40da2018-06-14 19:56:28 -06004922 "neither ARB_framebuffer_no_attachments nor ARB_sample_locations"
4923 " is available)");
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004924 return;
4925 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004926
Rhys Perry67f40da2018-06-14 19:56:28 -06004927 if (framebuffer)
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004928 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
4929 "glGetNamedFramebufferParameteriv");
Rhys Perry67f40da2018-06-14 19:56:28 -06004930 else
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004931 fb = ctx->WinSysDrawBuffer;
Kevin Rogovin6aa12992015-06-17 13:29:52 +03004932
4933 if (fb) {
4934 get_framebuffer_parameteriv(ctx, fb, pname, param,
4935 "glGetNamedFramebufferParameteriv");
4936 }
Laura Ekstrand9f1db782015-02-05 16:38:11 -08004937}
4938
4939
Pierre-Eric Pelloux-Prayer8cfb3e42019-11-05 14:47:53 +01004940void GLAPIENTRY
4941_mesa_GetNamedFramebufferParameterivEXT(GLuint framebuffer, GLenum pname,
4942 GLint *param)
4943{
4944 GET_CURRENT_CONTEXT(ctx);
4945 struct gl_framebuffer *fb =
4946 lookup_named_framebuffer_ext_dsa(ctx, framebuffer,
4947 "glGetNamedFramebufferParameterivEXT");
4948
4949 if (!fb)
4950 return;
4951
4952 get_framebuffer_parameteriv(ctx, fb, pname, param,
4953 "glGetNamedFramebufferParameterivEXT");
4954}
4955
4956
Ian Romanick342be8a2012-08-13 09:27:00 -07004957static void
Laura Ekstrand65d4a202015-02-04 09:49:58 -08004958invalidate_framebuffer_storage(struct gl_context *ctx,
4959 struct gl_framebuffer *fb,
4960 GLsizei numAttachments,
Ian Romanick342be8a2012-08-13 09:27:00 -07004961 const GLenum *attachments, GLint x, GLint y,
4962 GLsizei width, GLsizei height, const char *name)
4963{
4964 int i;
Ian Romanick342be8a2012-08-13 09:27:00 -07004965
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08004966 /* Section 17.4 Whole Framebuffer Operations of the OpenGL 4.5 Core
4967 * Spec (2.2.2015, PDF page 522) says:
4968 * "An INVALID_VALUE error is generated if numAttachments, width, or
4969 * height is negative."
4970 */
Ian Romanick342be8a2012-08-13 09:27:00 -07004971 if (numAttachments < 0) {
4972 _mesa_error(ctx, GL_INVALID_VALUE,
4973 "%s(numAttachments < 0)", name);
4974 return;
4975 }
4976
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08004977 if (width < 0) {
4978 _mesa_error(ctx, GL_INVALID_VALUE,
4979 "%s(width < 0)", name);
4980 return;
4981 }
4982
4983 if (height < 0) {
4984 _mesa_error(ctx, GL_INVALID_VALUE,
4985 "%s(height < 0)", name);
4986 return;
4987 }
4988
Ian Romanick342be8a2012-08-13 09:27:00 -07004989 /* The GL_ARB_invalidate_subdata spec says:
4990 *
4991 * "If an attachment is specified that does not exist in the
4992 * framebuffer bound to <target>, it is ignored."
4993 *
4994 * It also says:
4995 *
4996 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
4997 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
4998 * INVALID_OPERATION is generated."
4999 *
5000 * No mention is made of GL_AUXi being out of range. Therefore, we allow
5001 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
5002 * set of retrictions).
5003 */
5004 for (i = 0; i < numAttachments; i++) {
5005 if (_mesa_is_winsys_fbo(fb)) {
5006 switch (attachments[i]) {
5007 case GL_ACCUM:
5008 case GL_AUX0:
5009 case GL_AUX1:
5010 case GL_AUX2:
5011 case GL_AUX3:
5012 /* Accumulation buffers and auxilary buffers were removed in
5013 * OpenGL 3.1, and they never existed in OpenGL ES.
5014 */
Paul Berrydbd61352012-11-27 12:26:51 -08005015 if (ctx->API != API_OPENGL_COMPAT)
Ian Romanick342be8a2012-08-13 09:27:00 -07005016 goto invalid_enum;
5017 break;
5018 case GL_COLOR:
5019 case GL_DEPTH:
5020 case GL_STENCIL:
5021 break;
5022 case GL_BACK_LEFT:
5023 case GL_BACK_RIGHT:
5024 case GL_FRONT_LEFT:
5025 case GL_FRONT_RIGHT:
5026 if (!_mesa_is_desktop_gl(ctx))
5027 goto invalid_enum;
5028 break;
5029 default:
5030 goto invalid_enum;
5031 }
5032 } else {
5033 switch (attachments[i]) {
5034 case GL_DEPTH_ATTACHMENT:
5035 case GL_STENCIL_ATTACHMENT:
5036 break;
Eduardo Lima Mitev242ad322014-11-18 16:28:18 +01005037 case GL_DEPTH_STENCIL_ATTACHMENT:
5038 /* GL_DEPTH_STENCIL_ATTACHMENT is a valid attachment point only
5039 * in desktop and ES 3.0 profiles. Note that OES_packed_depth_stencil
5040 * extension does not make this attachment point valid on ES 2.0.
5041 */
5042 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx))
5043 break;
5044 /* fallthrough */
Ian Romanick342be8a2012-08-13 09:27:00 -07005045 case GL_COLOR_ATTACHMENT0:
5046 case GL_COLOR_ATTACHMENT1:
5047 case GL_COLOR_ATTACHMENT2:
5048 case GL_COLOR_ATTACHMENT3:
5049 case GL_COLOR_ATTACHMENT4:
5050 case GL_COLOR_ATTACHMENT5:
5051 case GL_COLOR_ATTACHMENT6:
5052 case GL_COLOR_ATTACHMENT7:
5053 case GL_COLOR_ATTACHMENT8:
5054 case GL_COLOR_ATTACHMENT9:
5055 case GL_COLOR_ATTACHMENT10:
5056 case GL_COLOR_ATTACHMENT11:
5057 case GL_COLOR_ATTACHMENT12:
5058 case GL_COLOR_ATTACHMENT13:
5059 case GL_COLOR_ATTACHMENT14:
5060 case GL_COLOR_ATTACHMENT15: {
Brian Paul859c3872012-11-04 16:43:44 -07005061 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
Ian Romanick342be8a2012-08-13 09:27:00 -07005062 if (k >= ctx->Const.MaxColorAttachments) {
5063 _mesa_error(ctx, GL_INVALID_OPERATION,
5064 "%s(attachment >= max. color attachments)", name);
5065 return;
5066 }
Constantin Baranov53904c62013-10-13 01:17:15 +03005067 break;
Ian Romanick342be8a2012-08-13 09:27:00 -07005068 }
5069 default:
5070 goto invalid_enum;
5071 }
5072 }
5073 }
5074
5075 /* We don't actually do anything for this yet. Just return after
5076 * validating the parameters and generating the required errors.
5077 */
5078 return;
5079
5080invalid_enum:
Laura Ekstrandb4368ac2015-02-04 14:21:17 -08005081 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid attachment %s)", name,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005082 _mesa_enum_to_string(attachments[i]));
Ian Romanick342be8a2012-08-13 09:27:00 -07005083 return;
5084}
5085
Rob Clark0c42b5f2018-11-01 11:10:46 -04005086static struct gl_renderbuffer_attachment *
5087get_fb_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
5088 const GLenum attachment)
5089{
5090 switch (attachment) {
5091 case GL_COLOR:
5092 return &fb->Attachment[BUFFER_BACK_LEFT];
5093 case GL_COLOR_ATTACHMENT0:
5094 case GL_COLOR_ATTACHMENT1:
5095 case GL_COLOR_ATTACHMENT2:
5096 case GL_COLOR_ATTACHMENT3:
5097 case GL_COLOR_ATTACHMENT4:
5098 case GL_COLOR_ATTACHMENT5:
5099 case GL_COLOR_ATTACHMENT6:
5100 case GL_COLOR_ATTACHMENT7:
5101 case GL_COLOR_ATTACHMENT8:
5102 case GL_COLOR_ATTACHMENT9:
5103 case GL_COLOR_ATTACHMENT10:
5104 case GL_COLOR_ATTACHMENT11:
5105 case GL_COLOR_ATTACHMENT12:
5106 case GL_COLOR_ATTACHMENT13:
5107 case GL_COLOR_ATTACHMENT14:
Tapani Pälli9762a9f2019-02-14 09:02:31 +02005108 case GL_COLOR_ATTACHMENT15: {
5109 const unsigned i = attachment - GL_COLOR_ATTACHMENT0;
5110 if (i >= ctx->Const.MaxColorAttachments)
5111 return NULL;
Marcin Ślusarzc3a251f2020-07-24 19:51:30 +02005112 assert(BUFFER_COLOR0 + i < ARRAY_SIZE(fb->Attachment));
Tapani Pälli9762a9f2019-02-14 09:02:31 +02005113 return &fb->Attachment[BUFFER_COLOR0 + i];
5114 }
Rob Clark0c42b5f2018-11-01 11:10:46 -04005115 case GL_DEPTH:
5116 case GL_DEPTH_ATTACHMENT:
5117 case GL_DEPTH_STENCIL_ATTACHMENT:
5118 return &fb->Attachment[BUFFER_DEPTH];
5119 case GL_STENCIL:
5120 case GL_STENCIL_ATTACHMENT:
5121 return &fb->Attachment[BUFFER_STENCIL];
5122 default:
5123 return NULL;
5124 }
5125}
5126
5127static void
5128discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
5129 GLsizei numAttachments, const GLenum *attachments)
5130{
5131 if (!ctx->Driver.DiscardFramebuffer)
5132 return;
5133
5134 for (int i = 0; i < numAttachments; i++) {
5135 struct gl_renderbuffer_attachment *att =
5136 get_fb_attachment(ctx, fb, attachments[i]);
5137
5138 if (!att)
5139 continue;
5140
Eric Anholtdb2ae512019-01-30 09:33:53 -08005141 /* If we're asked to invalidate just depth or just stencil, but the
5142 * attachment is packed depth/stencil, then we can only use
5143 * Driver.DiscardFramebuffer if the attachments list includes both depth
5144 * and stencil and they both point at the same renderbuffer.
5145 */
5146 if ((attachments[i] == GL_DEPTH_ATTACHMENT ||
5147 attachments[i] == GL_STENCIL_ATTACHMENT) &&
5148 (!att->Renderbuffer ||
5149 att->Renderbuffer->_BaseFormat == GL_DEPTH_STENCIL)) {
5150 GLenum other_format = (attachments[i] == GL_DEPTH_ATTACHMENT ?
5151 GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
5152 bool has_both = false;
5153 for (int j = 0; j < numAttachments; j++) {
Eric Anholt3be4b892020-01-13 13:06:01 -08005154 if (attachments[j] == other_format) {
Eric Anholtdb2ae512019-01-30 09:33:53 -08005155 has_both = true;
Eric Anholt3be4b892020-01-13 13:06:01 -08005156 break;
5157 }
Eric Anholtdb2ae512019-01-30 09:33:53 -08005158 }
5159
5160 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer !=
5161 fb->Attachment[BUFFER_STENCIL].Renderbuffer || !has_both)
5162 continue;
5163 }
5164
Rob Clark0c42b5f2018-11-01 11:10:46 -04005165 ctx->Driver.DiscardFramebuffer(ctx, fb, att);
5166 }
5167}
Brian Paulc1377ed2014-03-22 10:31:58 -06005168
Ian Romanick342be8a2012-08-13 09:27:00 -07005169void GLAPIENTRY
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005170_mesa_InvalidateSubFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5171 const GLenum *attachments, GLint x,
5172 GLint y, GLsizei width, GLsizei height)
5173{
5174 /* no-op */
5175}
5176
5177
5178void GLAPIENTRY
Ian Romanick342be8a2012-08-13 09:27:00 -07005179_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
5180 const GLenum *attachments, GLint x, GLint y,
5181 GLsizei width, GLsizei height)
5182{
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005183 struct gl_framebuffer *fb;
5184 GET_CURRENT_CONTEXT(ctx);
5185
5186 fb = get_framebuffer_target(ctx, target);
5187 if (!fb) {
5188 _mesa_error(ctx, GL_INVALID_ENUM,
5189 "glInvalidateSubFramebuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005190 _mesa_enum_to_string(target));
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005191 return;
5192 }
5193
5194 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
Ian Romanick342be8a2012-08-13 09:27:00 -07005195 x, y, width, height,
5196 "glInvalidateSubFramebuffer");
5197}
5198
Brian Paulc1377ed2014-03-22 10:31:58 -06005199
Ian Romanick342be8a2012-08-13 09:27:00 -07005200void GLAPIENTRY
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005201_mesa_InvalidateNamedFramebufferSubData(GLuint framebuffer,
5202 GLsizei numAttachments,
5203 const GLenum *attachments,
5204 GLint x, GLint y,
5205 GLsizei width, GLsizei height)
5206{
5207 struct gl_framebuffer *fb;
5208 GET_CURRENT_CONTEXT(ctx);
5209
5210 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5211 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5212 * default draw framebuffer is affected."
5213 */
5214 if (framebuffer) {
5215 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5216 "glInvalidateNamedFramebufferSubData");
5217 if (!fb)
5218 return;
5219 }
5220 else
5221 fb = ctx->WinSysDrawBuffer;
5222
5223 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5224 x, y, width, height,
5225 "glInvalidateNamedFramebufferSubData");
5226}
5227
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005228void GLAPIENTRY
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005229_mesa_InvalidateFramebuffer_no_error(GLenum target, GLsizei numAttachments,
5230 const GLenum *attachments)
5231{
Rob Clark0c42b5f2018-11-01 11:10:46 -04005232 struct gl_framebuffer *fb;
5233 GET_CURRENT_CONTEXT(ctx);
5234
5235 fb = get_framebuffer_target(ctx, target);
5236 if (!fb)
5237 return;
5238
5239 discard_framebuffer(ctx, fb, numAttachments, attachments);
Samuel Pitoisetc8864922017-07-18 18:02:51 +02005240}
5241
5242
5243void GLAPIENTRY
Ian Romanick342be8a2012-08-13 09:27:00 -07005244_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
5245 const GLenum *attachments)
5246{
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005247 struct gl_framebuffer *fb;
5248 GET_CURRENT_CONTEXT(ctx);
5249
5250 fb = get_framebuffer_target(ctx, target);
5251 if (!fb) {
5252 _mesa_error(ctx, GL_INVALID_ENUM,
5253 "glInvalidateFramebuffer(invalid target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005254 _mesa_enum_to_string(target));
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005255 return;
5256 }
5257
Ian Romanick342be8a2012-08-13 09:27:00 -07005258 /* The GL_ARB_invalidate_subdata spec says:
5259 *
5260 * "The command
5261 *
5262 * void InvalidateFramebuffer(enum target,
5263 * sizei numAttachments,
5264 * const enum *attachments);
5265 *
5266 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5267 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5268 * <MAX_VIEWPORT_DIMS[1]> respectively."
5269 */
Laura Ekstrand65d4a202015-02-04 09:49:58 -08005270 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
Brian Paulc1377ed2014-03-22 10:31:58 -06005271 0, 0,
Samuel Iglesias Gonsálvezaa849d92016-03-01 12:02:27 +01005272 ctx->Const.MaxViewportWidth,
5273 ctx->Const.MaxViewportHeight,
Ian Romanick342be8a2012-08-13 09:27:00 -07005274 "glInvalidateFramebuffer");
Rob Clark0c42b5f2018-11-01 11:10:46 -04005275
5276 discard_framebuffer(ctx, fb, numAttachments, attachments);
Ian Romanick342be8a2012-08-13 09:27:00 -07005277}
Tapani Pälli413941e2013-02-18 09:12:27 +02005278
Brian Paulc1377ed2014-03-22 10:31:58 -06005279
Tapani Pälli413941e2013-02-18 09:12:27 +02005280void GLAPIENTRY
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005281_mesa_InvalidateNamedFramebufferData(GLuint framebuffer,
5282 GLsizei numAttachments,
5283 const GLenum *attachments)
5284{
5285 struct gl_framebuffer *fb;
5286 GET_CURRENT_CONTEXT(ctx);
5287
5288 /* The OpenGL 4.5 core spec (02.02.2015) says (in Section 17.4 Whole
5289 * Framebuffer Operations, PDF page 522): "If framebuffer is zero, the
5290 * default draw framebuffer is affected."
5291 */
5292 if (framebuffer) {
5293 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5294 "glInvalidateNamedFramebufferData");
5295 if (!fb)
5296 return;
5297 }
5298 else
5299 fb = ctx->WinSysDrawBuffer;
5300
5301 /* The GL_ARB_invalidate_subdata spec says:
5302 *
5303 * "The command
5304 *
5305 * void InvalidateFramebuffer(enum target,
5306 * sizei numAttachments,
5307 * const enum *attachments);
5308 *
5309 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
5310 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
5311 * <MAX_VIEWPORT_DIMS[1]> respectively."
5312 */
5313 invalidate_framebuffer_storage(ctx, fb, numAttachments, attachments,
5314 0, 0,
Samuel Iglesias Gonsálvezaa849d92016-03-01 12:02:27 +01005315 ctx->Const.MaxViewportWidth,
5316 ctx->Const.MaxViewportHeight,
Laura Ekstrandd890fc72015-02-04 14:21:48 -08005317 "glInvalidateNamedFramebufferData");
5318}
5319
5320
5321void GLAPIENTRY
Tapani Pälli413941e2013-02-18 09:12:27 +02005322_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
5323 const GLenum *attachments)
5324{
5325 struct gl_framebuffer *fb;
5326 GLint i;
5327
5328 GET_CURRENT_CONTEXT(ctx);
5329
5330 fb = get_framebuffer_target(ctx, target);
5331 if (!fb) {
5332 _mesa_error(ctx, GL_INVALID_ENUM,
5333 "glDiscardFramebufferEXT(target %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005334 _mesa_enum_to_string(target));
Tapani Pälli413941e2013-02-18 09:12:27 +02005335 return;
5336 }
5337
5338 if (numAttachments < 0) {
5339 _mesa_error(ctx, GL_INVALID_VALUE,
5340 "glDiscardFramebufferEXT(numAttachments < 0)");
5341 return;
5342 }
5343
5344 for (i = 0; i < numAttachments; i++) {
5345 switch (attachments[i]) {
5346 case GL_COLOR:
5347 case GL_DEPTH:
5348 case GL_STENCIL:
5349 if (_mesa_is_user_fbo(fb))
5350 goto invalid_enum;
5351 break;
5352 case GL_COLOR_ATTACHMENT0:
5353 case GL_DEPTH_ATTACHMENT:
5354 case GL_STENCIL_ATTACHMENT:
5355 if (_mesa_is_winsys_fbo(fb))
5356 goto invalid_enum;
5357 break;
5358 default:
5359 goto invalid_enum;
5360 }
5361 }
5362
Rob Clark0c42b5f2018-11-01 11:10:46 -04005363 discard_framebuffer(ctx, fb, numAttachments, attachments);
Tapani Pälli413941e2013-02-18 09:12:27 +02005364
5365 return;
5366
5367invalid_enum:
5368 _mesa_error(ctx, GL_INVALID_ENUM,
5369 "glDiscardFramebufferEXT(attachment %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07005370 _mesa_enum_to_string(attachments[i]));
Tapani Pälli413941e2013-02-18 09:12:27 +02005371}
Rhys Perry67f40da2018-06-14 19:56:28 -06005372
5373static void
5374sample_locations(struct gl_context *ctx, struct gl_framebuffer *fb,
5375 GLuint start, GLsizei count, const GLfloat *v, bool no_error,
5376 const char *name)
5377{
5378 GLsizei i;
5379
5380 if (!no_error) {
5381 if (!ctx->Extensions.ARB_sample_locations) {
5382 _mesa_error(ctx, GL_INVALID_OPERATION,
5383 "%s not supported "
5384 "(ARB_sample_locations not available)", name);
5385 return;
5386 }
5387
5388 if (start + count > MAX_SAMPLE_LOCATION_TABLE_SIZE) {
5389 _mesa_error(ctx, GL_INVALID_VALUE,
5390 "%s(start+size > sample location table size)", name);
5391 return;
5392 }
5393 }
5394
5395 if (!fb->SampleLocationTable) {
5396 size_t size = MAX_SAMPLE_LOCATION_TABLE_SIZE * 2 * sizeof(GLfloat);
5397 fb->SampleLocationTable = malloc(size);
Eric Engestrom9a4bd6b2018-06-18 11:39:05 +01005398 if (!fb->SampleLocationTable) {
Rhys Perry67f40da2018-06-14 19:56:28 -06005399 _mesa_error(ctx, GL_OUT_OF_MEMORY,
5400 "Cannot allocate sample location table");
Eric Engestrom9a4bd6b2018-06-18 11:39:05 +01005401 return;
5402 }
Rhys Perry67f40da2018-06-14 19:56:28 -06005403 for (i = 0; i < MAX_SAMPLE_LOCATION_TABLE_SIZE * 2; i++)
5404 fb->SampleLocationTable[i] = 0.5f;
5405 }
5406
5407 for (i = 0; i < count * 2; i++) {
5408 /* The ARB_sample_locations spec says:
5409 *
5410 * Sample locations outside of [0,1] result in undefined
5411 * behavior.
5412 *
5413 * To simplify driver implementations, we choose to clamp to
5414 * [0,1] and change NaN into 0.5.
5415 */
5416 if (isnan(v[i]) || v[i] < 0.0f || v[i] > 1.0f) {
5417 static GLuint msg_id = 0;
5418 static const char* msg = "Invalid sample location specified";
5419 _mesa_debug_get_id(&msg_id);
5420
5421 _mesa_log_msg(ctx, MESA_DEBUG_SOURCE_API, MESA_DEBUG_TYPE_UNDEFINED,
5422 msg_id, MESA_DEBUG_SEVERITY_HIGH, strlen(msg), msg);
5423 }
5424
5425 if (isnan(v[i]))
5426 fb->SampleLocationTable[start * 2 + i] = 0.5f;
5427 else
Alyssa Rosenzweig05bacdb2020-05-19 11:08:51 -04005428 fb->SampleLocationTable[start * 2 + i] = SATURATE(v[i]);
Rhys Perry67f40da2018-06-14 19:56:28 -06005429 }
5430
5431 if (fb == ctx->DrawBuffer)
5432 ctx->NewDriverState |= ctx->DriverFlags.NewSampleLocations;
5433}
5434
5435void GLAPIENTRY
5436_mesa_FramebufferSampleLocationsfvARB(GLenum target, GLuint start,
5437 GLsizei count, const GLfloat *v)
5438{
5439 struct gl_framebuffer *fb;
5440
5441 GET_CURRENT_CONTEXT(ctx);
5442
5443 fb = get_framebuffer_target(ctx, target);
5444 if (!fb) {
5445 _mesa_error(ctx, GL_INVALID_ENUM,
5446 "glFramebufferSampleLocationsfvARB(target %s)",
5447 _mesa_enum_to_string(target));
5448 return;
5449 }
5450
5451 sample_locations(ctx, fb, start, count, v, false,
5452 "glFramebufferSampleLocationsfvARB");
5453}
5454
5455void GLAPIENTRY
5456_mesa_NamedFramebufferSampleLocationsfvARB(GLuint framebuffer, GLuint start,
5457 GLsizei count, const GLfloat *v)
5458{
5459 struct gl_framebuffer *fb;
5460
5461 GET_CURRENT_CONTEXT(ctx);
5462
5463 if (framebuffer) {
5464 fb = _mesa_lookup_framebuffer_err(ctx, framebuffer,
5465 "glNamedFramebufferSampleLocationsfvARB");
5466 if (!fb)
5467 return;
5468 }
5469 else
5470 fb = ctx->WinSysDrawBuffer;
5471
5472 sample_locations(ctx, fb, start, count, v, false,
5473 "glNamedFramebufferSampleLocationsfvARB");
5474}
5475
5476void GLAPIENTRY
5477_mesa_FramebufferSampleLocationsfvARB_no_error(GLenum target, GLuint start,
5478 GLsizei count, const GLfloat *v)
5479{
5480 GET_CURRENT_CONTEXT(ctx);
5481 sample_locations(ctx, get_framebuffer_target(ctx, target), start,
5482 count, v, true, "glFramebufferSampleLocationsfvARB");
5483}
5484
5485void GLAPIENTRY
5486_mesa_NamedFramebufferSampleLocationsfvARB_no_error(GLuint framebuffer,
5487 GLuint start, GLsizei count,
5488 const GLfloat *v)
5489{
5490 GET_CURRENT_CONTEXT(ctx);
5491 sample_locations(ctx, _mesa_lookup_framebuffer(ctx, framebuffer), start,
5492 count, v, true, "glNamedFramebufferSampleLocationsfvARB");
5493}
5494
5495void GLAPIENTRY
5496_mesa_EvaluateDepthValuesARB(void)
5497{
5498 GET_CURRENT_CONTEXT(ctx);
5499
5500 if (!ctx->Extensions.ARB_sample_locations) {
5501 _mesa_error(ctx, GL_INVALID_OPERATION,
5502 "EvaluateDepthValuesARB not supported (neither "
5503 "ARB_sample_locations nor NV_sample_locations is available)");
5504 return;
5505 }
5506
5507 if (ctx->Driver.EvaluateDepthValues)
5508 ctx->Driver.EvaluateDepthValues(ctx);
5509}