blob: 7c134212c910053714016c799e8c691bf8475bdb [file] [log] [blame]
Brian Paulddc82ee2005-02-05 19:56:45 +00001/*
2 * Mesa 3-D graphics library
Brian Paul3dc65912008-07-03 15:40:38 -06003 * Version: 7.1
Brian Paulddc82ee2005-02-05 19:56:45 +00004 *
Brian Paul3dc65912008-07-03 15:40:38 -06005 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
Brian Paul989edea2009-01-22 15:05:13 -07006 * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
Brian Paulddc82ee2005-02-05 19:56:45 +00007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Kenneth Graunke3d8d5b22013-04-21 13:46:48 -070021 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
Brian Paulddc82ee2005-02-05 19:56:45 +000025 */
26
27
Brian Paul463642c2005-02-08 02:06:00 +000028/*
Brian Paul989edea2009-01-22 15:05:13 -070029 * GL_EXT/ARB_framebuffer_object extensions
30 *
Brian Paul463642c2005-02-08 02:06:00 +000031 * Authors:
32 * Brian Paul
33 */
34
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -080035#include <stdbool.h>
Brian Paul463642c2005-02-08 02:06:00 +000036
Roland Scheideggera1bc0d02007-07-18 20:17:14 +020037#include "buffers.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000038#include "context.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 Paul21f8d312009-10-27 16:59:23 -060054/** Set this to 1 to debug/log glBlitFramebuffer() calls */
55#define DEBUG_BLIT 0
56
Brian Paulc26c2002009-09-15 17:20:32 -060057
Brian Pauld9468c92005-02-10 16:08:07 +000058/**
59 * Notes:
60 *
61 * None of the GL_EXT_framebuffer_object functions are compiled into
62 * display lists.
63 */
64
65
66
Brian Paul923b6fc2005-02-08 04:08:56 +000067/*
68 * When glGenRender/FramebuffersEXT() is called we insert pointers to
69 * these placeholder objects into the hash table.
70 * Later, when the object ID is first bound, we replace the placeholder
71 * with the real frame/renderbuffer.
72 */
Brian Paul2c6f9112005-02-24 05:47:06 +000073static struct gl_framebuffer DummyFramebuffer;
74static struct gl_renderbuffer DummyRenderbuffer;
Brian Paul1864c7d2005-02-08 03:46:37 +000075
Kristian Høgsberg144356f2010-09-09 17:08:12 -040076/* We bind this framebuffer when applications pass a NULL
77 * drawable/surface in make current. */
78static struct gl_framebuffer IncompleteFramebuffer;
79
Brian Paul1864c7d2005-02-08 03:46:37 +000080
Brian Paul3dc65912008-07-03 15:40:38 -060081static void
Brian Paulc7324582012-11-30 10:04:48 -070082delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
Brian Paul3dc65912008-07-03 15:40:38 -060083{
84 /* no op */
85}
86
87static void
88delete_dummy_framebuffer(struct gl_framebuffer *fb)
89{
90 /* no op */
91}
92
93
94void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -040095_mesa_init_fbobjects(struct gl_context *ctx)
Brian Paul3dc65912008-07-03 15:40:38 -060096{
Vladimir Vukicevic07317012010-09-01 08:54:21 -060097 _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
98 _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
Kristian Høgsberg144356f2010-09-09 17:08:12 -040099 _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex);
Brian Paul3dc65912008-07-03 15:40:38 -0600100 DummyFramebuffer.Delete = delete_dummy_framebuffer;
101 DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
Kristian Høgsberg144356f2010-09-09 17:08:12 -0400102 IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
Brian Paul3dc65912008-07-03 15:40:38 -0600103}
104
Kristian Høgsberg9456e222010-06-04 14:28:59 -0400105struct gl_framebuffer *
106_mesa_get_incomplete_framebuffer(void)
107{
Kristian Høgsberg144356f2010-09-09 17:08:12 -0400108 return &IncompleteFramebuffer;
Kristian Høgsberg9456e222010-06-04 14:28:59 -0400109}
Brian Paul3dc65912008-07-03 15:40:38 -0600110
Brian Paulddc82ee2005-02-05 19:56:45 +0000111/**
Brian Paul2c6f9112005-02-24 05:47:06 +0000112 * Helper routine for getting a gl_renderbuffer.
Brian Paulddc82ee2005-02-05 19:56:45 +0000113 */
Brian Paulea4fe662006-03-26 05:22:17 +0000114struct gl_renderbuffer *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400115_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
Brian Paulddc82ee2005-02-05 19:56:45 +0000116{
Brian Paul2c6f9112005-02-24 05:47:06 +0000117 struct gl_renderbuffer *rb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000118
Brian Paul1864c7d2005-02-08 03:46:37 +0000119 if (id == 0)
Brian Paulddc82ee2005-02-05 19:56:45 +0000120 return NULL;
121
Brian Paul2c6f9112005-02-24 05:47:06 +0000122 rb = (struct gl_renderbuffer *)
Brian Paulddc82ee2005-02-05 19:56:45 +0000123 _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
124 return rb;
125}
126
127
128/**
Brian Paul2c6f9112005-02-24 05:47:06 +0000129 * Helper routine for getting a gl_framebuffer.
Brian Paulddc82ee2005-02-05 19:56:45 +0000130 */
Brian Paulea4fe662006-03-26 05:22:17 +0000131struct gl_framebuffer *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400132_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
Brian Paulddc82ee2005-02-05 19:56:45 +0000133{
Brian Paul2c6f9112005-02-24 05:47:06 +0000134 struct gl_framebuffer *fb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000135
Brian Paul1864c7d2005-02-08 03:46:37 +0000136 if (id == 0)
Brian Paulddc82ee2005-02-05 19:56:45 +0000137 return NULL;
138
Brian Paul2c6f9112005-02-24 05:47:06 +0000139 fb = (struct gl_framebuffer *)
Brian Paulddc82ee2005-02-05 19:56:45 +0000140 _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
Brian Paul463642c2005-02-08 02:06:00 +0000141 return fb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000142}
143
144
145/**
Brian Paul72966362009-01-21 16:28:38 -0700146 * Mark the given framebuffer as invalid. This will force the
147 * test for framebuffer completeness to be done before the framebuffer
148 * is used.
149 */
150static void
151invalidate_framebuffer(struct gl_framebuffer *fb)
152{
153 fb->_Status = 0; /* "indeterminate" */
154}
155
156
157/**
Brian Paulc6991432011-02-28 18:24:25 -0700158 * Return the gl_framebuffer object which corresponds to the given
159 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
160 * Check support for GL_EXT_framebuffer_blit to determine if certain
161 * targets are legal.
162 * \return gl_framebuffer pointer or NULL if target is illegal
163 */
164static struct gl_framebuffer *
165get_framebuffer_target(struct gl_context *ctx, GLenum target)
166{
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800167 bool have_fb_blit = _mesa_is_gles3(ctx) ||
168 (ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx));
Brian Paulc6991432011-02-28 18:24:25 -0700169 switch (target) {
170 case GL_DRAW_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800171 return have_fb_blit ? ctx->DrawBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700172 case GL_READ_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800173 return have_fb_blit ? ctx->ReadBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700174 case GL_FRAMEBUFFER_EXT:
175 return ctx->DrawBuffer;
176 default:
177 return NULL;
178 }
179}
180
181
182/**
Brian Pauld9468c92005-02-10 16:08:07 +0000183 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
Brian Paul2c6f9112005-02-24 05:47:06 +0000184 * gl_renderbuffer_attachment object.
Brian Paul61ec2052010-06-22 08:37:44 -0600185 * This function is only used for user-created FB objects, not the
186 * default / window-system FB object.
Brian Paul30590072009-01-21 11:06:11 -0700187 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
188 * the depth buffer attachment point.
Brian Pauld9468c92005-02-10 16:08:07 +0000189 */
Brian Paul84716042005-11-16 04:05:54 +0000190struct gl_renderbuffer_attachment *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400191_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
Brian Paul84716042005-11-16 04:05:54 +0000192 GLenum attachment)
Brian Paul3deaa012005-02-07 05:08:24 +0000193{
194 GLuint i;
195
Brian Paul36ede892012-01-12 09:17:23 -0700196 assert(_mesa_is_user_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600197
Brian Paul3deaa012005-02-07 05:08:24 +0000198 switch (attachment) {
199 case GL_COLOR_ATTACHMENT0_EXT:
200 case GL_COLOR_ATTACHMENT1_EXT:
201 case GL_COLOR_ATTACHMENT2_EXT:
202 case GL_COLOR_ATTACHMENT3_EXT:
203 case GL_COLOR_ATTACHMENT4_EXT:
204 case GL_COLOR_ATTACHMENT5_EXT:
205 case GL_COLOR_ATTACHMENT6_EXT:
206 case GL_COLOR_ATTACHMENT7_EXT:
207 case GL_COLOR_ATTACHMENT8_EXT:
208 case GL_COLOR_ATTACHMENT9_EXT:
209 case GL_COLOR_ATTACHMENT10_EXT:
210 case GL_COLOR_ATTACHMENT11_EXT:
211 case GL_COLOR_ATTACHMENT12_EXT:
212 case GL_COLOR_ATTACHMENT13_EXT:
213 case GL_COLOR_ATTACHMENT14_EXT:
214 case GL_COLOR_ATTACHMENT15_EXT:
Ian Romanick2e3a4ab2011-10-02 15:03:07 -0700215 /* Only OpenGL ES 1.x forbids color attachments other than
216 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the
217 * hardware is used.
218 */
Brian Paul3deaa012005-02-07 05:08:24 +0000219 i = attachment - GL_COLOR_ATTACHMENT0_EXT;
Ian Romanick7e4cb322011-10-02 14:50:21 -0700220 if (i >= ctx->Const.MaxColorAttachments
Ian Romanick2e3a4ab2011-10-02 15:03:07 -0700221 || (i > 0 && ctx->API == API_OPENGLES)) {
Brian Paul3deaa012005-02-07 05:08:24 +0000222 return NULL;
223 }
Brian Paule4b23562005-05-04 20:11:35 +0000224 return &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paul30590072009-01-21 11:06:11 -0700225 case GL_DEPTH_STENCIL_ATTACHMENT:
Matt Turnerec8ee912012-11-15 22:13:48 -0800226 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
Ian Romanick7e4cb322011-10-02 14:50:21 -0700227 return NULL;
Brian Paul30590072009-01-21 11:06:11 -0700228 /* fall-through */
Brian Paul3deaa012005-02-07 05:08:24 +0000229 case GL_DEPTH_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000230 return &fb->Attachment[BUFFER_DEPTH];
Brian Paul3deaa012005-02-07 05:08:24 +0000231 case GL_STENCIL_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000232 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul61ec2052010-06-22 08:37:44 -0600233 default:
234 return NULL;
235 }
236}
237
238
239/**
240 * As above, but only used for getting attachments of the default /
241 * window-system framebuffer (not user-created framebuffer objects).
242 */
243static struct gl_renderbuffer_attachment *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400244_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
Brian Paul61ec2052010-06-22 08:37:44 -0600245 GLenum attachment)
246{
Brian Paul36ede892012-01-12 09:17:23 -0700247 assert(_mesa_is_winsys_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600248
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800249 if (_mesa_is_gles3(ctx)) {
250 assert(attachment == GL_BACK ||
251 attachment == GL_DEPTH ||
252 attachment == GL_STENCIL);
253 switch (attachment) {
254 case GL_BACK:
255 /* Since there is no stereo rendering in ES 3.0, only return the
256 * LEFT bits.
257 */
258 if (ctx->DrawBuffer->Visual.doubleBufferMode)
259 return &fb->Attachment[BUFFER_BACK_LEFT];
260 return &fb->Attachment[BUFFER_FRONT_LEFT];
261 case GL_DEPTH:
262 return &fb->Attachment[BUFFER_DEPTH];
263 case GL_STENCIL:
264 return &fb->Attachment[BUFFER_STENCIL];
265 }
266 }
267
Brian Paul61ec2052010-06-22 08:37:44 -0600268 switch (attachment) {
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400269 case GL_FRONT_LEFT:
270 return &fb->Attachment[BUFFER_FRONT_LEFT];
271 case GL_FRONT_RIGHT:
272 return &fb->Attachment[BUFFER_FRONT_RIGHT];
273 case GL_BACK_LEFT:
274 return &fb->Attachment[BUFFER_BACK_LEFT];
275 case GL_BACK_RIGHT:
276 return &fb->Attachment[BUFFER_BACK_RIGHT];
Brian Paul61ec2052010-06-22 08:37:44 -0600277 case GL_AUX0:
278 if (fb->Visual.numAuxBuffers == 1) {
279 return &fb->Attachment[BUFFER_AUX0];
280 }
281 return NULL;
Ian Romanicka8328cc2011-10-03 12:02:18 -0700282
283 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
284 *
285 * "If the default framebuffer is bound to target, then attachment must
286 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
287 * identifying a color buffer; DEPTH, identifying the depth buffer; or
288 * STENCIL, identifying the stencil buffer."
289 *
290 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
291 * language. However, revision #33 of the ARB_framebuffer_object spec
292 * says:
293 *
294 * "If the default framebuffer is bound to <target>, then <attachment>
295 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
296 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
297 * depth buffer, or the stencil buffer, and <pname> may be
298 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
299 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
300 *
301 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
302 * from glext.h, so shipping apps should not use those values.
303 *
304 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
305 * support queries of the window system FBO.
306 */
307 case GL_DEPTH:
Brian Paul61ec2052010-06-22 08:37:44 -0600308 return &fb->Attachment[BUFFER_DEPTH];
Ian Romanicka8328cc2011-10-03 12:02:18 -0700309 case GL_STENCIL:
Brian Paul61ec2052010-06-22 08:37:44 -0600310 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul3deaa012005-02-07 05:08:24 +0000311 default:
312 return NULL;
313 }
314}
315
316
Brian Paul61ec2052010-06-22 08:37:44 -0600317
Brian Pauld9468c92005-02-10 16:08:07 +0000318/**
319 * Remove any texture or renderbuffer attached to the given attachment
320 * point. Update reference counts, etc.
321 */
Brian Paule4b23562005-05-04 20:11:35 +0000322void
Brian Paulf9288542010-10-22 11:25:14 -0600323_mesa_remove_attachment(struct gl_context *ctx,
324 struct gl_renderbuffer_attachment *att)
Brian Paul3deaa012005-02-07 05:08:24 +0000325{
Eric Anholtc810e672013-05-10 12:36:43 -0700326 struct gl_renderbuffer *rb = att->Renderbuffer;
327
328 /* tell driver that we're done rendering to this texture. */
329 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700330 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700331
Brian Paul3deaa012005-02-07 05:08:24 +0000332 if (att->Type == GL_TEXTURE) {
333 ASSERT(att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100334 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
335 ASSERT(!att->Texture);
Brian Paul3deaa012005-02-07 05:08:24 +0000336 }
Brian Paul0e31e022005-12-01 00:25:00 +0000337 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul3deaa012005-02-07 05:08:24 +0000338 ASSERT(!att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100339 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
340 ASSERT(!att->Renderbuffer);
Brian Paul3deaa012005-02-07 05:08:24 +0000341 }
342 att->Type = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000343 att->Complete = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +0000344}
345
Eric Anholt749a9272013-04-22 10:38:41 -0700346/**
347 * Create a renderbuffer which will be set up by the driver to wrap the
348 * texture image slice.
349 *
350 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
351 * to share most of their framebuffer rendering code between winsys,
352 * renderbuffer, and texture attachments.
353 *
354 * The allocated renderbuffer uses a non-zero Name so that drivers can check
355 * it for determining vertical orientation, but we use ~0 to make it fairly
356 * unambiguous with actual user (non-texture) renderbuffers.
357 */
358void
359_mesa_update_texture_renderbuffer(struct gl_context *ctx,
360 struct gl_framebuffer *fb,
361 struct gl_renderbuffer_attachment *att)
362{
363 struct gl_texture_image *texImage;
364 struct gl_renderbuffer *rb;
365
Eric Anholte98c39c2013-05-10 11:51:01 -0700366 texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
Eric Anholt749a9272013-04-22 10:38:41 -0700367 if (!texImage)
368 return;
369
370 rb = att->Renderbuffer;
371 if (!rb) {
372 rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
373 if (!rb) {
374 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
375 return;
376 }
377 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
378
379 /* This can't get called on a texture renderbuffer, so set it to NULL
380 * for clarity compared to user renderbuffers.
381 */
382 rb->AllocStorage = NULL;
Eric Anholtc810e672013-05-10 12:36:43 -0700383
384 rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
Eric Anholt749a9272013-04-22 10:38:41 -0700385 }
386
Eric Anholt77a405d2013-04-22 11:04:21 -0700387 rb->_BaseFormat = texImage->_BaseFormat;
388 rb->Format = texImage->TexFormat;
389 rb->InternalFormat = texImage->InternalFormat;
390 rb->Width = texImage->Width2;
391 rb->Height = texImage->Height2;
392 rb->NumSamples = texImage->NumSamples;
Eric Anholte98c39c2013-05-10 11:51:01 -0700393 rb->TexImage = texImage;
Eric Anholt77a405d2013-04-22 11:04:21 -0700394
Eric Anholt749a9272013-04-22 10:38:41 -0700395 ctx->Driver.RenderTexture(ctx, fb, att);
396}
Brian Paul3deaa012005-02-07 05:08:24 +0000397
Brian Pauld9468c92005-02-10 16:08:07 +0000398/**
399 * Bind a texture object to an attachment point.
400 * The previous binding, if any, will be removed first.
401 */
Brian Paule4b23562005-05-04 20:11:35 +0000402void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400403_mesa_set_texture_attachment(struct gl_context *ctx,
Brian Paul519b23b2006-03-20 18:51:57 +0000404 struct gl_framebuffer *fb,
Brian Paule4b23562005-05-04 20:11:35 +0000405 struct gl_renderbuffer_attachment *att,
406 struct gl_texture_object *texObj,
Jordan Justena6280802013-04-18 10:08:50 -0700407 GLenum texTarget, GLuint level, GLuint zoffset,
408 GLboolean layered)
Brian Paul3deaa012005-02-07 05:08:24 +0000409{
Eric Anholtc810e672013-05-10 12:36:43 -0700410 struct gl_renderbuffer *rb = att->Renderbuffer;
411
412 if (rb && rb->NeedsFinishRenderTexture)
Eric Anholta5b04522013-05-10 12:17:52 -0700413 ctx->Driver.FinishRenderTexture(ctx, rb);
Eric Anholtc810e672013-05-10 12:36:43 -0700414
Brian Paul0e31e022005-12-01 00:25:00 +0000415 if (att->Texture == texObj) {
416 /* re-attaching same texture */
417 ASSERT(att->Type == GL_TEXTURE);
418 }
419 else {
420 /* new attachment */
421 _mesa_remove_attachment(ctx, att);
422 att->Type = GL_TEXTURE;
Brian9e01b912007-08-13 11:29:46 +0100423 assert(!att->Texture);
424 _mesa_reference_texobj(&att->Texture, texObj);
Brian Paul0e31e022005-12-01 00:25:00 +0000425 }
Eric Anholt749a9272013-04-22 10:38:41 -0700426 invalidate_framebuffer(fb);
Brian Paul0e31e022005-12-01 00:25:00 +0000427
428 /* always update these fields */
Brian Paul3deaa012005-02-07 05:08:24 +0000429 att->TextureLevel = level;
Brian Paul26f1ad62009-10-23 18:15:55 -0600430 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
Brian Paul3deaa012005-02-07 05:08:24 +0000431 att->Zoffset = zoffset;
Jordan Justena6280802013-04-18 10:08:50 -0700432 att->Layered = layered;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000433 att->Complete = GL_FALSE;
Brian Paul519b23b2006-03-20 18:51:57 +0000434
Eric Anholt749a9272013-04-22 10:38:41 -0700435 _mesa_update_texture_renderbuffer(ctx, fb, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000436}
437
438
Brian Pauld9468c92005-02-10 16:08:07 +0000439/**
440 * Bind a renderbuffer to an attachment point.
441 * The previous binding, if any, will be removed first.
442 */
Brian Paule4b23562005-05-04 20:11:35 +0000443void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400444_mesa_set_renderbuffer_attachment(struct gl_context *ctx,
Brian Paule4b23562005-05-04 20:11:35 +0000445 struct gl_renderbuffer_attachment *att,
446 struct gl_renderbuffer *rb)
Brian Paul3deaa012005-02-07 05:08:24 +0000447{
Brian Paulea4fe662006-03-26 05:22:17 +0000448 /* XXX check if re-doing same attachment, exit early */
Brian Paule4b23562005-05-04 20:11:35 +0000449 _mesa_remove_attachment(ctx, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000450 att->Type = GL_RENDERBUFFER_EXT;
Brian Paul2c6f9112005-02-24 05:47:06 +0000451 att->Texture = NULL; /* just to be safe */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000452 att->Complete = GL_FALSE;
Briandccd9c42007-04-02 09:56:28 -0600453 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
Brian Paul3deaa012005-02-07 05:08:24 +0000454}
455
Brian Paulddc82ee2005-02-05 19:56:45 +0000456
Brian Paulf0bbbf62005-02-09 03:50:30 +0000457/**
Brian Paule4b23562005-05-04 20:11:35 +0000458 * Fallback for ctx->Driver.FramebufferRenderbuffer()
Brian Paul84716042005-11-16 04:05:54 +0000459 * Attach a renderbuffer object to a framebuffer object.
Brian Paule4b23562005-05-04 20:11:35 +0000460 */
461void
Brian Paulf9288542010-10-22 11:25:14 -0600462_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
463 struct gl_framebuffer *fb,
Brian Paul84716042005-11-16 04:05:54 +0000464 GLenum attachment, struct gl_renderbuffer *rb)
Brian Paule4b23562005-05-04 20:11:35 +0000465{
Brian Paul84716042005-11-16 04:05:54 +0000466 struct gl_renderbuffer_attachment *att;
467
Brian Paulea4fe662006-03-26 05:22:17 +0000468 _glthread_LOCK_MUTEX(fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +0000469
Brian Paul84716042005-11-16 04:05:54 +0000470 att = _mesa_get_attachment(ctx, fb, attachment);
471 ASSERT(att);
Brian Paule4b23562005-05-04 20:11:35 +0000472 if (rb) {
473 _mesa_set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700474 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
475 /* do stencil attachment here (depth already done above) */
476 att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
477 assert(att);
478 _mesa_set_renderbuffer_attachment(ctx, att, rb);
479 }
Marek Olšákdf818d52011-03-06 05:26:12 +0100480 rb->AttachedAnytime = GL_TRUE;
Brian Paule4b23562005-05-04 20:11:35 +0000481 }
482 else {
483 _mesa_remove_attachment(ctx, att);
484 }
Brian Paulea4fe662006-03-26 05:22:17 +0000485
Brian Paul72966362009-01-21 16:28:38 -0700486 invalidate_framebuffer(fb);
487
Brian Paulea4fe662006-03-26 05:22:17 +0000488 _glthread_UNLOCK_MUTEX(fb->Mutex);
Brian Paule4b23562005-05-04 20:11:35 +0000489}
490
491
492/**
Brian Paul62c66b32011-01-24 19:38:52 -0700493 * Fallback for ctx->Driver.ValidateFramebuffer()
494 * Check if the renderbuffer's formats are supported by the software
495 * renderer.
496 * Drivers should probably override this.
497 */
498void
499_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
500{
501 gl_buffer_index buf;
502 for (buf = 0; buf < BUFFER_COUNT; buf++) {
503 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
504 if (rb) {
505 switch (rb->_BaseFormat) {
506 case GL_ALPHA:
507 case GL_LUMINANCE_ALPHA:
508 case GL_LUMINANCE:
509 case GL_INTENSITY:
Brian Pauld3015652011-01-24 19:38:52 -0700510 case GL_RED:
511 case GL_RG:
Brian Paul62c66b32011-01-24 19:38:52 -0700512 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
513 return;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200514
515 default:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200516 switch (rb->Format) {
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200517 /* XXX This list is likely incomplete. */
Marek Olšák9d7698c2011-04-26 02:18:24 +0200518 case MESA_FORMAT_RGB9_E5_FLOAT:
519 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
520 return;
521 default:;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200522 /* render buffer format is supported by software rendering */
Marek Olšák9d7698c2011-04-26 02:18:24 +0200523 }
Brian Paul62c66b32011-01-24 19:38:52 -0700524 }
525 }
526 }
527}
528
529
530/**
Marek Olšákf8855a42013-03-14 14:22:56 +0100531 * Return true if the framebuffer has a combined depth/stencil
532 * renderbuffer attached.
533 */
534GLboolean
535_mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
536{
537 const struct gl_renderbuffer_attachment *depth =
538 &fb->Attachment[BUFFER_DEPTH];
539 const struct gl_renderbuffer_attachment *stencil =
540 &fb->Attachment[BUFFER_STENCIL];
541
542 if (depth->Type == stencil->Type) {
543 if (depth->Type == GL_RENDERBUFFER_EXT &&
544 depth->Renderbuffer == stencil->Renderbuffer)
545 return GL_TRUE;
546
547 if (depth->Type == GL_TEXTURE &&
548 depth->Texture == stencil->Texture)
549 return GL_TRUE;
550 }
551
552 return GL_FALSE;
553}
554
555
556/**
Brian Paul9f731c82009-02-17 16:47:54 -0700557 * For debug only.
558 */
559static void
560att_incomplete(const char *msg)
561{
Brian Paul93bcf782012-05-09 12:09:21 -0600562 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
563 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
564 }
Brian Paul9f731c82009-02-17 16:47:54 -0700565}
566
567
568/**
Brian Paulc26c2002009-09-15 17:20:32 -0600569 * For debug only.
570 */
571static void
572fbo_incomplete(const char *msg, int index)
573{
Brian Paul93bcf782012-05-09 12:09:21 -0600574 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
575 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
576 }
Brian Paulc26c2002009-09-15 17:20:32 -0600577}
578
579
Brian Paule67f6ee2010-10-22 11:38:23 -0600580/**
581 * Is the given base format a legal format for a color renderbuffer?
582 */
Eric Anholt059cca92011-01-02 17:58:07 -0800583GLboolean
584_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
Brian Paule67f6ee2010-10-22 11:38:23 -0600585{
586 switch (baseFormat) {
587 case GL_RGB:
588 case GL_RGBA:
589 return GL_TRUE;
Marek Olšák6e618532010-10-02 21:53:03 +0200590 case GL_LUMINANCE:
591 case GL_LUMINANCE_ALPHA:
592 case GL_INTENSITY:
Brian Paule67f6ee2010-10-22 11:38:23 -0600593 case GL_ALPHA:
Jordan Justencf300ea2012-12-27 12:41:10 -0800594 return ctx->API == API_OPENGL_COMPAT &&
595 ctx->Extensions.ARB_framebuffer_object;
Brian Paule67f6ee2010-10-22 11:38:23 -0600596 case GL_RED:
597 case GL_RG:
598 return ctx->Extensions.ARB_texture_rg;
599 default:
600 return GL_FALSE;
601 }
602}
603
604
605/**
Jordan Justen6c7fa722012-12-27 13:34:44 -0800606 * Is the given base format a legal format for a color renderbuffer?
607 */
608static GLboolean
609is_format_color_renderable(const struct gl_context *ctx, gl_format format, GLenum internalFormat)
610{
611 const GLenum baseFormat =
612 _mesa_get_format_base_format(format);
613 GLboolean valid;
614
615 valid = _mesa_is_legal_color_format(ctx, baseFormat);
616 if (!valid || _mesa_is_desktop_gl(ctx)) {
617 return valid;
618 }
619
620 /* Reject additional cases for GLES */
621 switch (internalFormat) {
622 case GL_RGBA8_SNORM:
623 case GL_RGB32F:
624 case GL_RGB32I:
625 case GL_RGB32UI:
626 case GL_RGB16F:
627 case GL_RGB16I:
628 case GL_RGB16UI:
629 case GL_RGB8_SNORM:
630 case GL_RGB8I:
631 case GL_RGB8UI:
632 case GL_SRGB8:
633 case GL_RGB9_E5:
634 case GL_RG8_SNORM:
635 case GL_R8_SNORM:
636 return GL_FALSE;
637 default:
638 break;
639 }
640
641 if (format == MESA_FORMAT_ARGB2101010 && internalFormat != GL_RGB10_A2) {
642 return GL_FALSE;
643 }
644
645 return GL_TRUE;
646}
647
648
649/**
Brian Paule67f6ee2010-10-22 11:38:23 -0600650 * Is the given base format a legal format for a depth/stencil renderbuffer?
651 */
652static GLboolean
653is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
654{
655 switch (baseFormat) {
656 case GL_DEPTH_COMPONENT:
657 case GL_DEPTH_STENCIL_EXT:
658 return GL_TRUE;
659 default:
660 return GL_FALSE;
661 }
662}
Brian Paulc26c2002009-09-15 17:20:32 -0600663
664
665/**
Brian Paulf0bbbf62005-02-09 03:50:30 +0000666 * Test if an attachment point is complete and update its Complete field.
667 * \param format if GL_COLOR, this is a color attachment point,
668 * if GL_DEPTH, this is a depth component attachment point,
669 * if GL_STENCIL, this is a stencil component attachment point.
670 */
671static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400672test_attachment_completeness(const struct gl_context *ctx, GLenum format,
Brian Paul2c6f9112005-02-24 05:47:06 +0000673 struct gl_renderbuffer_attachment *att)
Brian Paulf0bbbf62005-02-09 03:50:30 +0000674{
675 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
676
677 /* assume complete */
678 att->Complete = GL_TRUE;
679
Brian Paulf0bbbf62005-02-09 03:50:30 +0000680 /* Look for reasons why the attachment might be incomplete */
681 if (att->Type == GL_TEXTURE) {
Brian Paule4b23562005-05-04 20:11:35 +0000682 const struct gl_texture_object *texObj = att->Texture;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000683 struct gl_texture_image *texImage;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600684 GLenum baseFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000685
Brian Paule4b23562005-05-04 20:11:35 +0000686 if (!texObj) {
Brian Paul9f731c82009-02-17 16:47:54 -0700687 att_incomplete("no texobj");
Brian Paule4b23562005-05-04 20:11:35 +0000688 att->Complete = GL_FALSE;
689 return;
690 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000691
692 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
693 if (!texImage) {
Brian Paul9f731c82009-02-17 16:47:54 -0700694 att_incomplete("no teximage");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000695 att->Complete = GL_FALSE;
696 return;
697 }
698 if (texImage->Width < 1 || texImage->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700699 att_incomplete("teximage width/height=0");
Kristian Høgsberg298be2b2010-02-19 12:32:24 -0500700 printf("texobj = %u\n", texObj->Name);
701 printf("level = %d\n", att->TextureLevel);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000702 att->Complete = GL_FALSE;
703 return;
704 }
705 if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
Brian Paul9f731c82009-02-17 16:47:54 -0700706 att_incomplete("bad z offset");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000707 att->Complete = GL_FALSE;
708 return;
709 }
710
Brian Paul1f7c9142009-09-30 20:28:45 -0600711 baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600712
Brian Paulf0bbbf62005-02-09 03:50:30 +0000713 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800714 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700715 att_incomplete("bad format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000716 att->Complete = GL_FALSE;
717 return;
718 }
Brian Paul1f7c9142009-09-30 20:28:45 -0600719 if (_mesa_is_format_compressed(texImage->TexFormat)) {
Eric Anholt957f3c82009-05-15 16:24:59 -0700720 att_incomplete("compressed internalformat");
721 att->Complete = GL_FALSE;
722 return;
723 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000724 }
725 else if (format == GL_DEPTH) {
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600726 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000727 /* OK */
728 }
729 else if (ctx->Extensions.EXT_packed_depth_stencil &&
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600730 ctx->Extensions.ARB_depth_texture &&
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600731 baseFormat == GL_DEPTH_STENCIL_EXT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000732 /* OK */
733 }
734 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000735 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700736 att_incomplete("bad depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000737 return;
738 }
739 }
740 else {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600741 ASSERT(format == GL_STENCIL);
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600742 if (ctx->Extensions.EXT_packed_depth_stencil &&
743 ctx->Extensions.ARB_depth_texture &&
Brian Paul45e76d22009-10-08 20:27:27 -0600744 baseFormat == GL_DEPTH_STENCIL_EXT) {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600745 /* OK */
746 }
747 else {
748 /* no such thing as stencil-only textures */
749 att_incomplete("illegal stencil texture");
750 att->Complete = GL_FALSE;
751 return;
752 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000753 }
754 }
Brian Paule4b23562005-05-04 20:11:35 +0000755 else if (att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul45e76d22009-10-08 20:27:27 -0600756 const GLenum baseFormat =
757 _mesa_get_format_base_format(att->Renderbuffer->Format);
758
Brian Paul49918882006-03-20 15:27:55 +0000759 ASSERT(att->Renderbuffer);
760 if (!att->Renderbuffer->InternalFormat ||
761 att->Renderbuffer->Width < 1 ||
762 att->Renderbuffer->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700763 att_incomplete("0x0 renderbuffer");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000764 att->Complete = GL_FALSE;
765 return;
766 }
767 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800768 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700769 att_incomplete("bad renderbuffer color format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000770 att->Complete = GL_FALSE;
771 return;
772 }
773 }
774 else if (format == GL_DEPTH) {
Brian Paul45e76d22009-10-08 20:27:27 -0600775 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000776 /* OK */
777 }
778 else if (ctx->Extensions.EXT_packed_depth_stencil &&
Brian Paul45e76d22009-10-08 20:27:27 -0600779 baseFormat == GL_DEPTH_STENCIL_EXT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000780 /* OK */
781 }
782 else {
Brian Paul9f731c82009-02-17 16:47:54 -0700783 att_incomplete("bad renderbuffer depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000784 att->Complete = GL_FALSE;
785 return;
786 }
787 }
788 else {
789 assert(format == GL_STENCIL);
Brian Paul45e76d22009-10-08 20:27:27 -0600790 if (baseFormat == GL_STENCIL_INDEX) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000791 /* OK */
792 }
793 else if (ctx->Extensions.EXT_packed_depth_stencil &&
Brian Paul45e76d22009-10-08 20:27:27 -0600794 baseFormat == GL_DEPTH_STENCIL_EXT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000795 /* OK */
796 }
797 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000798 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700799 att_incomplete("bad renderbuffer stencil format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000800 return;
801 }
802 }
803 }
Brian Paule4b23562005-05-04 20:11:35 +0000804 else {
805 ASSERT(att->Type == GL_NONE);
806 /* complete */
807 return;
808 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000809}
810
811
812/**
813 * Test if the given framebuffer object is complete and update its
814 * Status field with the results.
Brian Paul3528f692009-01-22 15:13:18 -0700815 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
816 * driver to make hardware-specific validation/completeness checks.
Brian Paule4b23562005-05-04 20:11:35 +0000817 * Also update the framebuffer's Width and Height fields if the
818 * framebuffer is complete.
Brian Paulf0bbbf62005-02-09 03:50:30 +0000819 */
Brian Paule4b23562005-05-04 20:11:35 +0000820void
Brian Paulf9288542010-10-22 11:25:14 -0600821_mesa_test_framebuffer_completeness(struct gl_context *ctx,
822 struct gl_framebuffer *fb)
Brian Paulf0bbbf62005-02-09 03:50:30 +0000823{
Brian Paul989edea2009-01-22 15:05:13 -0700824 GLuint numImages;
825 GLenum intFormat = GL_NONE; /* color buffers' internal format */
826 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
Brian Paul722d9762009-01-20 16:58:49 -0700827 GLint numSamples = -1;
Chris Forbes61d42ff2012-12-16 20:58:00 +1300828 GLint fixedSampleLocations = -1;
Brian Paule4b23562005-05-04 20:11:35 +0000829 GLint i;
Brian Paul28b014e2006-04-05 03:05:17 +0000830 GLuint j;
Jordan Justen5da82882013-04-18 10:20:05 -0700831 bool layer_count_valid = false;
832 GLuint layer_count = 0, att_layer_count;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000833
Brian Paul36ede892012-01-12 09:17:23 -0700834 assert(_mesa_is_user_fbo(fb));
Brian Paulc7264412005-06-01 00:50:23 +0000835
Marek Olšáke06d6162012-08-04 13:37:03 +0200836 /* we're changing framebuffer fields here */
837 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
838
Brian Paulf0bbbf62005-02-09 03:50:30 +0000839 numImages = 0;
Brian Paule4b23562005-05-04 20:11:35 +0000840 fb->Width = 0;
841 fb->Height = 0;
Marek Olšák21d407c2013-03-28 01:50:21 +0100842 fb->_AllColorBuffersFixedPoint = GL_TRUE;
Marek Olšák755648c2013-03-28 01:56:01 +0100843 fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000844
Brian Paul989edea2009-01-22 15:05:13 -0700845 /* Start at -2 to more easily loop over all attachment points.
846 * -2: depth buffer
847 * -1: stencil buffer
848 * >=0: color buffer
849 */
Brian Paule4b23562005-05-04 20:11:35 +0000850 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +0000851 struct gl_renderbuffer_attachment *att;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000852 GLenum f;
Brian Paulca1b5512011-02-28 18:23:23 -0700853 gl_format attFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000854
Brian Paul1bc59bf2009-01-22 15:07:34 -0700855 /*
856 * XXX for ARB_fbo, only check color buffers that are named by
857 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
858 */
859
Brian Paul989edea2009-01-22 15:05:13 -0700860 /* check for attachment completeness
861 */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000862 if (i == -2) {
Brian Paule4b23562005-05-04 20:11:35 +0000863 att = &fb->Attachment[BUFFER_DEPTH];
Brian Paulf0bbbf62005-02-09 03:50:30 +0000864 test_attachment_completeness(ctx, GL_DEPTH, att);
865 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +0000866 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000867 fbo_incomplete("depth attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000868 return;
869 }
870 }
871 else if (i == -1) {
Brian Paule4b23562005-05-04 20:11:35 +0000872 att = &fb->Attachment[BUFFER_STENCIL];
Brian Paulf0bbbf62005-02-09 03:50:30 +0000873 test_attachment_completeness(ctx, GL_STENCIL, att);
874 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +0000875 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000876 fbo_incomplete("stencil attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000877 return;
878 }
879 }
880 else {
Brian Paule4b23562005-05-04 20:11:35 +0000881 att = &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paulf0bbbf62005-02-09 03:50:30 +0000882 test_attachment_completeness(ctx, GL_COLOR, att);
883 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +0000884 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000885 fbo_incomplete("color attachment incomplete", i);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000886 return;
887 }
888 }
889
Brian Paul989edea2009-01-22 15:05:13 -0700890 /* get width, height, format of the renderbuffer/texture
891 */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000892 if (att->Type == GL_TEXTURE) {
Eric Anholte98c39c2013-05-10 11:51:01 -0700893 const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
Brian Paul989edea2009-01-22 15:05:13 -0700894 minWidth = MIN2(minWidth, texImg->Width);
895 maxWidth = MAX2(maxWidth, texImg->Width);
896 minHeight = MIN2(minHeight, texImg->Height);
897 maxHeight = MAX2(maxHeight, texImg->Height);
Brian Paula9fc8ba2005-10-05 01:48:07 +0000898 f = texImg->_BaseFormat;
Brian Paulca1b5512011-02-28 18:23:23 -0700899 attFormat = texImg->TexFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000900 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +1300901
Jordan Justen6c7fa722012-12-27 13:34:44 -0800902 if (!is_format_color_renderable(ctx, attFormat, texImg->InternalFormat) &&
Brian Paule67f6ee2010-10-22 11:38:23 -0600903 !is_legal_depth_format(ctx, f)) {
Brian Pauled7f3ae2005-06-07 15:03:40 +0000904 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000905 fbo_incomplete("texture attachment incomplete", -1);
Brian Pauled7f3ae2005-06-07 15:03:40 +0000906 return;
907 }
Chris Forbes61d42ff2012-12-16 20:58:00 +1300908
909 if (numSamples < 0)
910 numSamples = texImg->NumSamples;
911 else if (numSamples != texImg->NumSamples) {
912 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
913 fbo_incomplete("inconsistent sample count", -1);
914 return;
915 }
916
917 if (fixedSampleLocations < 0)
918 fixedSampleLocations = texImg->FixedSampleLocations;
919 else if (fixedSampleLocations != texImg->FixedSampleLocations) {
920 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
921 fbo_incomplete("inconsistent fixed sample locations", -1);
922 return;
923 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000924 }
925 else if (att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul989edea2009-01-22 15:05:13 -0700926 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
927 maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
928 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
929 maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000930 f = att->Renderbuffer->InternalFormat;
Brian Paulca1b5512011-02-28 18:23:23 -0700931 attFormat = att->Renderbuffer->Format;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000932 numImages++;
Chris Forbes61d42ff2012-12-16 20:58:00 +1300933
934 if (numSamples < 0)
935 numSamples = att->Renderbuffer->NumSamples;
936 else if (numSamples != att->Renderbuffer->NumSamples) {
937 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
938 fbo_incomplete("inconsistent sample count", -1);
939 return;
940 }
941
942 /* RENDERBUFFER has fixedSampleLocations implicitly true */
943 if (fixedSampleLocations < 0)
944 fixedSampleLocations = GL_TRUE;
945 else if (fixedSampleLocations != GL_TRUE) {
946 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
947 fbo_incomplete("inconsistent fixed sample locations", -1);
948 return;
949 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000950 }
951 else {
952 assert(att->Type == GL_NONE);
953 continue;
954 }
955
Brian Paulc7d18372010-10-23 09:38:45 -0600956 /* check if integer color */
Brian Paulca1b5512011-02-28 18:23:23 -0700957 fb->_IntegerColor = _mesa_is_format_integer_color(attFormat);
Brian Paulc7d18372010-10-23 09:38:45 -0600958
Marek Olšák755648c2013-03-28 01:56:01 +0100959 /* Update _AllColorBuffersFixedPoint and _HasSNormOrFloatColorBuffer. */
Marek Olšák21d407c2013-03-28 01:50:21 +0100960 if (i >= 0) {
961 GLenum type = _mesa_get_format_datatype(attFormat);
962
963 fb->_AllColorBuffersFixedPoint =
964 fb->_AllColorBuffersFixedPoint &&
965 (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
Marek Olšák755648c2013-03-28 01:56:01 +0100966
967 fb->_HasSNormOrFloatColorBuffer =
968 fb->_HasSNormOrFloatColorBuffer ||
969 type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
Marek Olšák21d407c2013-03-28 01:50:21 +0100970 }
971
Chris Forbes61d42ff2012-12-16 20:58:00 +1300972 /* Error-check width, height, format */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000973 if (numImages == 1) {
Chris Forbes61d42ff2012-12-16 20:58:00 +1300974 /* save format */
Brian Paul722d9762009-01-20 16:58:49 -0700975 if (i >= 0) {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000976 intFormat = f;
Brian Paul722d9762009-01-20 16:58:49 -0700977 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000978 }
979 else {
Brian Paul989edea2009-01-22 15:05:13 -0700980 if (!ctx->Extensions.ARB_framebuffer_object) {
981 /* check that width, height, format are same */
982 if (minWidth != maxWidth || minHeight != maxHeight) {
983 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
984 fbo_incomplete("width or height mismatch", -1);
985 return;
986 }
Brian Paul45bd5c42011-12-16 08:44:43 -0700987 /* check that all color buffers are the same format */
Brian Paul989edea2009-01-22 15:05:13 -0700988 if (intFormat != GL_NONE && f != intFormat) {
989 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
990 fbo_incomplete("format mismatch", -1);
991 return;
992 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000993 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000994 }
Marek Olšáka82227c2012-06-15 17:21:05 +0200995
996 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
997 */
998 if (att->Type == GL_RENDERBUFFER &&
999 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1000 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1001 fbo_incomplete("unsupported renderbuffer format", i);
1002 return;
1003 }
Jordan Justen5da82882013-04-18 10:20:05 -07001004
1005 /* Check that layered rendering is consistent. */
1006 att_layer_count = att->Layered ? att->Renderbuffer->Depth : 0;
1007 if (!layer_count_valid) {
1008 layer_count = att_layer_count;
1009 layer_count_valid = true;
1010 } else if (layer_count != att_layer_count) {
1011 if (layer_count == 0 || att_layer_count == 0) {
1012 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1013 fbo_incomplete("framebuffer attachment layer mode is inconsistent", i);
1014 } else {
1015 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB;
1016 fbo_incomplete("framebuffer attachment layer count is inconsistent", i);
1017 }
1018 return;
1019 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001020 }
1021
Jordan Justen5da82882013-04-18 10:20:05 -07001022 fb->Layered = layer_count > 0;
1023
Jordan Justen09714c02012-07-19 11:27:16 -07001024 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001025 /* Check that all DrawBuffers are present */
1026 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
1027 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1028 const struct gl_renderbuffer_attachment *att
1029 = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
1030 assert(att);
1031 if (att->Type == GL_NONE) {
1032 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1033 fbo_incomplete("missing drawbuffer", j);
1034 return;
1035 }
1036 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001037 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001038
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001039 /* Check that the ReadBuffer is present */
1040 if (fb->ColorReadBuffer != GL_NONE) {
1041 const struct gl_renderbuffer_attachment *att
1042 = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
1043 assert(att);
1044 if (att->Type == GL_NONE) {
1045 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
Brian Paul49918882006-03-20 15:27:55 +00001046 fbo_incomplete("missing readbuffer", -1);
Kristian Høgsberge88cef32010-05-24 16:56:12 -04001047 return;
1048 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001049 }
1050 }
1051
1052 if (numImages == 0) {
Brian Paule4b23562005-05-04 20:11:35 +00001053 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +00001054 fbo_incomplete("no attachments", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +00001055 return;
1056 }
Brian Paulf0bbbf62005-02-09 03:50:30 +00001057
Brian Paul3528f692009-01-22 15:13:18 -07001058 /* Provisionally set status = COMPLETE ... */
Brian Paule4b23562005-05-04 20:11:35 +00001059 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
Brian Paul3528f692009-01-22 15:13:18 -07001060
Brian Paul777a2ef2009-01-22 15:17:42 -07001061 /* ... but the driver may say the FB is incomplete.
1062 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1063 * if anything.
1064 */
Brian Paul3528f692009-01-22 15:13:18 -07001065 if (ctx->Driver.ValidateFramebuffer) {
1066 ctx->Driver.ValidateFramebuffer(ctx, fb);
Brian Paul1f32c412009-01-19 17:34:19 -07001067 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1068 fbo_incomplete("driver marked FBO as incomplete", -1);
1069 }
Brian Paul3528f692009-01-22 15:13:18 -07001070 }
1071
1072 if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
1073 /*
1074 * Note that if ARB_framebuffer_object is supported and the attached
1075 * renderbuffers/textures are different sizes, the framebuffer
1076 * width/height will be set to the smallest width/height.
1077 */
1078 fb->Width = minWidth;
1079 fb->Height = minHeight;
Brian Paul38768db2009-01-27 09:49:27 -07001080
1081 /* finally, update the visual info for the framebuffer */
Eric Anholt059cca92011-01-02 17:58:07 -08001082 _mesa_update_framebuffer_visual(ctx, fb);
Brian Paul3528f692009-01-22 15:13:18 -07001083 }
Brian Paule4b23562005-05-04 20:11:35 +00001084}
Brian Paulf0bbbf62005-02-09 03:50:30 +00001085
1086
Brian Paul1864c7d2005-02-08 03:46:37 +00001087GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001088_mesa_IsRenderbuffer(GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001089{
Brian Paulddc82ee2005-02-05 19:56:45 +00001090 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +00001091 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Brian Paulbc6cced2005-10-04 15:01:27 +00001092 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00001093 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paulbc6cced2005-10-04 15:01:27 +00001094 if (rb != NULL && rb != &DummyRenderbuffer)
1095 return GL_TRUE;
1096 }
1097 return GL_FALSE;
Brian Paulddc82ee2005-02-05 19:56:45 +00001098}
1099
1100
Brian Paul1864c7d2005-02-08 03:46:37 +00001101void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001102_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001103{
Brian42aaa542007-03-25 10:39:36 -06001104 struct gl_renderbuffer *newRb;
Brian Paulddc82ee2005-02-05 19:56:45 +00001105 GET_CURRENT_CONTEXT(ctx);
1106
Brian Paul3deaa012005-02-07 05:08:24 +00001107 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul4de18fb2009-11-02 15:30:51 -07001108 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00001109 return;
1110 }
1111
Brian Paul800e5532009-11-02 15:39:39 -07001112 /* No need to flush here since the render buffer binding has no
1113 * effect on rendering state.
1114 */
Brian Paul474f28e2005-10-08 14:41:17 +00001115
Brian Paul3deaa012005-02-07 05:08:24 +00001116 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00001117 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001118 if (newRb == &DummyRenderbuffer) {
1119 /* ID was reserved, but no real renderbuffer object made yet */
1120 newRb = NULL;
1121 }
Ian Romanicka13f9df2012-12-01 10:50:57 -08001122 else if (!newRb
1123 && _mesa_is_desktop_gl(ctx)
1124 && ctx->Extensions.ARB_framebuffer_object) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07001125 /* All RB IDs must be Gen'd */
1126 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
1127 return;
1128 }
1129
Brian Paul3deaa012005-02-07 05:08:24 +00001130 if (!newRb) {
1131 /* create new renderbuffer object */
Brian Paul2c6f9112005-02-24 05:47:06 +00001132 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
Brian Paul3deaa012005-02-07 05:08:24 +00001133 if (!newRb) {
1134 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
1135 return;
1136 }
Brian Paul2c6f9112005-02-24 05:47:06 +00001137 ASSERT(newRb->AllocStorage);
Brian Paul1864c7d2005-02-08 03:46:37 +00001138 _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
Brian42aaa542007-03-25 10:39:36 -06001139 newRb->RefCount = 1; /* referenced by hash table */
Brian Paul3deaa012005-02-07 05:08:24 +00001140 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001141 }
Brian Paul463642c2005-02-08 02:06:00 +00001142 else {
1143 newRb = NULL;
1144 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001145
Brian Paul1864c7d2005-02-08 03:46:37 +00001146 ASSERT(newRb != &DummyRenderbuffer);
1147
Brian42aaa542007-03-25 10:39:36 -06001148 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
Brian Paulddc82ee2005-02-05 19:56:45 +00001149}
1150
1151
Brian Pauld0f13fa2009-01-21 11:17:45 -07001152/**
1153 * If the given renderbuffer is anywhere attached to the framebuffer, detach
1154 * the renderbuffer.
1155 * This is used when a renderbuffer object is deleted.
1156 * The spec calls for unbinding.
1157 */
1158static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001159detach_renderbuffer(struct gl_context *ctx,
Brian Pauld0f13fa2009-01-21 11:17:45 -07001160 struct gl_framebuffer *fb,
1161 struct gl_renderbuffer *rb)
1162{
1163 GLuint i;
1164 for (i = 0; i < BUFFER_COUNT; i++) {
1165 if (fb->Attachment[i].Renderbuffer == rb) {
1166 _mesa_remove_attachment(ctx, &fb->Attachment[i]);
1167 }
1168 }
Brian Paul72966362009-01-21 16:28:38 -07001169 invalidate_framebuffer(fb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07001170}
1171
1172
Brian Paul1864c7d2005-02-08 03:46:37 +00001173void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001174_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001175{
1176 GLint i;
1177 GET_CURRENT_CONTEXT(ctx);
1178
Brian Paul474f28e2005-10-08 14:41:17 +00001179 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00001180
1181 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001182 if (renderbuffers[i] > 0) {
1183 struct gl_renderbuffer *rb;
Brian Paulea4fe662006-03-26 05:22:17 +00001184 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
Brian Paul3deaa012005-02-07 05:08:24 +00001185 if (rb) {
Brian Paul91802fd2005-10-04 16:01:02 +00001186 /* check if deleting currently bound renderbuffer object */
1187 if (rb == ctx->CurrentRenderbuffer) {
1188 /* bind default */
1189 ASSERT(rb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001190 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
Brian Paul91802fd2005-10-04 16:01:02 +00001191 }
1192
Brian Paul36ede892012-01-12 09:17:23 -07001193 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
Brian Pauld0f13fa2009-01-21 11:17:45 -07001194 detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
1195 }
Brian Paul36ede892012-01-12 09:17:23 -07001196 if (_mesa_is_user_fbo(ctx->ReadBuffer)
Brian Paulfc8c4a32011-06-16 07:31:58 -06001197 && ctx->ReadBuffer != ctx->DrawBuffer) {
Brian Pauld0f13fa2009-01-21 11:17:45 -07001198 detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
1199 }
1200
Brian42aaa542007-03-25 10:39:36 -06001201 /* Remove from hash table immediately, to free the ID.
1202 * But the object will not be freed until it's no longer
1203 * referenced anywhere else.
1204 */
Brian Paul3deaa012005-02-07 05:08:24 +00001205 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00001206
Brian Paul1864c7d2005-02-08 03:46:37 +00001207 if (rb != &DummyRenderbuffer) {
Brian42aaa542007-03-25 10:39:36 -06001208 /* no longer referenced by hash table */
1209 _mesa_reference_renderbuffer(&rb, NULL);
Brian Paul3deaa012005-02-07 05:08:24 +00001210 }
1211 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001212 }
1213 }
1214}
1215
1216
Brian Paul1864c7d2005-02-08 03:46:37 +00001217void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001218_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001219{
1220 GET_CURRENT_CONTEXT(ctx);
1221 GLuint first;
1222 GLint i;
1223
Brian Paulddc82ee2005-02-05 19:56:45 +00001224 if (n < 0) {
1225 _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
1226 return;
1227 }
1228
1229 if (!renderbuffers)
1230 return;
1231
1232 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1233
1234 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001235 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001236 renderbuffers[i] = name;
Brian Paul1864c7d2005-02-08 03:46:37 +00001237 /* insert dummy placeholder into hash table */
Brian Paulddc82ee2005-02-05 19:56:45 +00001238 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
Brian Paul1864c7d2005-02-08 03:46:37 +00001239 _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
Brian Paulddc82ee2005-02-05 19:56:45 +00001240 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
Brian Paulddc82ee2005-02-05 19:56:45 +00001241 }
1242}
1243
1244
Brian Pauld9468c92005-02-10 16:08:07 +00001245/**
Brian Paulf41bbc72011-01-24 19:38:52 -07001246 * Given an internal format token for a render buffer, return the
Brian Paul976ea9d2011-01-24 19:38:52 -07001247 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
1248 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
1249 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
Brian Paulf41bbc72011-01-24 19:38:52 -07001250 *
Brian Paul976ea9d2011-01-24 19:38:52 -07001251 * This is similar to _mesa_base_tex_format() but the set of valid
1252 * internal formats is different.
Brian Paulf41bbc72011-01-24 19:38:52 -07001253 *
Brian Paul976ea9d2011-01-24 19:38:52 -07001254 * Note that even if a format is determined to be legal here, validation
Brian Paulb3cfcdf2011-01-28 20:25:26 -07001255 * of the FBO may fail if the format is not supported by the driver/GPU.
Brian Paul976ea9d2011-01-24 19:38:52 -07001256 *
1257 * \param internalFormat as passed to glRenderbufferStorage()
1258 * \return the base internal format, or 0 if internalFormat is illegal
Brian Pauld9468c92005-02-10 16:08:07 +00001259 */
Brian Paul59e0faa2006-03-15 17:48:00 +00001260GLenum
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001261_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
Brian Paul463642c2005-02-08 02:06:00 +00001262{
Brian Paul976ea9d2011-01-24 19:38:52 -07001263 /*
1264 * Notes: some formats such as alpha, luminance, etc. were added
1265 * with GL_ARB_framebuffer_object.
1266 */
Brian Paul463642c2005-02-08 02:06:00 +00001267 switch (internalFormat) {
Brian Paulf41bbc72011-01-24 19:38:52 -07001268 case GL_ALPHA:
1269 case GL_ALPHA4:
1270 case GL_ALPHA8:
1271 case GL_ALPHA12:
1272 case GL_ALPHA16:
Paul Berrydbd61352012-11-27 12:26:51 -08001273 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001274 ? GL_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07001275 case GL_LUMINANCE:
1276 case GL_LUMINANCE4:
1277 case GL_LUMINANCE8:
1278 case GL_LUMINANCE12:
1279 case GL_LUMINANCE16:
Paul Berrydbd61352012-11-27 12:26:51 -08001280 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001281 ? GL_LUMINANCE : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07001282 case GL_LUMINANCE_ALPHA:
1283 case GL_LUMINANCE4_ALPHA4:
1284 case GL_LUMINANCE6_ALPHA2:
1285 case GL_LUMINANCE8_ALPHA8:
1286 case GL_LUMINANCE12_ALPHA4:
1287 case GL_LUMINANCE12_ALPHA12:
1288 case GL_LUMINANCE16_ALPHA16:
Paul Berrydbd61352012-11-27 12:26:51 -08001289 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001290 ? GL_LUMINANCE_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07001291 case GL_INTENSITY:
1292 case GL_INTENSITY4:
1293 case GL_INTENSITY8:
1294 case GL_INTENSITY12:
1295 case GL_INTENSITY16:
Paul Berrydbd61352012-11-27 12:26:51 -08001296 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001297 ? GL_INTENSITY : 0;
1298 case GL_RGB8:
1299 return GL_RGB;
Brian Paulf41bbc72011-01-24 19:38:52 -07001300 case GL_RGB:
1301 case GL_R3_G3_B2:
1302 case GL_RGB4:
1303 case GL_RGB5:
Brian Paulf41bbc72011-01-24 19:38:52 -07001304 case GL_RGB10:
1305 case GL_RGB12:
1306 case GL_RGB16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001307 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001308 case GL_SRGB8_EXT:
Matt Turnercbef5372012-11-20 13:45:03 -08001309 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001310 case GL_RGBA4:
1311 case GL_RGB5_A1:
1312 case GL_RGBA8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001313 return GL_RGBA;
1314 case GL_RGBA:
1315 case GL_RGBA2:
Brian Paulf41bbc72011-01-24 19:38:52 -07001316 case GL_RGBA12:
1317 case GL_RGBA16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001318 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
1319 case GL_RGB10_A2:
Brian Paulf41bbc72011-01-24 19:38:52 -07001320 case GL_SRGB8_ALPHA8_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001321 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001322 case GL_STENCIL_INDEX:
1323 case GL_STENCIL_INDEX1_EXT:
1324 case GL_STENCIL_INDEX4_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00001325 case GL_STENCIL_INDEX16_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001326 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
1327 * OpenGL ES, but Mesa does not currently support them.
1328 */
1329 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
1330 case GL_STENCIL_INDEX8_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00001331 return GL_STENCIL_INDEX;
1332 case GL_DEPTH_COMPONENT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001333 case GL_DEPTH_COMPONENT32:
1334 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
Brian Paul2c6f9112005-02-24 05:47:06 +00001335 case GL_DEPTH_COMPONENT16:
1336 case GL_DEPTH_COMPONENT24:
Brian Paulf0bbbf62005-02-09 03:50:30 +00001337 return GL_DEPTH_COMPONENT;
Brian Paulf41bbc72011-01-24 19:38:52 -07001338 case GL_DEPTH_STENCIL_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001339 return _mesa_is_desktop_gl(ctx)
1340 && ctx->Extensions.EXT_packed_depth_stencil
1341 ? GL_DEPTH_STENCIL_EXT : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001342 case GL_DEPTH24_STENCIL8_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001343 return ctx->Extensions.EXT_packed_depth_stencil
1344 ? GL_DEPTH_STENCIL_EXT : 0;
Marek Olšák11652802011-06-01 15:48:51 +02001345 case GL_DEPTH_COMPONENT32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001346 return ctx->Version >= 30
Paul Berrydbd61352012-11-27 12:26:51 -08001347 || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07001348 ? GL_DEPTH_COMPONENT : 0;
Marek Olšák11652802011-06-01 15:48:51 +02001349 case GL_DEPTH32F_STENCIL8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001350 return ctx->Version >= 30
Paul Berrydbd61352012-11-27 12:26:51 -08001351 || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07001352 ? GL_DEPTH_STENCIL : 0;
Brian Pauld3015652011-01-24 19:38:52 -07001353 case GL_RED:
Brian Pauld3015652011-01-24 19:38:52 -07001354 case GL_R16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001355 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1356 ? GL_RED : 0;
1357 case GL_R8:
1358 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1359 ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07001360 case GL_RG:
Brian Pauld3015652011-01-24 19:38:52 -07001361 case GL_RG16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001362 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1363 ? GL_RG : 0;
1364 case GL_RG8:
1365 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1366 ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01001367 /* signed normalized texture formats */
Ian Romanickf0c99d02012-07-27 08:31:12 -07001368 case GL_RED_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001369 case GL_R8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001370 case GL_R16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001371 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1372 ? GL_RED : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07001373 case GL_RG_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001374 case GL_RG8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001375 case GL_RG16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001376 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1377 ? GL_RG : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07001378 case GL_RGB_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001379 case GL_RGB8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001380 case GL_RGB16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001381 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1382 ? GL_RGB : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07001383 case GL_RGBA_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001384 case GL_RGBA8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001385 case GL_RGBA16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001386 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1387 ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01001388 case GL_ALPHA_SNORM:
1389 case GL_ALPHA8_SNORM:
1390 case GL_ALPHA16_SNORM:
Paul Berrydbd61352012-11-27 12:26:51 -08001391 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001392 ctx->Extensions.EXT_texture_snorm &&
Marek Olšák0be36992011-03-18 13:44:51 +01001393 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001394 case GL_R16F:
1395 case GL_R32F:
Jordan Justen119002a2013-01-10 17:29:27 -08001396 return ((_mesa_is_desktop_gl(ctx) &&
1397 ctx->Extensions.ARB_texture_rg &&
1398 ctx->Extensions.ARB_texture_float) ||
1399 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1400 ? GL_RED : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001401 case GL_RG16F:
1402 case GL_RG32F:
Jordan Justen119002a2013-01-10 17:29:27 -08001403 return ((_mesa_is_desktop_gl(ctx) &&
1404 ctx->Extensions.ARB_texture_rg &&
1405 ctx->Extensions.ARB_texture_float) ||
1406 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1407 ? GL_RG : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001408 case GL_RGB16F:
1409 case GL_RGB32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001410 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07001411 ? GL_RGB : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001412 case GL_RGBA16F:
1413 case GL_RGBA32F:
Jordan Justen119002a2013-01-10 17:29:27 -08001414 return ((_mesa_is_desktop_gl(ctx) &&
1415 ctx->Extensions.ARB_texture_float) ||
1416 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Ian Romanickf0c99d02012-07-27 08:31:12 -07001417 ? GL_RGBA : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001418 case GL_ALPHA16F_ARB:
1419 case GL_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001420 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001421 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001422 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1423 case GL_LUMINANCE16F_ARB:
1424 case GL_LUMINANCE32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001425 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001426 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001427 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1428 case GL_LUMINANCE_ALPHA16F_ARB:
1429 case GL_LUMINANCE_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001430 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001431 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001432 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1433 case GL_INTENSITY16F_ARB:
1434 case GL_INTENSITY32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001435 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001436 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001437 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
Marek Olšák9d7698c2011-04-26 02:18:24 +02001438 case GL_RGB9_E5:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001439 return (_mesa_is_desktop_gl(ctx)
1440 && ctx->Extensions.EXT_texture_shared_exponent)
Matt Turnercbef5372012-11-20 13:45:03 -08001441 ? GL_RGB : 0;
Marek Olšák631d23d2011-04-26 02:27:25 +02001442 case GL_R11F_G11F_B10F:
Jordan Justen119002a2013-01-10 17:29:27 -08001443 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
1444 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Matt Turnercbef5372012-11-20 13:45:03 -08001445 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001446
1447 case GL_RGBA8UI_EXT:
1448 case GL_RGBA16UI_EXT:
1449 case GL_RGBA32UI_EXT:
1450 case GL_RGBA8I_EXT:
1451 case GL_RGBA16I_EXT:
1452 case GL_RGBA32I_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001453 return ctx->Version >= 30
1454 || (_mesa_is_desktop_gl(ctx) &&
1455 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001456
1457 case GL_RGB8UI_EXT:
1458 case GL_RGB16UI_EXT:
1459 case GL_RGB32UI_EXT:
1460 case GL_RGB8I_EXT:
1461 case GL_RGB16I_EXT:
1462 case GL_RGB32I_EXT:
Ian Romanicka86d6292012-12-03 11:55:12 -08001463 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
1464 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001465 case GL_R8UI:
1466 case GL_R8I:
1467 case GL_R16UI:
1468 case GL_R16I:
1469 case GL_R32UI:
1470 case GL_R32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001471 return ctx->Version >= 30
1472 || (_mesa_is_desktop_gl(ctx) &&
1473 ctx->Extensions.ARB_texture_rg &&
1474 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001475
1476 case GL_RG8UI:
1477 case GL_RG8I:
1478 case GL_RG16UI:
1479 case GL_RG16I:
1480 case GL_RG32UI:
1481 case GL_RG32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001482 return ctx->Version >= 30
1483 || (_mesa_is_desktop_gl(ctx) &&
1484 ctx->Extensions.ARB_texture_rg &&
1485 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
Brian Paul45bd5c42011-12-16 08:44:43 -07001486
Dave Airlie9c697a92011-10-04 20:59:40 +01001487 case GL_INTENSITY8I_EXT:
1488 case GL_INTENSITY8UI_EXT:
1489 case GL_INTENSITY16I_EXT:
1490 case GL_INTENSITY16UI_EXT:
1491 case GL_INTENSITY32I_EXT:
1492 case GL_INTENSITY32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001493 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001494 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01001495 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1496
1497 case GL_LUMINANCE8I_EXT:
1498 case GL_LUMINANCE8UI_EXT:
1499 case GL_LUMINANCE16I_EXT:
1500 case GL_LUMINANCE16UI_EXT:
1501 case GL_LUMINANCE32I_EXT:
1502 case GL_LUMINANCE32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001503 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001504 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01001505 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1506
1507 case GL_LUMINANCE_ALPHA8I_EXT:
1508 case GL_LUMINANCE_ALPHA8UI_EXT:
1509 case GL_LUMINANCE_ALPHA16I_EXT:
1510 case GL_LUMINANCE_ALPHA16UI_EXT:
1511 case GL_LUMINANCE_ALPHA32I_EXT:
1512 case GL_LUMINANCE_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001513 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001514 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01001515 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
Dave Airlief449be62011-11-27 16:21:02 +00001516
Marek Olšák636802f2012-01-22 20:21:36 +01001517 case GL_ALPHA8I_EXT:
1518 case GL_ALPHA8UI_EXT:
1519 case GL_ALPHA16I_EXT:
1520 case GL_ALPHA16UI_EXT:
1521 case GL_ALPHA32I_EXT:
1522 case GL_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001523 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001524 ctx->Extensions.EXT_texture_integer &&
Marek Olšák636802f2012-01-22 20:21:36 +01001525 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1526
Dave Airlief449be62011-11-27 16:21:02 +00001527 case GL_RGB10_A2UI:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001528 return (_mesa_is_desktop_gl(ctx) &&
1529 ctx->Extensions.ARB_texture_rgb10_a2ui)
1530 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Marek Olšák1a06e842012-07-12 14:07:41 +02001531
1532 case GL_RGB565:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001533 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
1534 ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001535 default:
Eric Anholt65c41d52011-01-13 10:05:50 -08001536 return 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001537 }
Brian Paul463642c2005-02-08 02:06:00 +00001538}
1539
1540
Marek Olšákdf818d52011-03-06 05:26:12 +01001541/**
1542 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
1543 */
1544static void
1545invalidate_rb(GLuint key, void *data, void *userData)
1546{
1547 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
1548 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
1549
1550 /* If this is a user-created FBO */
Brian Paul36ede892012-01-12 09:17:23 -07001551 if (_mesa_is_user_fbo(fb)) {
Marek Olšákdf818d52011-03-06 05:26:12 +01001552 GLuint i;
1553 for (i = 0; i < BUFFER_COUNT; i++) {
1554 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1555 if (att->Type == GL_RENDERBUFFER &&
1556 att->Renderbuffer == rb) {
1557 /* Mark fb status as indeterminate to force re-validation */
1558 fb->_Status = 0;
Marek Olšáka674ef72011-03-07 23:33:36 +01001559 return;
Marek Olšákdf818d52011-03-06 05:26:12 +01001560 }
1561 }
1562 }
1563}
1564
1565
Brian Paul4f3514e2009-01-22 15:19:56 -07001566/** sentinal value, see below */
1567#define NO_SAMPLES 1000
1568
1569
1570/**
Paul Berry1a1db172012-11-06 08:57:59 -08001571 * Helper function used by _mesa_RenderbufferStorage() and
Brian Paul4f3514e2009-01-22 15:19:56 -07001572 * _mesa_RenderbufferStorageMultisample().
Paul Berry1a1db172012-11-06 08:57:59 -08001573 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
Brian Paul4f3514e2009-01-22 15:19:56 -07001574 */
1575static void
1576renderbuffer_storage(GLenum target, GLenum internalFormat,
1577 GLsizei width, GLsizei height, GLsizei samples)
Brian Paulddc82ee2005-02-05 19:56:45 +00001578{
Brian Paul4f3514e2009-01-22 15:19:56 -07001579 const char *func = samples == NO_SAMPLES ?
Jordan Justen275620c2013-01-12 14:19:30 -08001580 "glRenderbufferStorage" : "glRenderbufferStorageMultisample";
Brian Paul2c6f9112005-02-24 05:47:06 +00001581 struct gl_renderbuffer *rb;
Brian Paul463642c2005-02-08 02:06:00 +00001582 GLenum baseFormat;
Chris Forbes90b5a242013-02-06 20:42:53 +13001583 GLenum sample_count_error;
Brian Paulddc82ee2005-02-05 19:56:45 +00001584 GET_CURRENT_CONTEXT(ctx);
1585
Jordan Justen275620c2013-01-12 14:19:30 -08001586 if (MESA_VERBOSE & VERBOSE_API) {
1587 if (samples == NO_SAMPLES)
1588 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
1589 func,
1590 _mesa_lookup_enum_by_nr(target),
1591 _mesa_lookup_enum_by_nr(internalFormat),
1592 width, height);
1593 else
1594 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
1595 func,
1596 _mesa_lookup_enum_by_nr(target),
1597 _mesa_lookup_enum_by_nr(internalFormat),
1598 width, height, samples);
1599 }
1600
Brian Paul463642c2005-02-08 02:06:00 +00001601 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul4f3514e2009-01-22 15:19:56 -07001602 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00001603 return;
1604 }
1605
Brian Paul59e0faa2006-03-15 17:48:00 +00001606 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
Brian Paul463642c2005-02-08 02:06:00 +00001607 if (baseFormat == 0) {
Jordan Justen119002a2013-01-10 17:29:27 -08001608 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
1609 func, _mesa_lookup_enum_by_nr(internalFormat));
Brian Paulddc82ee2005-02-05 19:56:45 +00001610 return;
1611 }
1612
Yuanhan Liu49f84472011-10-25 15:36:59 +08001613 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Brian Paul4f3514e2009-01-22 15:19:56 -07001614 _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00001615 return;
1616 }
1617
Yuanhan Liu49f84472011-10-25 15:36:59 +08001618 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Brian Paul4f3514e2009-01-22 15:19:56 -07001619 _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
1620 return;
1621 }
1622
1623 if (samples == NO_SAMPLES) {
1624 /* NumSamples == 0 indicates non-multisampling */
1625 samples = 0;
1626 }
Chris Forbes21a2dfa2013-03-25 23:19:07 +13001627 else {
1628 /* check the sample count;
1629 * note: driver may choose to use more samples than what's requested
1630 */
1631 sample_count_error = _mesa_check_sample_count(ctx, target,
1632 internalFormat, samples);
1633 if (sample_count_error != GL_NO_ERROR) {
1634 _mesa_error(ctx, sample_count_error, "%s(samples)", func);
1635 return;
1636 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001637 }
1638
Brian Paul2c6f9112005-02-24 05:47:06 +00001639 rb = ctx->CurrentRenderbuffer;
Brian Paul2c6f9112005-02-24 05:47:06 +00001640 if (!rb) {
Vinson Leec5dde532010-09-02 16:03:32 -07001641 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
Brian Paul463642c2005-02-08 02:06:00 +00001642 return;
1643 }
1644
Brian Paul474f28e2005-10-08 14:41:17 +00001645 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1646
Brian Paul311bcf52005-11-18 02:24:14 +00001647 if (rb->InternalFormat == internalFormat &&
Brian Paul13abf912006-04-13 19:17:13 +00001648 rb->Width == (GLuint) width &&
Eric Anholt0e8d1562012-01-11 13:46:43 -08001649 rb->Height == (GLuint) height &&
1650 rb->NumSamples == samples) {
Brian Paul311bcf52005-11-18 02:24:14 +00001651 /* no change in allocation needed */
1652 return;
1653 }
1654
Brian Paulea4fe662006-03-26 05:22:17 +00001655 /* These MUST get set by the AllocStorage func */
Brian Paul45e76d22009-10-08 20:27:27 -06001656 rb->Format = MESA_FORMAT_NONE;
Brian Paul4f3514e2009-01-22 15:19:56 -07001657 rb->NumSamples = samples;
Brian Paulea4fe662006-03-26 05:22:17 +00001658
Brian Paul2c6f9112005-02-24 05:47:06 +00001659 /* Now allocate the storage */
1660 ASSERT(rb->AllocStorage);
1661 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
1662 /* No error - check/set fields now */
Marek Olšáka82227c2012-06-15 17:21:05 +02001663 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
Brian Paul13abf912006-04-13 19:17:13 +00001664 assert(rb->Width == (GLuint) width);
1665 assert(rb->Height == (GLuint) height);
Brian Paulea4fe662006-03-26 05:22:17 +00001666 rb->InternalFormat = internalFormat;
Brian Paula8dafe72010-02-25 19:03:55 -07001667 rb->_BaseFormat = baseFormat;
Brian Paul45e76d22009-10-08 20:27:27 -06001668 assert(rb->_BaseFormat != 0);
Brian Paul2c6f9112005-02-24 05:47:06 +00001669 }
1670 else {
1671 /* Probably ran out of memory - clear the fields */
1672 rb->Width = 0;
1673 rb->Height = 0;
Brian Paul45e76d22009-10-08 20:27:27 -06001674 rb->Format = MESA_FORMAT_NONE;
Brian Paul2c6f9112005-02-24 05:47:06 +00001675 rb->InternalFormat = GL_NONE;
1676 rb->_BaseFormat = GL_NONE;
Brian Paul4f3514e2009-01-22 15:19:56 -07001677 rb->NumSamples = 0;
Brian Paul463642c2005-02-08 02:06:00 +00001678 }
1679
Marek Olšákdf818d52011-03-06 05:26:12 +01001680 /* Invalidate the framebuffers the renderbuffer is attached in. */
1681 if (rb->AttachedAnytime) {
1682 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
1683 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001684}
1685
Brian Paul23c5b212010-05-28 13:33:03 -06001686
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001687void GLAPIENTRY
Brian Paul23c5b212010-05-28 13:33:03 -06001688_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001689{
Brian Paul51b79922010-02-24 11:57:26 -07001690 struct gl_renderbuffer *rb;
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001691 GET_CURRENT_CONTEXT(ctx);
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001692
Chia-I Wu2002e4d02010-04-06 17:46:17 +08001693 if (!ctx->Extensions.OES_EGL_image) {
1694 _mesa_error(ctx, GL_INVALID_OPERATION,
1695 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
1696 return;
1697 }
1698
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001699 if (target != GL_RENDERBUFFER) {
Brian Paul23c5b212010-05-28 13:33:03 -06001700 _mesa_error(ctx, GL_INVALID_ENUM,
1701 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001702 return;
1703 }
1704
1705 rb = ctx->CurrentRenderbuffer;
1706 if (!rb) {
Brian Paul23c5b212010-05-28 13:33:03 -06001707 _mesa_error(ctx, GL_INVALID_OPERATION,
1708 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001709 return;
1710 }
1711
1712 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1713
1714 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
1715}
Brian Paulddc82ee2005-02-05 19:56:45 +00001716
Brian Paul23c5b212010-05-28 13:33:03 -06001717
Brian Paul45e76d22009-10-08 20:27:27 -06001718/**
Paul Berry1a1db172012-11-06 08:57:59 -08001719 * Helper function for _mesa_GetRenderbufferParameteriv() and
1720 * _mesa_GetFramebufferAttachmentParameteriv()
Brian Paul45e76d22009-10-08 20:27:27 -06001721 * We have to be careful to respect the base format. For example, if a
1722 * renderbuffer/texture was created with internalFormat=GL_RGB but the
1723 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
1724 * we need to return zero.
1725 */
1726static GLint
1727get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
1728{
Brian Paulf0b6e9a2011-11-23 15:33:45 -07001729 if (_mesa_base_format_has_channel(baseFormat, pname))
1730 return _mesa_get_format_bits(format, pname);
1731 else
Brian Paul45e76d22009-10-08 20:27:27 -06001732 return 0;
Brian Paul45e76d22009-10-08 20:27:27 -06001733}
1734
1735
1736
Brian Paul1864c7d2005-02-08 03:46:37 +00001737void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001738_mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
Brian Paul4f3514e2009-01-22 15:19:56 -07001739 GLsizei width, GLsizei height)
1740{
Brian Paul722d9762009-01-20 16:58:49 -07001741 /* GL_ARB_fbo says calling this function is equivalent to calling
1742 * glRenderbufferStorageMultisample() with samples=0. We pass in
1743 * a token value here just for error reporting purposes.
1744 */
Brian Paul4f3514e2009-01-22 15:19:56 -07001745 renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
1746}
1747
1748
1749void GLAPIENTRY
Brian Paul777a2ef2009-01-22 15:17:42 -07001750_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
Brian Paul4f3514e2009-01-22 15:19:56 -07001751 GLenum internalFormat,
Brian Paul777a2ef2009-01-22 15:17:42 -07001752 GLsizei width, GLsizei height)
1753{
Brian Paul4f3514e2009-01-22 15:19:56 -07001754 renderbuffer_storage(target, internalFormat, width, height, samples);
Brian Paul777a2ef2009-01-22 15:17:42 -07001755}
1756
Brian Paul23c5b212010-05-28 13:33:03 -06001757
1758/**
1759 * OpenGL ES version of glRenderBufferStorage.
1760 */
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04001761void GLAPIENTRY
1762_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1763 GLsizei width, GLsizei height)
1764{
1765 switch (internalFormat) {
1766 case GL_RGB565:
1767 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
1768 /* choose a closest format */
1769 internalFormat = GL_RGB5;
1770 break;
1771 default:
1772 break;
1773 }
Brian Paul777a2ef2009-01-22 15:17:42 -07001774
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04001775 renderbuffer_storage(target, internalFormat, width, height, 0);
1776}
Brian Paul777a2ef2009-01-22 15:17:42 -07001777
Brian Paul23c5b212010-05-28 13:33:03 -06001778
Brian Paul777a2ef2009-01-22 15:17:42 -07001779void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001780_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
Brian Paulddc82ee2005-02-05 19:56:45 +00001781{
Brian Paul722d9762009-01-20 16:58:49 -07001782 struct gl_renderbuffer *rb;
Brian Paulddc82ee2005-02-05 19:56:45 +00001783 GET_CURRENT_CONTEXT(ctx);
1784
Brian Paul463642c2005-02-08 02:06:00 +00001785 if (target != GL_RENDERBUFFER_EXT) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001786 _mesa_error(ctx, GL_INVALID_ENUM,
1787 "glGetRenderbufferParameterivEXT(target)");
1788 return;
1789 }
1790
Brian Paul722d9762009-01-20 16:58:49 -07001791 rb = ctx->CurrentRenderbuffer;
1792 if (!rb) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001793 _mesa_error(ctx, GL_INVALID_OPERATION,
1794 "glGetRenderbufferParameterivEXT");
1795 return;
1796 }
1797
Brian Paul800e5532009-11-02 15:39:39 -07001798 /* No need to flush here since we're just quering state which is
1799 * not effected by rendering.
1800 */
Brian Paul474f28e2005-10-08 14:41:17 +00001801
Brian Paul463642c2005-02-08 02:06:00 +00001802 switch (pname) {
1803 case GL_RENDERBUFFER_WIDTH_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07001804 *params = rb->Width;
Brian Paul463642c2005-02-08 02:06:00 +00001805 return;
1806 case GL_RENDERBUFFER_HEIGHT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07001807 *params = rb->Height;
Brian Paul463642c2005-02-08 02:06:00 +00001808 return;
1809 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07001810 *params = rb->InternalFormat;
Brian Paul463642c2005-02-08 02:06:00 +00001811 return;
Brian Paul1b939532005-05-31 23:55:21 +00001812 case GL_RENDERBUFFER_RED_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001813 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001814 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001815 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001816 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001817 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
Brian Paul45e76d22009-10-08 20:27:27 -06001818 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
Brian Paul1b939532005-05-31 23:55:21 +00001819 break;
Brian Paul722d9762009-01-20 16:58:49 -07001820 case GL_RENDERBUFFER_SAMPLES:
Ian Romanickae86ebf2012-07-27 07:49:49 -07001821 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
1822 || _mesa_is_gles3(ctx)) {
Brian Paul722d9762009-01-20 16:58:49 -07001823 *params = rb->NumSamples;
1824 break;
1825 }
1826 /* fallthrough */
Brian Paul463642c2005-02-08 02:06:00 +00001827 default:
1828 _mesa_error(ctx, GL_INVALID_ENUM,
1829 "glGetRenderbufferParameterivEXT(target)");
1830 return;
1831 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001832}
1833
1834
Brian Paul1864c7d2005-02-08 03:46:37 +00001835GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001836_mesa_IsFramebuffer(GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001837{
Brian Paulddc82ee2005-02-05 19:56:45 +00001838 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +00001839 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Brian Paulbc6cced2005-10-04 15:01:27 +00001840 if (framebuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00001841 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
Brian Paulbc6cced2005-10-04 15:01:27 +00001842 if (rb != NULL && rb != &DummyFramebuffer)
1843 return GL_TRUE;
1844 }
1845 return GL_FALSE;
Brian Paulddc82ee2005-02-05 19:56:45 +00001846}
1847
1848
briana492ab72009-11-10 15:33:31 -07001849/**
1850 * Check if any of the attachments of the given framebuffer are textures
1851 * (render to texture). Call ctx->Driver.RenderTexture() for such
1852 * attachments.
1853 */
Brian Paulea4fe662006-03-26 05:22:17 +00001854static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001855check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paulea4fe662006-03-26 05:22:17 +00001856{
1857 GLuint i;
1858 ASSERT(ctx->Driver.RenderTexture);
briana65b84d2009-11-10 18:02:03 -07001859
Brian Paul36ede892012-01-12 09:17:23 -07001860 if (_mesa_is_winsys_fbo(fb))
briana65b84d2009-11-10 18:02:03 -07001861 return; /* can't render to texture with winsys framebuffers */
1862
Brian Paulea4fe662006-03-26 05:22:17 +00001863 for (i = 0; i < BUFFER_COUNT; i++) {
1864 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Eric Anholte98c39c2013-05-10 11:51:01 -07001865 if (att->Texture && att->Renderbuffer->TexImage) {
Brian Paulea4fe662006-03-26 05:22:17 +00001866 ctx->Driver.RenderTexture(ctx, fb, att);
1867 }
1868 }
1869}
1870
1871
Brian Paul0e31e022005-12-01 00:25:00 +00001872/**
1873 * Examine all the framebuffer's attachments to see if any are textures.
1874 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
1875 * notify the device driver that the texture image may have changed.
1876 */
1877static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001878check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paul0e31e022005-12-01 00:25:00 +00001879{
Brian Paul36ede892012-01-12 09:17:23 -07001880 if (_mesa_is_winsys_fbo(fb))
briana65b84d2009-11-10 18:02:03 -07001881 return; /* can't render to texture with winsys framebuffers */
1882
Brian Paul0e31e022005-12-01 00:25:00 +00001883 if (ctx->Driver.FinishRenderTexture) {
1884 GLuint i;
1885 for (i = 0; i < BUFFER_COUNT; i++) {
1886 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Eric Anholtc810e672013-05-10 12:36:43 -07001887 struct gl_renderbuffer *rb = att->Renderbuffer;
1888 if (rb && rb->NeedsFinishRenderTexture) {
Eric Anholta5b04522013-05-10 12:17:52 -07001889 ctx->Driver.FinishRenderTexture(ctx, rb);
Brian Paul0e31e022005-12-01 00:25:00 +00001890 }
1891 }
1892 }
1893}
1894
1895
Brian Paul1864c7d2005-02-08 03:46:37 +00001896void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001897_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001898{
briane6f60d32009-11-10 15:47:34 -07001899 struct gl_framebuffer *newDrawFb, *newReadFb;
briand96e55f2009-11-10 15:50:22 -07001900 struct gl_framebuffer *oldDrawFb, *oldReadFb;
Brian Paul0bffb112005-11-08 14:45:48 +00001901 GLboolean bindReadBuf, bindDrawBuf;
Brian Paulddc82ee2005-02-05 19:56:45 +00001902 GET_CURRENT_CONTEXT(ctx);
1903
Brian Paul1bc59bf2009-01-22 15:07:34 -07001904#ifdef DEBUG
1905 if (ctx->Extensions.ARB_framebuffer_object) {
1906 ASSERT(ctx->Extensions.EXT_framebuffer_object);
1907 ASSERT(ctx->Extensions.EXT_framebuffer_blit);
1908 }
1909#endif
1910
Brian Paulea4fe662006-03-26 05:22:17 +00001911 if (!ctx->Extensions.EXT_framebuffer_object) {
1912 _mesa_error(ctx, GL_INVALID_OPERATION,
1913 "glBindFramebufferEXT(unsupported)");
1914 return;
1915 }
1916
Brian Paul0bffb112005-11-08 14:45:48 +00001917 switch (target) {
Brian Paul0bffb112005-11-08 14:45:48 +00001918 case GL_DRAW_FRAMEBUFFER_EXT:
1919 if (!ctx->Extensions.EXT_framebuffer_blit) {
1920 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1921 return;
1922 }
1923 bindDrawBuf = GL_TRUE;
1924 bindReadBuf = GL_FALSE;
1925 break;
1926 case GL_READ_FRAMEBUFFER_EXT:
1927 if (!ctx->Extensions.EXT_framebuffer_blit) {
1928 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1929 return;
1930 }
1931 bindDrawBuf = GL_FALSE;
1932 bindReadBuf = GL_TRUE;
1933 break;
Brian Paul0bffb112005-11-08 14:45:48 +00001934 case GL_FRAMEBUFFER_EXT:
1935 bindDrawBuf = GL_TRUE;
1936 bindReadBuf = GL_TRUE;
1937 break;
1938 default:
Brian Pauleba4ff62005-09-06 21:22:16 +00001939 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00001940 return;
1941 }
1942
Brian Paul3deaa012005-02-07 05:08:24 +00001943 if (framebuffer) {
Brian Paule4b23562005-05-04 20:11:35 +00001944 /* Binding a user-created framebuffer object */
briane6f60d32009-11-10 15:47:34 -07001945 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
1946 if (newDrawFb == &DummyFramebuffer) {
Brian Paul923b6fc2005-02-08 04:08:56 +00001947 /* ID was reserved, but no real framebuffer object made yet */
briane6f60d32009-11-10 15:47:34 -07001948 newDrawFb = NULL;
Brian Paul1864c7d2005-02-08 03:46:37 +00001949 }
Ian Romanicka13f9df2012-12-01 10:50:57 -08001950 else if (!newDrawFb
1951 && _mesa_is_desktop_gl(ctx)
1952 && ctx->Extensions.ARB_framebuffer_object) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07001953 /* All FBO IDs must be Gen'd */
1954 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
1955 return;
1956 }
1957
briane6f60d32009-11-10 15:47:34 -07001958 if (!newDrawFb) {
Brian Paul3deaa012005-02-07 05:08:24 +00001959 /* create new framebuffer object */
briane6f60d32009-11-10 15:47:34 -07001960 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
1961 if (!newDrawFb) {
Brian Paul3deaa012005-02-07 05:08:24 +00001962 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
1963 return;
1964 }
briane6f60d32009-11-10 15:47:34 -07001965 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
Brian Paul3deaa012005-02-07 05:08:24 +00001966 }
briane6f60d32009-11-10 15:47:34 -07001967 newReadFb = newDrawFb;
Brian Paul3deaa012005-02-07 05:08:24 +00001968 }
Brian Paul463642c2005-02-08 02:06:00 +00001969 else {
Brian Paule4b23562005-05-04 20:11:35 +00001970 /* Binding the window system framebuffer (which was originally set
1971 * with MakeCurrent).
1972 */
briane6f60d32009-11-10 15:47:34 -07001973 newDrawFb = ctx->WinSysDrawBuffer;
1974 newReadFb = ctx->WinSysReadBuffer;
Brian Paul3deaa012005-02-07 05:08:24 +00001975 }
1976
briane6f60d32009-11-10 15:47:34 -07001977 ASSERT(newDrawFb);
1978 ASSERT(newDrawFb != &DummyFramebuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001979
briana65b84d2009-11-10 18:02:03 -07001980 /* save pointers to current/old framebuffers */
briand96e55f2009-11-10 15:50:22 -07001981 oldDrawFb = ctx->DrawBuffer;
1982 oldReadFb = ctx->ReadBuffer;
1983
briana65b84d2009-11-10 18:02:03 -07001984 /* check if really changing bindings */
1985 if (oldDrawFb == newDrawFb)
1986 bindDrawBuf = GL_FALSE;
1987 if (oldReadFb == newReadFb)
1988 bindReadBuf = GL_FALSE;
1989
Brian Paulea4fe662006-03-26 05:22:17 +00001990 /*
Brian Paul16144632009-02-26 14:49:24 -07001991 * OK, now bind the new Draw/Read framebuffers, if they're changing.
briana65b84d2009-11-10 18:02:03 -07001992 *
1993 * We also check if we're beginning and/or ending render-to-texture.
1994 * When a framebuffer with texture attachments is unbound, call
1995 * ctx->Driver.FinishRenderTexture().
1996 * When a framebuffer with texture attachments is bound, call
1997 * ctx->Driver.RenderTexture().
1998 *
1999 * Note that if the ReadBuffer has texture attachments we don't consider
2000 * that a render-to-texture case.
Brian Paulea4fe662006-03-26 05:22:17 +00002001 */
Brian Paul0bffb112005-11-08 14:45:48 +00002002 if (bindReadBuf) {
briana65b84d2009-11-10 18:02:03 -07002003 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
brianbc569cd2009-11-10 16:00:35 -07002004
briana65b84d2009-11-10 18:02:03 -07002005 /* check if old readbuffer was render-to-texture */
2006 check_end_texture_render(ctx, oldReadFb);
2007
2008 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
Brian Paul0bffb112005-11-08 14:45:48 +00002009 }
2010
2011 if (bindDrawBuf) {
briana65b84d2009-11-10 18:02:03 -07002012 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian32d86eb2007-08-16 18:52:48 +01002013
Eric Anholta1fd13f2012-02-10 12:05:16 -08002014 /* check if old framebuffer had any texture attachments */
2015 if (oldDrawFb)
briana65b84d2009-11-10 18:02:03 -07002016 check_end_texture_render(ctx, oldDrawFb);
brianbc569cd2009-11-10 16:00:35 -07002017
briana65b84d2009-11-10 18:02:03 -07002018 /* check if newly bound framebuffer has any texture attachments */
2019 check_begin_texture_render(ctx, newDrawFb);
2020
2021 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
Brian Paul0bffb112005-11-08 14:45:48 +00002022 }
Brian Paul59e0faa2006-03-15 17:48:00 +00002023
Brian Paul16144632009-02-26 14:49:24 -07002024 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
briane6f60d32009-11-10 15:47:34 -07002025 ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
Brian Paul59e0faa2006-03-15 17:48:00 +00002026 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002027}
2028
2029
Brian Paul1864c7d2005-02-08 03:46:37 +00002030void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002031_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00002032{
2033 GLint i;
2034 GET_CURRENT_CONTEXT(ctx);
2035
Brian Paul800e5532009-11-02 15:39:39 -07002036 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00002037
2038 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00002039 if (framebuffers[i] > 0) {
2040 struct gl_framebuffer *fb;
Brian Paulea4fe662006-03-26 05:22:17 +00002041 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
Brian Paul3deaa012005-02-07 05:08:24 +00002042 if (fb) {
Brian Paule4b23562005-05-04 20:11:35 +00002043 ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
Brian Paul91802fd2005-10-04 16:01:02 +00002044
2045 /* check if deleting currently bound framebuffer object */
Erik Wien68ca19a2010-01-26 13:19:30 -07002046 if (ctx->Extensions.EXT_framebuffer_blit) {
2047 /* separate draw/read binding points */
2048 if (fb == ctx->DrawBuffer) {
2049 /* bind default */
2050 ASSERT(fb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08002051 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
Erik Wien68ca19a2010-01-26 13:19:30 -07002052 }
2053 if (fb == ctx->ReadBuffer) {
2054 /* bind default */
2055 ASSERT(fb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08002056 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
Erik Wien68ca19a2010-01-26 13:19:30 -07002057 }
Brian Pauld0f13fa2009-01-21 11:17:45 -07002058 }
Erik Wien68ca19a2010-01-26 13:19:30 -07002059 else {
2060 /* only one binding point for read/draw buffers */
2061 if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
2062 /* bind default */
2063 ASSERT(fb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08002064 _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
Brian Paul45bd5c42011-12-16 08:44:43 -07002065 }
Brian Paul91802fd2005-10-04 16:01:02 +00002066 }
2067
Brian Paul3deaa012005-02-07 05:08:24 +00002068 /* remove from hash table immediately, to free the ID */
2069 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00002070
Brian Paul1864c7d2005-02-08 03:46:37 +00002071 if (fb != &DummyFramebuffer) {
2072 /* But the object will not be freed until it's no longer
2073 * bound in any context.
2074 */
Brian Pauld5229442009-02-09 08:30:55 -07002075 _mesa_reference_framebuffer(&fb, NULL);
Brian Paul3deaa012005-02-07 05:08:24 +00002076 }
2077 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002078 }
2079 }
2080}
2081
2082
Brian Paul1864c7d2005-02-08 03:46:37 +00002083void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002084_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00002085{
2086 GET_CURRENT_CONTEXT(ctx);
2087 GLuint first;
2088 GLint i;
2089
Brian Paulddc82ee2005-02-05 19:56:45 +00002090 if (n < 0) {
2091 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
2092 return;
2093 }
2094
2095 if (!framebuffers)
2096 return;
2097
2098 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
2099
2100 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00002101 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00002102 framebuffers[i] = name;
2103 /* insert dummy placeholder into hash table */
Brian Paulddc82ee2005-02-05 19:56:45 +00002104 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
Brian Paul1864c7d2005-02-08 03:46:37 +00002105 _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
Brian Paulddc82ee2005-02-05 19:56:45 +00002106 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
Brian Paulddc82ee2005-02-05 19:56:45 +00002107 }
2108}
2109
2110
2111
Brian Paul1864c7d2005-02-08 03:46:37 +00002112GLenum GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002113_mesa_CheckFramebufferStatus(GLenum target)
Brian Paulddc82ee2005-02-05 19:56:45 +00002114{
Brian Paul0bffb112005-11-08 14:45:48 +00002115 struct gl_framebuffer *buffer;
Brian Paulddc82ee2005-02-05 19:56:45 +00002116 GET_CURRENT_CONTEXT(ctx);
2117
Brian Paule4b23562005-05-04 20:11:35 +00002118 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00002119
Jordan Justen7f867852013-01-12 19:21:54 -08002120 if (MESA_VERBOSE & VERBOSE_API)
2121 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
2122 _mesa_lookup_enum_by_nr(target));
2123
Brian Paulc6991432011-02-28 18:24:25 -07002124 buffer = get_framebuffer_target(ctx, target);
2125 if (!buffer) {
Brian Paulf0bbbf62005-02-09 03:50:30 +00002126 _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
Brian Paulc6991432011-02-28 18:24:25 -07002127 return 0;
Brian Paulddc82ee2005-02-05 19:56:45 +00002128 }
2129
Brian Paul36ede892012-01-12 09:17:23 -07002130 if (_mesa_is_winsys_fbo(buffer)) {
Brian Paulf0bbbf62005-02-09 03:50:30 +00002131 /* The window system / default framebuffer is always complete */
2132 return GL_FRAMEBUFFER_COMPLETE_EXT;
2133 }
2134
Brian Paul800e5532009-11-02 15:39:39 -07002135 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00002136
Brian Paul72966362009-01-21 16:28:38 -07002137 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
2138 _mesa_test_framebuffer_completeness(ctx, buffer);
2139 }
2140
Brian Paul0bffb112005-11-08 14:45:48 +00002141 return buffer->_Status;
Brian Paulddc82ee2005-02-05 19:56:45 +00002142}
2143
Brian Paul45bd5c42011-12-16 08:44:43 -07002144
Chad Versacebf8ad172011-11-10 10:19:20 -08002145/**
2146 * Replicate the src attachment point. Used by framebuffer_texture() when
2147 * the same texture is attached at GL_DEPTH_ATTACHMENT and
2148 * GL_STENCIL_ATTACHMENT.
2149 */
2150static void
2151reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
2152 gl_buffer_index dst,
2153 gl_buffer_index src)
2154{
2155 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
2156 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
Brian Paulddc82ee2005-02-05 19:56:45 +00002157
Chad Versacebf8ad172011-11-10 10:19:20 -08002158 assert(src_att->Texture != NULL);
Brian Paul45bd5c42011-12-16 08:44:43 -07002159 assert(src_att->Renderbuffer != NULL);
Chad Versacebf8ad172011-11-10 10:19:20 -08002160
2161 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
2162 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
2163 dst_att->Type = src_att->Type;
2164 dst_att->Complete = src_att->Complete;
2165 dst_att->TextureLevel = src_att->TextureLevel;
2166 dst_att->Zoffset = src_att->Zoffset;
2167}
Brian Paulddc82ee2005-02-05 19:56:45 +00002168
Brian Paul45bd5c42011-12-16 08:44:43 -07002169
Brian Paulddc82ee2005-02-05 19:56:45 +00002170/**
Brian Paul534cbbe2012-03-12 11:03:59 -06002171 * Common code called by glFramebufferTexture1D/2D/3DEXT() and
2172 * glFramebufferTextureLayerEXT().
2173 * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll
2174 * get textarget=0 in that case.
Brian Paulddc82ee2005-02-05 19:56:45 +00002175 */
Brian Paulea4fe662006-03-26 05:22:17 +00002176static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002177framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002178 GLenum attachment, GLenum textarget, GLuint texture,
Jordan Justena6280802013-04-18 10:08:50 -07002179 GLint level, GLint zoffset, GLboolean layered)
Brian Paulddc82ee2005-02-05 19:56:45 +00002180{
Brian Paul2c6f9112005-02-24 05:47:06 +00002181 struct gl_renderbuffer_attachment *att;
Brian Paulea4fe662006-03-26 05:22:17 +00002182 struct gl_texture_object *texObj = NULL;
2183 struct gl_framebuffer *fb;
Anuj Phogatcc5b0ff2012-03-12 10:39:48 -07002184 GLenum maxLevelsTarget;
Brian Paulddc82ee2005-02-05 19:56:45 +00002185
Brian Paulc6991432011-02-28 18:24:25 -07002186 fb = get_framebuffer_target(ctx, target);
2187 if (!fb) {
Brian Paulea4fe662006-03-26 05:22:17 +00002188 _mesa_error(ctx, GL_INVALID_ENUM,
Brian Paul5fec84a2009-01-29 15:01:09 -07002189 "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
Brian Paulddc82ee2005-02-05 19:56:45 +00002190 return;
Brian Paulea4fe662006-03-26 05:22:17 +00002191 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002192
Brian Paulea4fe662006-03-26 05:22:17 +00002193 /* check framebuffer binding */
Brian Paul36ede892012-01-12 09:17:23 -07002194 if (_mesa_is_winsys_fbo(fb)) {
Brian Paulea4fe662006-03-26 05:22:17 +00002195 _mesa_error(ctx, GL_INVALID_OPERATION,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002196 "glFramebufferTexture%sEXT", caller);
Brian Paulea4fe662006-03-26 05:22:17 +00002197 return;
2198 }
2199
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002200 /* The textarget, level, and zoffset parameters are only validated if
2201 * texture is non-zero.
2202 */
2203 if (texture) {
2204 GLboolean err = GL_TRUE;
2205
2206 texObj = _mesa_lookup_texture(ctx, texture);
2207 if (texObj != NULL) {
Ian Romanickbb372f12007-05-16 15:34:22 -07002208 if (textarget == 0) {
Brian Paul534cbbe2012-03-12 11:03:59 -06002209 /* If textarget == 0 it means we're being called by
2210 * glFramebufferTextureLayer() and textarget is not used.
2211 * The only legal texture types for that function are 3D and
2212 * 1D/2D arrays textures.
2213 */
Ian Romanickbb372f12007-05-16 15:34:22 -07002214 err = (texObj->Target != GL_TEXTURE_3D) &&
2215 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
Dave Airliee0e7e292012-11-03 20:41:08 +10002216 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) &&
Chris Forbesd04a4dd2012-11-24 21:46:56 +13002217 (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY) &&
2218 (texObj->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
Ian Romanickbb372f12007-05-16 15:34:22 -07002219 }
2220 else {
Brian Paul534cbbe2012-03-12 11:03:59 -06002221 /* Make sure textarget is consistent with the texture's type */
Ian Romanickbb372f12007-05-16 15:34:22 -07002222 err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
Brian Paul2efa3d42011-11-18 17:39:00 -07002223 ? !_mesa_is_cube_face(textarget)
Ian Romanickbb372f12007-05-16 15:34:22 -07002224 : (texObj->Target != textarget);
2225 }
Brian Paulea4fe662006-03-26 05:22:17 +00002226 }
Brian Paul7a2e32d2010-03-10 10:54:24 -07002227 else {
2228 /* can't render to a non-existant texture */
2229 _mesa_error(ctx, GL_INVALID_OPERATION,
2230 "glFramebufferTexture%sEXT(non existant texture)",
2231 caller);
2232 return;
2233 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002234
2235 if (err) {
Brian Paulea4fe662006-03-26 05:22:17 +00002236 _mesa_error(ctx, GL_INVALID_OPERATION,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002237 "glFramebufferTexture%sEXT(texture target mismatch)",
2238 caller);
Brian Paulea4fe662006-03-26 05:22:17 +00002239 return;
2240 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002241
2242 if (texObj->Target == GL_TEXTURE_3D) {
Brian Paulea4fe662006-03-26 05:22:17 +00002243 const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
2244 if (zoffset < 0 || zoffset >= maxSize) {
2245 _mesa_error(ctx, GL_INVALID_VALUE,
Ian Romanickbb372f12007-05-16 15:34:22 -07002246 "glFramebufferTexture%sEXT(zoffset)", caller);
Brian Paulea4fe662006-03-26 05:22:17 +00002247 return;
2248 }
2249 }
Ian Romanickbb372f12007-05-16 15:34:22 -07002250 else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
Dave Airliee0e7e292012-11-03 20:41:08 +10002251 (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) ||
Chris Forbesd04a4dd2012-11-24 21:46:56 +13002252 (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
2253 (texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
Brian Paul859c3872012-11-04 16:43:44 -07002254 if (zoffset < 0 ||
2255 zoffset >= (GLint) ctx->Const.MaxArrayTextureLayers) {
Ian Romanickbb372f12007-05-16 15:34:22 -07002256 _mesa_error(ctx, GL_INVALID_VALUE,
2257 "glFramebufferTexture%sEXT(layer)", caller);
2258 return;
2259 }
2260 }
2261
Anuj Phogatcc5b0ff2012-03-12 10:39:48 -07002262 maxLevelsTarget = textarget ? textarget : texObj->Target;
Brian Paul45bd5c42011-12-16 08:44:43 -07002263 if ((level < 0) ||
Anuj Phogatcc5b0ff2012-03-12 10:39:48 -07002264 (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002265 _mesa_error(ctx, GL_INVALID_VALUE,
2266 "glFramebufferTexture%sEXT(level)", caller);
2267 return;
2268 }
Brian Paulea4fe662006-03-26 05:22:17 +00002269 }
2270
2271 att = _mesa_get_attachment(ctx, fb, attachment);
Brian Paul3deaa012005-02-07 05:08:24 +00002272 if (att == NULL) {
2273 _mesa_error(ctx, GL_INVALID_ENUM,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002274 "glFramebufferTexture%sEXT(attachment)", caller);
Brian Paul3deaa012005-02-07 05:08:24 +00002275 return;
2276 }
2277
Brian Paul800e5532009-11-02 15:39:39 -07002278 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paul474f28e2005-10-08 14:41:17 +00002279
Brian Paulea4fe662006-03-26 05:22:17 +00002280 _glthread_LOCK_MUTEX(fb->Mutex);
2281 if (texObj) {
Chad Versacebf8ad172011-11-10 10:19:20 -08002282 if (attachment == GL_DEPTH_ATTACHMENT &&
Paul Berryb9819a02012-04-13 21:50:08 -07002283 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
2284 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
2285 _mesa_tex_target_to_face(textarget) ==
2286 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
2287 zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
Chad Versacebf8ad172011-11-10 10:19:20 -08002288 /* The texture object is already attached to the stencil attachment
2289 * point. Don't create a new renderbuffer; just reuse the stencil
2290 * attachment's. This is required to prevent a GL error in
2291 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
2292 */
2293 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
2294 BUFFER_STENCIL);
2295 } else if (attachment == GL_STENCIL_ATTACHMENT &&
Paul Berryb9819a02012-04-13 21:50:08 -07002296 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
2297 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
2298 _mesa_tex_target_to_face(textarget) ==
2299 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
2300 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
2301 /* As above, but with depth and stencil transposed. */
Chad Versacebf8ad172011-11-10 10:19:20 -08002302 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
2303 BUFFER_DEPTH);
2304 } else {
2305 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
Jordan Justena6280802013-04-18 10:08:50 -07002306 level, zoffset, layered);
Chad Versacebf8ad172011-11-10 10:19:20 -08002307 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2308 /* Above we created a new renderbuffer and attached it to the
2309 * depth attachment point. Now attach it to the stencil attachment
2310 * point too.
2311 */
2312 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2313 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
2314 BUFFER_DEPTH);
2315 }
2316 }
2317
Brian Paul2897cee2009-01-29 09:20:18 -07002318 /* Set the render-to-texture flag. We'll check this flag in
2319 * glTexImage() and friends to determine if we need to revalidate
2320 * any FBOs that might be rendering into this texture.
2321 * This flag never gets cleared since it's non-trivial to determine
2322 * when all FBOs might be done rendering to this texture. That's OK
2323 * though since it's uncommon to render to a texture then repeatedly
2324 * call glTexImage() to change images in the texture.
2325 */
2326 texObj->_RenderToTexture = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +00002327 }
2328 else {
Brian Paul519b23b2006-03-20 18:51:57 +00002329 _mesa_remove_attachment(ctx, att);
Chad Versacebf8ad172011-11-10 10:19:20 -08002330 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2331 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2332 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
2333 }
Brian Paul3deaa012005-02-07 05:08:24 +00002334 }
Brian Paul72966362009-01-21 16:28:38 -07002335
2336 invalidate_framebuffer(fb);
2337
Brian Paulea4fe662006-03-26 05:22:17 +00002338 _glthread_UNLOCK_MUTEX(fb->Mutex);
2339}
2340
2341
2342
2343void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002344_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
Brian Paulea4fe662006-03-26 05:22:17 +00002345 GLenum textarget, GLuint texture, GLint level)
2346{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002347 GET_CURRENT_CONTEXT(ctx);
2348
Brian Paul352cab42011-08-18 14:35:27 -06002349 if (texture != 0) {
2350 GLboolean error;
2351
2352 switch (textarget) {
2353 case GL_TEXTURE_1D:
2354 error = GL_FALSE;
2355 break;
Brian Paul3e9dc512011-08-18 15:59:33 -06002356 case GL_TEXTURE_1D_ARRAY:
2357 error = !ctx->Extensions.EXT_texture_array;
2358 break;
Brian Paul352cab42011-08-18 14:35:27 -06002359 default:
2360 error = GL_TRUE;
2361 }
2362
2363 if (error) {
2364 _mesa_error(ctx, GL_INVALID_OPERATION,
2365 "glFramebufferTexture1DEXT(textarget=%s)",
2366 _mesa_lookup_enum_by_nr(textarget));
2367 return;
2368 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002369 }
2370
2371 framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
Jordan Justena6280802013-04-18 10:08:50 -07002372 level, 0, GL_FALSE);
Brian Paulddc82ee2005-02-05 19:56:45 +00002373}
2374
2375
Brian Paul1864c7d2005-02-08 03:46:37 +00002376void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002377_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002378 GLenum textarget, GLuint texture, GLint level)
2379{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002380 GET_CURRENT_CONTEXT(ctx);
2381
Brian Paul352cab42011-08-18 14:35:27 -06002382 if (texture != 0) {
2383 GLboolean error;
2384
2385 switch (textarget) {
2386 case GL_TEXTURE_2D:
2387 error = GL_FALSE;
2388 break;
2389 case GL_TEXTURE_RECTANGLE:
Ian Romanick7f991d22012-07-27 07:22:41 -07002390 error = _mesa_is_gles(ctx)
2391 || !ctx->Extensions.NV_texture_rectangle;
Brian Paul352cab42011-08-18 14:35:27 -06002392 break;
2393 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2394 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2395 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2396 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2397 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2398 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2399 error = !ctx->Extensions.ARB_texture_cube_map;
2400 break;
Brian Paul3e9dc512011-08-18 15:59:33 -06002401 case GL_TEXTURE_2D_ARRAY:
Ian Romanick7f991d22012-07-27 07:22:41 -07002402 error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2403 || !ctx->Extensions.EXT_texture_array;
Brian Paul3e9dc512011-08-18 15:59:33 -06002404 break;
Chris Forbesd04a4dd2012-11-24 21:46:56 +13002405 case GL_TEXTURE_2D_MULTISAMPLE:
2406 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2407 error = _mesa_is_gles(ctx)
2408 || !ctx->Extensions.ARB_texture_multisample;
2409 break;
Brian Paul352cab42011-08-18 14:35:27 -06002410 default:
Chia-I Wud8ba30a2011-10-22 22:17:31 +08002411 error = GL_TRUE;
Brian Paul352cab42011-08-18 14:35:27 -06002412 }
2413
2414 if (error) {
2415 _mesa_error(ctx, GL_INVALID_OPERATION,
2416 "glFramebufferTexture2DEXT(textarget=%s)",
2417 _mesa_lookup_enum_by_nr(textarget));
2418 return;
2419 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002420 }
2421
2422 framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
Jordan Justena6280802013-04-18 10:08:50 -07002423 level, 0, GL_FALSE);
Brian Paulddc82ee2005-02-05 19:56:45 +00002424}
2425
2426
Brian Paul1864c7d2005-02-08 03:46:37 +00002427void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002428_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002429 GLenum textarget, GLuint texture,
2430 GLint level, GLint zoffset)
2431{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002432 GET_CURRENT_CONTEXT(ctx);
2433
2434 if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
Brian Paulccecc082011-08-18 11:51:48 -06002435 _mesa_error(ctx, GL_INVALID_OPERATION,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002436 "glFramebufferTexture3DEXT(textarget)");
2437 return;
2438 }
2439
2440 framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
Jordan Justena6280802013-04-18 10:08:50 -07002441 level, zoffset, GL_FALSE);
Brian Paulddc82ee2005-02-05 19:56:45 +00002442}
2443
2444
Brian Paul1864c7d2005-02-08 03:46:37 +00002445void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002446_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
Ian Romanickbb372f12007-05-16 15:34:22 -07002447 GLuint texture, GLint level, GLint layer)
2448{
2449 GET_CURRENT_CONTEXT(ctx);
2450
2451 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
Jordan Justena6280802013-04-18 10:08:50 -07002452 level, layer, GL_FALSE);
Ian Romanickbb372f12007-05-16 15:34:22 -07002453}
2454
2455
2456void GLAPIENTRY
Jordan Justen02f2bce2013-04-18 10:46:12 -07002457_mesa_FramebufferTexture(GLenum target, GLenum attachment,
2458 GLuint texture, GLint level)
2459{
2460 GET_CURRENT_CONTEXT(ctx);
2461
2462 if (ctx->Version >= 32 || ctx->Extensions.ARB_geometry_shader4) {
2463 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2464 level, 0, GL_TRUE);
2465 } else {
2466 _mesa_error(ctx, GL_INVALID_OPERATION,
2467 "unsupported function (glFramebufferTexture) called");
2468 }
2469}
2470
2471
2472void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002473_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002474 GLenum renderbufferTarget,
2475 GLuint renderbuffer)
2476{
Brian Paul2c6f9112005-02-24 05:47:06 +00002477 struct gl_renderbuffer_attachment *att;
Brian Paul0bffb112005-11-08 14:45:48 +00002478 struct gl_framebuffer *fb;
Brian Paule4b23562005-05-04 20:11:35 +00002479 struct gl_renderbuffer *rb;
Brian Paulddc82ee2005-02-05 19:56:45 +00002480 GET_CURRENT_CONTEXT(ctx);
2481
Brian Paulc6991432011-02-28 18:24:25 -07002482 fb = get_framebuffer_target(ctx, target);
2483 if (!fb) {
2484 _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00002485 return;
2486 }
2487
Brian Paul3deaa012005-02-07 05:08:24 +00002488 if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
Brian Paule4b23562005-05-04 20:11:35 +00002489 _mesa_error(ctx, GL_INVALID_ENUM,
2490 "glFramebufferRenderbufferEXT(renderbufferTarget)");
Brian Paul3deaa012005-02-07 05:08:24 +00002491 return;
2492 }
2493
Brian Paul36ede892012-01-12 09:17:23 -07002494 if (_mesa_is_winsys_fbo(fb)) {
Brian Paulab8ef282005-09-07 23:21:59 +00002495 /* Can't attach new renderbuffers to a window system framebuffer */
Brian Paul3deaa012005-02-07 05:08:24 +00002496 _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
2497 return;
2498 }
2499
Brian Paul84716042005-11-16 04:05:54 +00002500 att = _mesa_get_attachment(ctx, fb, attachment);
Brian Paul3deaa012005-02-07 05:08:24 +00002501 if (att == NULL) {
Brian Paulddc82ee2005-02-05 19:56:45 +00002502 _mesa_error(ctx, GL_INVALID_ENUM,
Brian Paul9b50cea2009-10-23 11:34:14 -06002503 "glFramebufferRenderbufferEXT(invalid attachment %s)",
2504 _mesa_lookup_enum_by_nr(attachment));
Brian Paulddc82ee2005-02-05 19:56:45 +00002505 return;
2506 }
2507
Brian Paul1864c7d2005-02-08 03:46:37 +00002508 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00002509 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00002510 if (!rb) {
Brian Paule4b23562005-05-04 20:11:35 +00002511 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paul9b50cea2009-10-23 11:34:14 -06002512 "glFramebufferRenderbufferEXT(non-existant"
2513 " renderbuffer %u)", renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00002514 return;
2515 }
Brian Pauldd973cd2011-01-12 18:14:14 -07002516 else if (rb == &DummyRenderbuffer) {
2517 /* This is what NVIDIA does */
2518 _mesa_error(ctx, GL_INVALID_VALUE,
2519 "glFramebufferRenderbufferEXT(renderbuffer %u)",
2520 renderbuffer);
2521 return;
2522 }
Brian Paul1864c7d2005-02-08 03:46:37 +00002523 }
2524 else {
Brian Paule4b23562005-05-04 20:11:35 +00002525 /* remove renderbuffer attachment */
2526 rb = NULL;
Brian Paul1864c7d2005-02-08 03:46:37 +00002527 }
Brian Paule4b23562005-05-04 20:11:35 +00002528
Brian Paula504f232010-05-27 13:05:23 -06002529 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2530 rb && rb->Format != MESA_FORMAT_NONE) {
Brian Paul30590072009-01-21 11:06:11 -07002531 /* make sure the renderbuffer is a depth/stencil format */
Brian Paula504f232010-05-27 13:05:23 -06002532 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
Brian Paul45e76d22009-10-08 20:27:27 -06002533 if (baseFormat != GL_DEPTH_STENCIL) {
Brian Paul30590072009-01-21 11:06:11 -07002534 _mesa_error(ctx, GL_INVALID_OPERATION,
2535 "glFramebufferRenderbufferEXT(renderbuffer"
2536 " is not DEPTH_STENCIL format)");
2537 return;
2538 }
2539 }
2540
2541
Brian Paul800e5532009-11-02 15:39:39 -07002542 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paul474f28e2005-10-08 14:41:17 +00002543
Brian Paule4b23562005-05-04 20:11:35 +00002544 assert(ctx->Driver.FramebufferRenderbuffer);
Brian Paul84716042005-11-16 04:05:54 +00002545 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
Brian Paul2e019182006-03-07 01:43:52 +00002546
2547 /* Some subsequent GL commands may depend on the framebuffer's visual
2548 * after the binding is updated. Update visual info now.
2549 */
Eric Anholt059cca92011-01-02 17:58:07 -08002550 _mesa_update_framebuffer_visual(ctx, fb);
Brian Paulddc82ee2005-02-05 19:56:45 +00002551}
2552
2553
Brian Paul1864c7d2005-02-08 03:46:37 +00002554void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002555_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002556 GLenum pname, GLint *params)
2557{
Brian Paul2c6f9112005-02-24 05:47:06 +00002558 const struct gl_renderbuffer_attachment *att;
Brian Paul0bffb112005-11-08 14:45:48 +00002559 struct gl_framebuffer *buffer;
Marek Olšák000896c2011-07-19 03:05:07 +02002560 GLenum err;
Brian Paulddc82ee2005-02-05 19:56:45 +00002561 GET_CURRENT_CONTEXT(ctx);
2562
Brian Pauldbe88512012-02-10 16:22:33 -07002563 /* The error differs in GL and GLES. */
Jordan Justen09714c02012-07-19 11:27:16 -07002564 err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
Marek Olšák000896c2011-07-19 03:05:07 +02002565
Brian Paulc6991432011-02-28 18:24:25 -07002566 buffer = get_framebuffer_target(ctx, target);
2567 if (!buffer) {
Brian Paulddc82ee2005-02-05 19:56:45 +00002568 _mesa_error(ctx, GL_INVALID_ENUM,
2569 "glGetFramebufferAttachmentParameterivEXT(target)");
2570 return;
2571 }
2572
Brian Paul36ede892012-01-12 09:17:23 -07002573 if (_mesa_is_winsys_fbo(buffer)) {
Ian Romanickda2e41c2011-10-03 12:04:09 -07002574 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
2575 * says:
2576 *
2577 * "If the framebuffer currently bound to target is zero, then
2578 * INVALID_OPERATION is generated."
2579 *
2580 * The EXT_framebuffer_object spec has the same wording, and the
2581 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
2582 * spec.
2583 */
Anuj Phogat2f2801f2012-12-11 20:08:13 -08002584 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2585 && !_mesa_is_gles3(ctx)) {
Ian Romanickda2e41c2011-10-03 12:04:09 -07002586 _mesa_error(ctx, GL_INVALID_OPERATION,
2587 "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
2588 return;
2589 }
Anuj Phogat2f2801f2012-12-11 20:08:13 -08002590
2591 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
2592 attachment != GL_DEPTH && attachment != GL_STENCIL) {
2593 _mesa_error(ctx, GL_INVALID_OPERATION,
2594 "glGetFramebufferAttachmentParameteriv(attachment)");
2595 return;
2596 }
Brian Paul61ec2052010-06-22 08:37:44 -06002597 /* the default / window-system FBO */
2598 att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
2599 }
2600 else {
2601 /* user-created framebuffer FBO */
2602 att = _mesa_get_attachment(ctx, buffer, attachment);
2603 }
2604
Brian Paul3deaa012005-02-07 05:08:24 +00002605 if (att == NULL) {
Brian Paulddc82ee2005-02-05 19:56:45 +00002606 _mesa_error(ctx, GL_INVALID_ENUM,
2607 "glGetFramebufferAttachmentParameterivEXT(attachment)");
2608 return;
2609 }
2610
Brian Paul30590072009-01-21 11:06:11 -07002611 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2612 /* the depth and stencil attachments must point to the same buffer */
2613 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
2614 depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
2615 stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
2616 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
2617 _mesa_error(ctx, GL_INVALID_OPERATION,
2618 "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
2619 " attachments differ)");
2620 return;
2621 }
2622 }
2623
Brian Paul800e5532009-11-02 15:39:39 -07002624 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00002625
Brian Paulddc82ee2005-02-05 19:56:45 +00002626 switch (pname) {
2627 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
Brian Paul36ede892012-01-12 09:17:23 -07002628 *params = _mesa_is_winsys_fbo(buffer)
2629 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
Brian Paul3deaa012005-02-07 05:08:24 +00002630 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002631 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00002632 if (att->Type == GL_RENDERBUFFER_EXT) {
2633 *params = att->Renderbuffer->Name;
2634 }
2635 else if (att->Type == GL_TEXTURE) {
2636 *params = att->Texture->Name;
2637 }
2638 else {
Brian Paul20cf1852010-12-03 08:23:31 -07002639 assert(att->Type == GL_NONE);
Ian Romanick0cdaa472012-07-27 07:47:28 -07002640 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
Marek Olšák000896c2011-07-19 03:05:07 +02002641 *params = 0;
2642 } else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002643 goto invalid_pname_enum;
Marek Olšák000896c2011-07-19 03:05:07 +02002644 }
Brian Paul3deaa012005-02-07 05:08:24 +00002645 }
2646 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002647 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00002648 if (att->Type == GL_TEXTURE) {
2649 *params = att->TextureLevel;
2650 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002651 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002652 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002653 "glGetFramebufferAttachmentParameterivEXT(pname)");
2654 }
Brian Paul3deaa012005-02-07 05:08:24 +00002655 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002656 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00002657 }
2658 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002659 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00002660 if (att->Type == GL_TEXTURE) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06002661 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
2662 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
2663 }
2664 else {
2665 *params = 0;
2666 }
Brian Paul3deaa012005-02-07 05:08:24 +00002667 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002668 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002669 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002670 "glGetFramebufferAttachmentParameterivEXT(pname)");
2671 }
Brian Paul3deaa012005-02-07 05:08:24 +00002672 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002673 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00002674 }
2675 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002676 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002677 if (ctx->API == API_OPENGLES) {
2678 goto invalid_pname_enum;
2679 } else if (att->Type == GL_NONE) {
2680 _mesa_error(ctx, err,
2681 "glGetFramebufferAttachmentParameterivEXT(pname)");
2682 } else if (att->Type == GL_TEXTURE) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06002683 if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
2684 *params = att->Zoffset;
2685 }
2686 else {
2687 *params = 0;
2688 }
Brian Paul3deaa012005-02-07 05:08:24 +00002689 }
2690 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002691 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00002692 }
2693 return;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002694 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002695 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2696 && !_mesa_is_gles3(ctx)) {
2697 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002698 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002699 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002700 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002701 "glGetFramebufferAttachmentParameterivEXT(pname)");
2702 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002703 else {
Marek Olšák69c8f462012-01-24 23:39:31 +01002704 if (ctx->Extensions.EXT_framebuffer_sRGB) {
Marek Olšák81ae8c62011-01-23 13:26:43 +01002705 *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
2706 }
2707 else {
2708 /* According to ARB_framebuffer_sRGB, we should return LINEAR
2709 * if the sRGB conversion is unsupported. */
2710 *params = GL_LINEAR;
2711 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002712 }
2713 return;
2714 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Paul Berrydbd61352012-11-27 12:26:51 -08002715 if ((ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07002716 && ctx->API != API_OPENGL_CORE
2717 && !_mesa_is_gles3(ctx)) {
2718 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002719 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002720 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002721 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002722 "glGetFramebufferAttachmentParameterivEXT(pname)");
2723 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002724 else {
Brian Paul45e76d22009-10-08 20:27:27 -06002725 gl_format format = att->Renderbuffer->Format;
Ian Romanickd7475c72013-01-18 17:25:57 -08002726
2727 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
2728 * 3.0.1 spec says:
2729 *
2730 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
2731 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
2732 * generate an INVALID_OPERATION error.
2733 */
2734 if (_mesa_is_gles3(ctx) && attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2735 _mesa_error(ctx, GL_INVALID_OPERATION,
2736 "glGetFramebufferAttachmentParameteriv(cannot query "
2737 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
2738 "GL_DEPTH_STENCIL_ATTACHMENT");
2739 return;
2740 }
2741
Ian Romanick55d232a2011-08-26 12:20:00 -07002742 if (format == MESA_FORMAT_S8) {
Brian Paul45e76d22009-10-08 20:27:27 -06002743 /* special cases */
2744 *params = GL_INDEX;
2745 }
Marek Olšák11652802011-06-01 15:48:51 +02002746 else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) {
2747 /* depends on the attachment parameter */
2748 if (attachment == GL_STENCIL_ATTACHMENT) {
2749 *params = GL_INDEX;
2750 }
2751 else {
2752 *params = GL_FLOAT;
2753 }
2754 }
Brian Paul45e76d22009-10-08 20:27:27 -06002755 else {
2756 *params = _mesa_get_format_datatype(format);
2757 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002758 }
2759 return;
2760 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002761 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002762 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002763 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002764 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002765 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002766 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2767 && !_mesa_is_gles3(ctx)) {
2768 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002769 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002770 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002771 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002772 "glGetFramebufferAttachmentParameterivEXT(pname)");
2773 }
Brian Paul45e76d22009-10-08 20:27:27 -06002774 else if (att->Texture) {
2775 const struct gl_texture_image *texImage =
2776 _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
2777 att->TextureLevel);
2778 if (texImage) {
2779 *params = get_component_bits(pname, texImage->_BaseFormat,
2780 texImage->TexFormat);
2781 }
2782 else {
2783 *params = 0;
2784 }
2785 }
2786 else if (att->Renderbuffer) {
2787 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
2788 att->Renderbuffer->Format);
2789 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002790 else {
Marek Olšákb9e9df72011-05-31 20:36:07 +02002791 _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
2792 " invalid FBO attachment structure");
Brian Paul1bc59bf2009-01-22 15:07:34 -07002793 }
2794 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002795 default:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002796 goto invalid_pname_enum;
Brian Paulddc82ee2005-02-05 19:56:45 +00002797 }
Ian Romanick0cdaa472012-07-27 07:47:28 -07002798
2799 return;
2800
2801invalid_pname_enum:
2802 _mesa_error(ctx, GL_INVALID_ENUM,
2803 "glGetFramebufferAttachmentParameteriv(pname)");
2804 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002805}
2806
2807
Brian Paul1864c7d2005-02-08 03:46:37 +00002808void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002809_mesa_GenerateMipmap(GLenum target)
Brian Paulddc82ee2005-02-05 19:56:45 +00002810{
Eric Anholtf80e1e72011-10-18 11:52:39 -07002811 struct gl_texture_image *srcImage;
Brian Paul463642c2005-02-08 02:06:00 +00002812 struct gl_texture_object *texObj;
Brian Paul3e9dc512011-08-18 15:59:33 -06002813 GLboolean error;
2814
Brian Paulddc82ee2005-02-05 19:56:45 +00002815 GET_CURRENT_CONTEXT(ctx);
2816
Marek Olšák1e3b4222013-04-14 22:31:50 +02002817 FLUSH_VERTICES(ctx, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00002818
2819 switch (target) {
2820 case GL_TEXTURE_1D:
Ian Romanick5b44a772012-07-27 07:24:37 -07002821 error = _mesa_is_gles(ctx);
2822 break;
Brian Paulddc82ee2005-02-05 19:56:45 +00002823 case GL_TEXTURE_2D:
Brian Paul3e9dc512011-08-18 15:59:33 -06002824 error = GL_FALSE;
2825 break;
Ian Romanick5b44a772012-07-27 07:24:37 -07002826 case GL_TEXTURE_3D:
2827 error = ctx->API == API_OPENGLES;
2828 break;
Brian Paul463642c2005-02-08 02:06:00 +00002829 case GL_TEXTURE_CUBE_MAP:
Brian Paul3e9dc512011-08-18 15:59:33 -06002830 error = !ctx->Extensions.ARB_texture_cube_map;
2831 break;
2832 case GL_TEXTURE_1D_ARRAY:
Ian Romanick5b44a772012-07-27 07:24:37 -07002833 error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array;
2834 break;
Brian Paul3e9dc512011-08-18 15:59:33 -06002835 case GL_TEXTURE_2D_ARRAY:
Ian Romanick5b44a772012-07-27 07:24:37 -07002836 error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2837 || !ctx->Extensions.EXT_texture_array;
Brian Paulddc82ee2005-02-05 19:56:45 +00002838 break;
2839 default:
Brian Paul3e9dc512011-08-18 15:59:33 -06002840 error = GL_TRUE;
2841 }
2842
2843 if (error) {
2844 _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)",
2845 _mesa_lookup_enum_by_nr(target));
Brian Paulddc82ee2005-02-05 19:56:45 +00002846 return;
2847 }
2848
Brian Paula7193952009-11-16 08:21:28 -07002849 texObj = _mesa_get_current_tex_object(ctx, target);
Brian Paul463642c2005-02-08 02:06:00 +00002850
Brian Paul652828e2009-11-16 08:25:17 -07002851 if (texObj->BaseLevel >= texObj->MaxLevel) {
2852 /* nothing to do */
2853 return;
2854 }
2855
Brian Paulecb7cc32010-12-06 15:11:41 -07002856 if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
2857 !_mesa_cube_complete(texObj)) {
2858 _mesa_error(ctx, GL_INVALID_OPERATION,
2859 "glGenerateMipmap(incomplete cube map)");
2860 return;
2861 }
2862
Keith Whitwell5ac93f82006-11-01 14:21:57 +00002863 _mesa_lock_texture(ctx, texObj);
Eric Anholtf80e1e72011-10-18 11:52:39 -07002864
2865 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
2866 if (!srcImage) {
2867 _mesa_unlock_texture(ctx, texObj);
Brian Paulf6b71572012-08-10 10:36:17 -06002868 _mesa_error(ctx, GL_INVALID_OPERATION,
2869 "glGenerateMipmap(zero size base image)");
Eric Anholtf80e1e72011-10-18 11:52:39 -07002870 return;
2871 }
2872
Anuj Phogatc0a78d72012-11-02 10:47:33 -07002873 if (_mesa_is_enum_format_integer(srcImage->InternalFormat) ||
2874 _mesa_is_depthstencil_format(srcImage->InternalFormat) ||
2875 _mesa_is_stencil_format(srcImage->InternalFormat)) {
2876 _mesa_unlock_texture(ctx, texObj);
2877 _mesa_error(ctx, GL_INVALID_OPERATION,
2878 "glGenerateMipmap(invalid internal format)");
2879 return;
2880 }
2881
Eric Anholtf849d362008-12-06 21:14:56 -08002882 if (target == GL_TEXTURE_CUBE_MAP) {
Brian Paulef6ee072009-09-15 18:09:03 -06002883 GLuint face;
Eric Anholtf849d362008-12-06 21:14:56 -08002884 for (face = 0; face < 6; face++)
2885 ctx->Driver.GenerateMipmap(ctx,
2886 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
2887 texObj);
Brian Paulef6ee072009-09-15 18:09:03 -06002888 }
2889 else {
Eric Anholtf849d362008-12-06 21:14:56 -08002890 ctx->Driver.GenerateMipmap(ctx, target, texObj);
2891 }
Keith Whitwell5ac93f82006-11-01 14:21:57 +00002892 _mesa_unlock_texture(ctx, texObj);
Brian Paulddc82ee2005-02-05 19:56:45 +00002893}
Brian Paul0bffb112005-11-08 14:45:48 +00002894
2895
Brian Paul21f8d312009-10-27 16:59:23 -06002896static const struct gl_renderbuffer_attachment *
Brian Paulb3cfcdf2011-01-28 20:25:26 -07002897find_attachment(const struct gl_framebuffer *fb,
2898 const struct gl_renderbuffer *rb)
Brian Paul21f8d312009-10-27 16:59:23 -06002899{
2900 GLuint i;
2901 for (i = 0; i < Elements(fb->Attachment); i++) {
2902 if (fb->Attachment[i].Renderbuffer == rb)
2903 return &fb->Attachment[i];
2904 }
2905 return NULL;
2906}
2907
2908
Brian Paul9b111702012-01-09 12:38:49 -07002909/**
2910 * Helper function for checking if the datatypes of color buffers are
2911 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
2912 *
2913 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
2914 * and any of the following conditions hold:
2915 * - The read buffer contains fixed-point or floating-point values and any
2916 * draw buffer contains neither fixed-point nor floating-point values.
2917 * - The read buffer contains unsigned integer values and any draw buffer
2918 * does not contain unsigned integer values.
2919 * - The read buffer contains signed integer values and any draw buffer
2920 * does not contain signed integer values."
2921 */
2922static GLboolean
2923compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat)
2924{
2925 GLenum srcType = _mesa_get_format_datatype(srcFormat);
2926 GLenum dstType = _mesa_get_format_datatype(dstFormat);
2927
2928 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
2929 assert(srcType == GL_UNSIGNED_NORMALIZED ||
2930 srcType == GL_SIGNED_NORMALIZED ||
2931 srcType == GL_FLOAT);
2932 /* Boil any of those types down to GL_FLOAT */
2933 srcType = GL_FLOAT;
2934 }
2935
2936 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
2937 assert(dstType == GL_UNSIGNED_NORMALIZED ||
2938 dstType == GL_SIGNED_NORMALIZED ||
2939 dstType == GL_FLOAT);
2940 /* Boil any of those types down to GL_FLOAT */
2941 dstType = GL_FLOAT;
2942 }
2943
2944 return srcType == dstType;
2945}
2946
Brian Paul21f8d312009-10-27 16:59:23 -06002947
Marek Olšák59272272012-07-21 15:16:15 +02002948static GLboolean
Marek Olšák135fe902012-11-28 19:07:18 +01002949compatible_resolve_formats(const struct gl_renderbuffer *readRb,
2950 const struct gl_renderbuffer *drawRb)
Marek Olšák59272272012-07-21 15:16:15 +02002951{
Marek Olšák91ca0532012-11-23 03:02:44 +01002952 GLenum readFormat, drawFormat;
2953
2954 /* The simple case where we know the backing Mesa formats are the same.
Marek Olšák59272272012-07-21 15:16:15 +02002955 */
Marek Olšák135fe902012-11-28 19:07:18 +01002956 if (_mesa_get_srgb_format_linear(readRb->Format) ==
2957 _mesa_get_srgb_format_linear(drawRb->Format)) {
Marek Olšák59272272012-07-21 15:16:15 +02002958 return GL_TRUE;
2959 }
2960
2961 /* The Mesa formats are different, so we must check whether the internal
2962 * formats are compatible.
2963 *
2964 * Under some circumstances, the user may request e.g. two GL_RGBA8
2965 * textures and get two entirely different Mesa formats like RGBA8888 and
2966 * ARGB8888. Drivers behaving like that should be able to cope with
2967 * non-matching formats by themselves, because it's not the user's fault.
Marek Olšák91ca0532012-11-23 03:02:44 +01002968 *
2969 * Blits between linear and sRGB formats are also allowed.
Marek Olšák59272272012-07-21 15:16:15 +02002970 */
Marek Olšák135fe902012-11-28 19:07:18 +01002971 readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
2972 drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
2973 readFormat = _mesa_get_linear_internalformat(readFormat);
2974 drawFormat = _mesa_get_linear_internalformat(drawFormat);
Marek Olšák91ca0532012-11-23 03:02:44 +01002975
2976 if (readFormat == drawFormat) {
Marek Olšák59272272012-07-21 15:16:15 +02002977 return GL_TRUE;
2978 }
2979
2980 return GL_FALSE;
2981}
2982
2983
2984/**
Brian Paul722d9762009-01-20 16:58:49 -07002985 * Blit rectangular region, optionally from one framebuffer to another.
2986 *
2987 * Note, if the src buffer is multisampled and the dest is not, this is
2988 * when the samples must be resolved to a single color.
2989 */
Brian Paul0bffb112005-11-08 14:45:48 +00002990void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002991_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Brian Paul0bffb112005-11-08 14:45:48 +00002992 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
2993 GLbitfield mask, GLenum filter)
2994{
Brian Paul722d9762009-01-20 16:58:49 -07002995 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
2996 GL_DEPTH_BUFFER_BIT |
2997 GL_STENCIL_BUFFER_BIT);
2998 const struct gl_framebuffer *readFb, *drawFb;
Brian Paul0bffb112005-11-08 14:45:48 +00002999 GET_CURRENT_CONTEXT(ctx);
3000
Marek Olšák1e3b4222013-04-14 22:31:50 +02003001 FLUSH_VERTICES(ctx, 0);
Brian Paul0bffb112005-11-08 14:45:48 +00003002
Brian Paul6364d752011-02-18 09:53:29 -07003003 if (MESA_VERBOSE & VERBOSE_API)
3004 _mesa_debug(ctx,
3005 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
3006 srcX0, srcY0, srcX1, srcY1,
3007 dstX0, dstY0, dstX1, dstY1,
3008 mask, _mesa_lookup_enum_by_nr(filter));
3009
Brian Paul99745402006-03-01 02:02:43 +00003010 if (ctx->NewState) {
3011 _mesa_update_state(ctx);
3012 }
3013
Brian Paul722d9762009-01-20 16:58:49 -07003014 readFb = ctx->ReadBuffer;
3015 drawFb = ctx->DrawBuffer;
3016
3017 if (!readFb || !drawFb) {
3018 /* This will normally never happen but someday we may want to
3019 * support MakeCurrent() with no drawables.
3020 */
3021 return;
Brian Paul99745402006-03-01 02:02:43 +00003022 }
3023
Brian Paul0bffb112005-11-08 14:45:48 +00003024 /* check for complete framebuffers */
Brian Paul722d9762009-01-20 16:58:49 -07003025 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
3026 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
Brian Paul0bffb112005-11-08 14:45:48 +00003027 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
3028 "glBlitFramebufferEXT(incomplete draw/read buffers)");
3029 return;
3030 }
3031
Brian Paul99745402006-03-01 02:02:43 +00003032 if (filter != GL_NEAREST && filter != GL_LINEAR) {
3033 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
3034 return;
3035 }
3036
Brian Paul722d9762009-01-20 16:58:49 -07003037 if (mask & ~legalMaskBits) {
Brian Paul99745402006-03-01 02:02:43 +00003038 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
3039 return;
3040 }
3041
Brian Paul0bffb112005-11-08 14:45:48 +00003042 /* depth/stencil must be blitted with nearest filtering */
3043 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
3044 && filter != GL_NEAREST) {
3045 _mesa_error(ctx, GL_INVALID_OPERATION,
Vinson Lee4f94e0b2011-03-28 20:32:01 -07003046 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
Brian Paul0bffb112005-11-08 14:45:48 +00003047 return;
3048 }
3049
Brian Paul722d9762009-01-20 16:58:49 -07003050 /* get color read/draw renderbuffers */
3051 if (mask & GL_COLOR_BUFFER_BIT) {
Anuj Phogatab36ca02012-12-11 20:17:47 -08003052 const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
3053 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
3054 const struct gl_renderbuffer *colorDrawRb = NULL;
3055 GLuint i;
Ian Romanickbb475862011-06-07 12:38:39 -07003056
3057 /* From the EXT_framebuffer_object spec:
3058 *
3059 * "If a buffer is specified in <mask> and does not exist in both
3060 * the read and draw framebuffers, the corresponding bit is silently
3061 * ignored."
3062 */
Anuj Phogatab36ca02012-12-11 20:17:47 -08003063 if (!colorReadRb || numColorDrawBuffers == 0) {
3064 mask &= ~GL_COLOR_BUFFER_BIT;
Ian Romanickbb475862011-06-07 12:38:39 -07003065 }
Anuj Phogatab36ca02012-12-11 20:17:47 -08003066 else {
3067 for (i = 0; i < numColorDrawBuffers; i++) {
3068 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
3069 if (!colorDrawRb)
3070 continue;
3071
Ian Romanick9cb64a42013-01-17 13:37:53 -08003072 /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
3073 * ES 3.0.1 spec says:
3074 *
3075 * "If the source and destination buffers are identical, an
3076 * INVALID_OPERATION error is generated. Different mipmap
3077 * levels of a texture, different layers of a three-
3078 * dimensional texture or two-dimensional array texture, and
3079 * different faces of a cube map texture do not constitute
3080 * identical buffers."
3081 */
3082 if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
3083 _mesa_error(ctx, GL_INVALID_OPERATION,
3084 "glBlitFramebuffer(source and destination color "
3085 "buffer cannot be the same)");
3086 return;
3087 }
3088
Anuj Phogatab36ca02012-12-11 20:17:47 -08003089 if (!compatible_color_datatypes(colorReadRb->Format,
3090 colorDrawRb->Format)) {
3091 _mesa_error(ctx, GL_INVALID_OPERATION,
3092 "glBlitFramebufferEXT(color buffer datatypes mismatch)");
3093 return;
3094 }
3095 /* extra checks for multisample copies... */
3096 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
3097 /* color formats must match */
3098 if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
3099 _mesa_error(ctx, GL_INVALID_OPERATION,
3100 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
3101 return;
3102 }
3103 }
3104 }
3105 if (filter == GL_LINEAR) {
3106 /* 3.1 spec, page 199:
3107 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
3108 * if filter is LINEAR and read buffer contains integer data."
3109 */
3110 GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
3111 if (type == GL_INT || type == GL_UNSIGNED_INT) {
3112 _mesa_error(ctx, GL_INVALID_OPERATION,
3113 "glBlitFramebufferEXT(integer color type)");
3114 return;
3115 }
3116 }
Brian Paul9b111702012-01-09 12:38:49 -07003117 }
Brian Paul722d9762009-01-20 16:58:49 -07003118 }
Brian Paul722d9762009-01-20 16:58:49 -07003119
Brian Paul99745402006-03-01 02:02:43 +00003120 if (mask & GL_STENCIL_BUFFER_BIT) {
Brian Pauld1240922011-12-10 11:44:43 -07003121 struct gl_renderbuffer *readRb =
3122 readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
3123 struct gl_renderbuffer *drawRb =
3124 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
Ian Romanickbb475862011-06-07 12:38:39 -07003125
3126 /* From the EXT_framebuffer_object spec:
3127 *
3128 * "If a buffer is specified in <mask> and does not exist in both
3129 * the read and draw framebuffers, the corresponding bit is silently
3130 * ignored."
3131 */
3132 if ((readRb == NULL) || (drawRb == NULL)) {
Ian Romanickbb475862011-06-07 12:38:39 -07003133 mask &= ~GL_STENCIL_BUFFER_BIT;
3134 }
Anuj Phogat252573a2013-01-07 15:55:31 -08003135 else {
Brian Paul7ecbbc32013-01-15 17:02:30 -07003136 int read_z_bits, draw_z_bits;
3137
Ian Romanick9cb64a42013-01-17 13:37:53 -08003138 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
3139 _mesa_error(ctx, GL_INVALID_OPERATION,
3140 "glBlitFramebuffer(source and destination stencil "
3141 "buffer cannot be the same)");
3142 return;
3143 }
3144
Anuj Phogat252573a2013-01-07 15:55:31 -08003145 if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
3146 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
3147 /* There is no need to check the stencil datatype here, because
3148 * there is only one: GL_UNSIGNED_INT.
3149 */
3150 _mesa_error(ctx, GL_INVALID_OPERATION,
3151 "glBlitFramebuffer(stencil attachment format mismatch)");
3152 return;
3153 }
3154
Brian Paul7ecbbc32013-01-15 17:02:30 -07003155 read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
3156 draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
Anuj Phogat252573a2013-01-07 15:55:31 -08003157
3158 /* If both buffers also have depth data, the depth formats must match
3159 * as well. If one doesn't have depth, it's not blitted, so we should
3160 * ignore the depth format check.
3161 */
3162 if (read_z_bits > 0 && draw_z_bits > 0 &&
3163 (read_z_bits != draw_z_bits ||
3164 _mesa_get_format_datatype(readRb->Format) !=
3165 _mesa_get_format_datatype(drawRb->Format))) {
3166
3167 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3168 "(stencil attachment depth format mismatch)");
3169 return;
3170 }
Brian Paul99745402006-03-01 02:02:43 +00003171 }
3172 }
3173
3174 if (mask & GL_DEPTH_BUFFER_BIT) {
Brian Pauld1240922011-12-10 11:44:43 -07003175 struct gl_renderbuffer *readRb =
3176 readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
3177 struct gl_renderbuffer *drawRb =
3178 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
Ian Romanickbb475862011-06-07 12:38:39 -07003179
3180 /* From the EXT_framebuffer_object spec:
3181 *
3182 * "If a buffer is specified in <mask> and does not exist in both
3183 * the read and draw framebuffers, the corresponding bit is silently
3184 * ignored."
3185 */
3186 if ((readRb == NULL) || (drawRb == NULL)) {
Ian Romanickbb475862011-06-07 12:38:39 -07003187 mask &= ~GL_DEPTH_BUFFER_BIT;
3188 }
Anuj Phogat252573a2013-01-07 15:55:31 -08003189 else {
Brian Paul7ecbbc32013-01-15 17:02:30 -07003190 int read_s_bit, draw_s_bit;
3191
Ian Romanick9cb64a42013-01-17 13:37:53 -08003192 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
3193 _mesa_error(ctx, GL_INVALID_OPERATION,
3194 "glBlitFramebuffer(source and destination depth "
3195 "buffer cannot be the same)");
3196 return;
3197 }
3198
Anuj Phogat252573a2013-01-07 15:55:31 -08003199 if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
3200 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
3201 (_mesa_get_format_datatype(readRb->Format) !=
3202 _mesa_get_format_datatype(drawRb->Format))) {
3203 _mesa_error(ctx, GL_INVALID_OPERATION,
3204 "glBlitFramebuffer(depth attachment format mismatch)");
3205 return;
3206 }
3207
Brian Paul7ecbbc32013-01-15 17:02:30 -07003208 read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
3209 draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
Anuj Phogat252573a2013-01-07 15:55:31 -08003210
3211 /* If both buffers also have stencil data, the stencil formats must
3212 * match as well. If one doesn't have stencil, it's not blitted, so
3213 * we should ignore the stencil format check.
3214 */
3215 if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
3216 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3217 "(depth attachment stencil bits mismatch)");
3218 return;
3219 }
Brian Paul99745402006-03-01 02:02:43 +00003220 }
Brian Paul0bffb112005-11-08 14:45:48 +00003221 }
3222
Brian Paul722d9762009-01-20 16:58:49 -07003223
Ian Romanick148fc6d2013-01-18 17:29:37 -08003224 if (_mesa_is_gles3(ctx)) {
3225 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
3226 * 3.0.1 spec says:
3227 *
3228 * "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
3229 * an INVALID_OPERATION error is generated."
3230 */
3231 if (drawFb->Visual.samples > 0) {
Brian Paul722d9762009-01-20 16:58:49 -07003232 _mesa_error(ctx, GL_INVALID_OPERATION,
Ian Romanick148fc6d2013-01-18 17:29:37 -08003233 "glBlitFramebuffer(destination samples must be 0)");
Brian Paul722d9762009-01-20 16:58:49 -07003234 return;
3235 }
Ian Romanick148fc6d2013-01-18 17:29:37 -08003236
3237 /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
3238 * 3.0.1 spec says:
3239 *
3240 * "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
3241 * no copy is performed and an INVALID_OPERATION error is generated
3242 * if the formats of the read and draw framebuffers are not
3243 * identical or if the source and destination rectangles are not
3244 * defined with the same (X0, Y0) and (X1, Y1) bounds."
3245 *
3246 * The format check was made above because desktop OpenGL has the same
3247 * requirement.
3248 */
3249 if (readFb->Visual.samples > 0
3250 && (srcX0 != dstX0 || srcY0 != dstY0
3251 || srcX1 != dstX1 || srcY1 != dstY1)) {
3252 _mesa_error(ctx, GL_INVALID_OPERATION,
3253 "glBlitFramebuffer(bad src/dst multisample region)");
3254 return;
3255 }
3256 } else {
3257 if (readFb->Visual.samples > 0 &&
3258 drawFb->Visual.samples > 0 &&
3259 readFb->Visual.samples != drawFb->Visual.samples) {
3260 _mesa_error(ctx, GL_INVALID_OPERATION,
3261 "glBlitFramebufferEXT(mismatched samples)");
3262 return;
3263 }
3264
3265 /* extra checks for multisample copies... */
3266 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
3267 /* src and dest region sizes must be the same */
3268 if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
3269 abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
3270 _mesa_error(ctx, GL_INVALID_OPERATION,
3271 "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
3272 return;
3273 }
3274 }
Brian Paul84c38c72012-01-09 08:11:33 -07003275 }
3276
Brian Paul0bffb112005-11-08 14:45:48 +00003277 if (!ctx->Extensions.EXT_framebuffer_blit) {
3278 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
3279 return;
3280 }
3281
Brian Paul21f8d312009-10-27 16:59:23 -06003282 /* Debug code */
3283 if (DEBUG_BLIT) {
Anuj Phogatab36ca02012-12-11 20:17:47 -08003284 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
3285 const struct gl_renderbuffer *colorDrawRb = NULL;
3286 GLuint i = 0;
3287
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003288 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
3289 " 0x%x, 0x%x)\n",
3290 srcX0, srcY0, srcX1, srcY1,
3291 dstX0, dstY0, dstX1, dstY1,
3292 mask, filter);
Brian Paul21f8d312009-10-27 16:59:23 -06003293 if (colorReadRb) {
3294 const struct gl_renderbuffer_attachment *att;
3295
3296 att = find_attachment(readFb, colorReadRb);
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003297 printf(" Src FBO %u RB %u (%dx%d) ",
3298 readFb->Name, colorReadRb->Name,
3299 colorReadRb->Width, colorReadRb->Height);
Brian Paul21f8d312009-10-27 16:59:23 -06003300 if (att && att->Texture) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003301 printf("Tex %u tgt 0x%x level %u face %u",
3302 att->Texture->Name,
3303 att->Texture->Target,
3304 att->TextureLevel,
3305 att->CubeMapFace);
Brian Paul21f8d312009-10-27 16:59:23 -06003306 }
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003307 printf("\n");
Brian Paul21f8d312009-10-27 16:59:23 -06003308
Anuj Phogatab36ca02012-12-11 20:17:47 -08003309 /* Print all active color render buffers */
3310 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
3311 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
3312 if (!colorDrawRb)
3313 continue;
3314
3315 att = find_attachment(drawFb, colorDrawRb);
3316 printf(" Dst FBO %u RB %u (%dx%d) ",
3317 drawFb->Name, colorDrawRb->Name,
3318 colorDrawRb->Width, colorDrawRb->Height);
3319 if (att && att->Texture) {
3320 printf("Tex %u tgt 0x%x level %u face %u",
3321 att->Texture->Name,
3322 att->Texture->Target,
3323 att->TextureLevel,
3324 att->CubeMapFace);
3325 }
3326 printf("\n");
Brian Paul21f8d312009-10-27 16:59:23 -06003327 }
Brian Paul21f8d312009-10-27 16:59:23 -06003328 }
3329 }
3330
Anuj Phogatd78dcdf2013-03-07 14:05:38 -08003331 if (!mask ||
3332 (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
3333 (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
Marek Olšák83478e52011-07-10 20:01:33 +02003334 return;
3335 }
3336
Brian Paul0bffb112005-11-08 14:45:48 +00003337 ASSERT(ctx->Driver.BlitFramebuffer);
3338 ctx->Driver.BlitFramebuffer(ctx,
3339 srcX0, srcY0, srcX1, srcY1,
3340 dstX0, dstY0, dstX1, dstY1,
3341 mask, filter);
3342}
Zack Rusinda7bd6a2010-06-28 17:31:21 -04003343
Brian Paul45bd5c42011-12-16 08:44:43 -07003344
Ian Romanick342be8a2012-08-13 09:27:00 -07003345static void
3346invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
3347 const GLenum *attachments, GLint x, GLint y,
3348 GLsizei width, GLsizei height, const char *name)
3349{
3350 int i;
3351 struct gl_framebuffer *fb;
3352 GET_CURRENT_CONTEXT(ctx);
3353
Ian Romanick342be8a2012-08-13 09:27:00 -07003354 fb = get_framebuffer_target(ctx, target);
3355 if (!fb) {
3356 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
3357 return;
3358 }
3359
3360 if (numAttachments < 0) {
3361 _mesa_error(ctx, GL_INVALID_VALUE,
3362 "%s(numAttachments < 0)", name);
3363 return;
3364 }
3365
3366 /* The GL_ARB_invalidate_subdata spec says:
3367 *
3368 * "If an attachment is specified that does not exist in the
3369 * framebuffer bound to <target>, it is ignored."
3370 *
3371 * It also says:
3372 *
3373 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
3374 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
3375 * INVALID_OPERATION is generated."
3376 *
3377 * No mention is made of GL_AUXi being out of range. Therefore, we allow
3378 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
3379 * set of retrictions).
3380 */
3381 for (i = 0; i < numAttachments; i++) {
3382 if (_mesa_is_winsys_fbo(fb)) {
3383 switch (attachments[i]) {
3384 case GL_ACCUM:
3385 case GL_AUX0:
3386 case GL_AUX1:
3387 case GL_AUX2:
3388 case GL_AUX3:
3389 /* Accumulation buffers and auxilary buffers were removed in
3390 * OpenGL 3.1, and they never existed in OpenGL ES.
3391 */
Paul Berrydbd61352012-11-27 12:26:51 -08003392 if (ctx->API != API_OPENGL_COMPAT)
Ian Romanick342be8a2012-08-13 09:27:00 -07003393 goto invalid_enum;
3394 break;
3395 case GL_COLOR:
3396 case GL_DEPTH:
3397 case GL_STENCIL:
3398 break;
3399 case GL_BACK_LEFT:
3400 case GL_BACK_RIGHT:
3401 case GL_FRONT_LEFT:
3402 case GL_FRONT_RIGHT:
3403 if (!_mesa_is_desktop_gl(ctx))
3404 goto invalid_enum;
3405 break;
3406 default:
3407 goto invalid_enum;
3408 }
3409 } else {
3410 switch (attachments[i]) {
3411 case GL_DEPTH_ATTACHMENT:
3412 case GL_STENCIL_ATTACHMENT:
3413 break;
3414 case GL_COLOR_ATTACHMENT0:
3415 case GL_COLOR_ATTACHMENT1:
3416 case GL_COLOR_ATTACHMENT2:
3417 case GL_COLOR_ATTACHMENT3:
3418 case GL_COLOR_ATTACHMENT4:
3419 case GL_COLOR_ATTACHMENT5:
3420 case GL_COLOR_ATTACHMENT6:
3421 case GL_COLOR_ATTACHMENT7:
3422 case GL_COLOR_ATTACHMENT8:
3423 case GL_COLOR_ATTACHMENT9:
3424 case GL_COLOR_ATTACHMENT10:
3425 case GL_COLOR_ATTACHMENT11:
3426 case GL_COLOR_ATTACHMENT12:
3427 case GL_COLOR_ATTACHMENT13:
3428 case GL_COLOR_ATTACHMENT14:
3429 case GL_COLOR_ATTACHMENT15: {
Brian Paul859c3872012-11-04 16:43:44 -07003430 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
Ian Romanick342be8a2012-08-13 09:27:00 -07003431 if (k >= ctx->Const.MaxColorAttachments) {
3432 _mesa_error(ctx, GL_INVALID_OPERATION,
3433 "%s(attachment >= max. color attachments)", name);
3434 return;
3435 }
3436 }
3437 default:
3438 goto invalid_enum;
3439 }
3440 }
3441 }
3442
3443 /* We don't actually do anything for this yet. Just return after
3444 * validating the parameters and generating the required errors.
3445 */
3446 return;
3447
3448invalid_enum:
3449 _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
3450 return;
3451}
3452
3453void GLAPIENTRY
3454_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
3455 const GLenum *attachments, GLint x, GLint y,
3456 GLsizei width, GLsizei height)
3457{
3458 invalidate_framebuffer_storage(target, numAttachments, attachments,
3459 x, y, width, height,
3460 "glInvalidateSubFramebuffer");
3461}
3462
3463void GLAPIENTRY
3464_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
3465 const GLenum *attachments)
3466{
3467 /* The GL_ARB_invalidate_subdata spec says:
3468 *
3469 * "The command
3470 *
3471 * void InvalidateFramebuffer(enum target,
3472 * sizei numAttachments,
3473 * const enum *attachments);
3474 *
3475 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
3476 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
3477 * <MAX_VIEWPORT_DIMS[1]> respectively."
3478 */
3479 invalidate_framebuffer_storage(target, numAttachments, attachments,
3480 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
3481 "glInvalidateFramebuffer");
3482}
Tapani Pälli413941e2013-02-18 09:12:27 +02003483
3484void GLAPIENTRY
3485_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
3486 const GLenum *attachments)
3487{
3488 struct gl_framebuffer *fb;
3489 GLint i;
3490
3491 GET_CURRENT_CONTEXT(ctx);
3492
3493 fb = get_framebuffer_target(ctx, target);
3494 if (!fb) {
3495 _mesa_error(ctx, GL_INVALID_ENUM,
3496 "glDiscardFramebufferEXT(target %s)",
3497 _mesa_lookup_enum_by_nr(target));
3498 return;
3499 }
3500
3501 if (numAttachments < 0) {
3502 _mesa_error(ctx, GL_INVALID_VALUE,
3503 "glDiscardFramebufferEXT(numAttachments < 0)");
3504 return;
3505 }
3506
3507 for (i = 0; i < numAttachments; i++) {
3508 switch (attachments[i]) {
3509 case GL_COLOR:
3510 case GL_DEPTH:
3511 case GL_STENCIL:
3512 if (_mesa_is_user_fbo(fb))
3513 goto invalid_enum;
3514 break;
3515 case GL_COLOR_ATTACHMENT0:
3516 case GL_DEPTH_ATTACHMENT:
3517 case GL_STENCIL_ATTACHMENT:
3518 if (_mesa_is_winsys_fbo(fb))
3519 goto invalid_enum;
3520 break;
3521 default:
3522 goto invalid_enum;
3523 }
3524 }
3525
3526 if (ctx->Driver.DiscardFramebuffer)
3527 ctx->Driver.DiscardFramebuffer(ctx, target, numAttachments, attachments);
3528
3529 return;
3530
3531invalid_enum:
3532 _mesa_error(ctx, GL_INVALID_ENUM,
3533 "glDiscardFramebufferEXT(attachment %s)",
3534 _mesa_lookup_enum_by_nr(attachments[i]));
3535}