blob: 4b80f8bacef471c924da80ca8d58b1ac018e132e [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
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
Brian Paul463642c2005-02-08 02:06:00 +000027/*
Brian Paul989edea2009-01-22 15:05:13 -070028 * GL_EXT/ARB_framebuffer_object extensions
29 *
Brian Paul463642c2005-02-08 02:06:00 +000030 * Authors:
31 * Brian Paul
32 */
33
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -080034#include <stdbool.h>
Brian Paul463642c2005-02-08 02:06:00 +000035
Roland Scheideggera1bc0d02007-07-18 20:17:14 +020036#include "buffers.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000037#include "context.h"
Brian Paul9b50cea2009-10-23 11:34:14 -060038#include "enums.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000039#include "fbobject.h"
Brian Paul5cf5d4b2009-09-27 20:51:18 -060040#include "formats.h"
Brian Paule4b23562005-05-04 20:11:35 +000041#include "framebuffer.h"
Brian Paula1287f52012-07-22 11:20:00 -060042#include "glformats.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000043#include "hash.h"
Brian Paul989edea2009-01-22 15:05:13 -070044#include "macros.h"
Vinson Leedb61b9c2011-01-07 00:08:24 -080045#include "mfeatures.h"
Vinson Lee0117da42011-01-05 23:11:54 -080046#include "mtypes.h"
Brian Paule4b23562005-05-04 20:11:35 +000047#include "renderbuffer.h"
Brian Paul99745402006-03-01 02:02:43 +000048#include "state.h"
Brian Paul463642c2005-02-08 02:06:00 +000049#include "teximage.h"
Brian Paulea4fe662006-03-26 05:22:17 +000050#include "texobj.h"
Brian Paulddc82ee2005-02-05 19:56:45 +000051
52
Brian Paul21f8d312009-10-27 16:59:23 -060053/** Set this to 1 to debug/log glBlitFramebuffer() calls */
54#define DEBUG_BLIT 0
55
Brian Paulc26c2002009-09-15 17:20:32 -060056
Brian Pauld9468c92005-02-10 16:08:07 +000057/**
58 * Notes:
59 *
60 * None of the GL_EXT_framebuffer_object functions are compiled into
61 * display lists.
62 */
63
64
65
Brian Paul923b6fc2005-02-08 04:08:56 +000066/*
67 * When glGenRender/FramebuffersEXT() is called we insert pointers to
68 * these placeholder objects into the hash table.
69 * Later, when the object ID is first bound, we replace the placeholder
70 * with the real frame/renderbuffer.
71 */
Brian Paul2c6f9112005-02-24 05:47:06 +000072static struct gl_framebuffer DummyFramebuffer;
73static struct gl_renderbuffer DummyRenderbuffer;
Brian Paul1864c7d2005-02-08 03:46:37 +000074
Kristian Høgsberg144356f2010-09-09 17:08:12 -040075/* We bind this framebuffer when applications pass a NULL
76 * drawable/surface in make current. */
77static struct gl_framebuffer IncompleteFramebuffer;
78
Brian Paul1864c7d2005-02-08 03:46:37 +000079
Brian Paul3dc65912008-07-03 15:40:38 -060080static void
Brian Paulc7324582012-11-30 10:04:48 -070081delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
Brian Paul3dc65912008-07-03 15:40:38 -060082{
83 /* no op */
84}
85
86static void
87delete_dummy_framebuffer(struct gl_framebuffer *fb)
88{
89 /* no op */
90}
91
92
93void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -040094_mesa_init_fbobjects(struct gl_context *ctx)
Brian Paul3dc65912008-07-03 15:40:38 -060095{
Vladimir Vukicevic07317012010-09-01 08:54:21 -060096 _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
97 _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
Kristian Høgsberg144356f2010-09-09 17:08:12 -040098 _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex);
Brian Paul3dc65912008-07-03 15:40:38 -060099 DummyFramebuffer.Delete = delete_dummy_framebuffer;
100 DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
Kristian Høgsberg144356f2010-09-09 17:08:12 -0400101 IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
Brian Paul3dc65912008-07-03 15:40:38 -0600102}
103
Kristian Høgsberg9456e222010-06-04 14:28:59 -0400104struct gl_framebuffer *
105_mesa_get_incomplete_framebuffer(void)
106{
Kristian Høgsberg144356f2010-09-09 17:08:12 -0400107 return &IncompleteFramebuffer;
Kristian Høgsberg9456e222010-06-04 14:28:59 -0400108}
Brian Paul3dc65912008-07-03 15:40:38 -0600109
Brian Paulddc82ee2005-02-05 19:56:45 +0000110/**
Brian Paul2c6f9112005-02-24 05:47:06 +0000111 * Helper routine for getting a gl_renderbuffer.
Brian Paulddc82ee2005-02-05 19:56:45 +0000112 */
Brian Paulea4fe662006-03-26 05:22:17 +0000113struct gl_renderbuffer *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400114_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
Brian Paulddc82ee2005-02-05 19:56:45 +0000115{
Brian Paul2c6f9112005-02-24 05:47:06 +0000116 struct gl_renderbuffer *rb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000117
Brian Paul1864c7d2005-02-08 03:46:37 +0000118 if (id == 0)
Brian Paulddc82ee2005-02-05 19:56:45 +0000119 return NULL;
120
Brian Paul2c6f9112005-02-24 05:47:06 +0000121 rb = (struct gl_renderbuffer *)
Brian Paulddc82ee2005-02-05 19:56:45 +0000122 _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
123 return rb;
124}
125
126
127/**
Brian Paul2c6f9112005-02-24 05:47:06 +0000128 * Helper routine for getting a gl_framebuffer.
Brian Paulddc82ee2005-02-05 19:56:45 +0000129 */
Brian Paulea4fe662006-03-26 05:22:17 +0000130struct gl_framebuffer *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400131_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
Brian Paulddc82ee2005-02-05 19:56:45 +0000132{
Brian Paul2c6f9112005-02-24 05:47:06 +0000133 struct gl_framebuffer *fb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000134
Brian Paul1864c7d2005-02-08 03:46:37 +0000135 if (id == 0)
Brian Paulddc82ee2005-02-05 19:56:45 +0000136 return NULL;
137
Brian Paul2c6f9112005-02-24 05:47:06 +0000138 fb = (struct gl_framebuffer *)
Brian Paulddc82ee2005-02-05 19:56:45 +0000139 _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
Brian Paul463642c2005-02-08 02:06:00 +0000140 return fb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000141}
142
143
144/**
Brian Paul72966362009-01-21 16:28:38 -0700145 * Mark the given framebuffer as invalid. This will force the
146 * test for framebuffer completeness to be done before the framebuffer
147 * is used.
148 */
149static void
150invalidate_framebuffer(struct gl_framebuffer *fb)
151{
152 fb->_Status = 0; /* "indeterminate" */
153}
154
155
156/**
Brian Paulc6991432011-02-28 18:24:25 -0700157 * Return the gl_framebuffer object which corresponds to the given
158 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
159 * Check support for GL_EXT_framebuffer_blit to determine if certain
160 * targets are legal.
161 * \return gl_framebuffer pointer or NULL if target is illegal
162 */
163static struct gl_framebuffer *
164get_framebuffer_target(struct gl_context *ctx, GLenum target)
165{
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800166 bool have_fb_blit = _mesa_is_gles3(ctx) ||
167 (ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx));
Brian Paulc6991432011-02-28 18:24:25 -0700168 switch (target) {
169 case GL_DRAW_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800170 return have_fb_blit ? ctx->DrawBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700171 case GL_READ_FRAMEBUFFER:
Kenneth Graunkec6ed42a2012-11-17 23:23:06 -0800172 return have_fb_blit ? ctx->ReadBuffer : NULL;
Brian Paulc6991432011-02-28 18:24:25 -0700173 case GL_FRAMEBUFFER_EXT:
174 return ctx->DrawBuffer;
175 default:
176 return NULL;
177 }
178}
179
180
181/**
Brian Pauld9468c92005-02-10 16:08:07 +0000182 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
Brian Paul2c6f9112005-02-24 05:47:06 +0000183 * gl_renderbuffer_attachment object.
Brian Paul61ec2052010-06-22 08:37:44 -0600184 * This function is only used for user-created FB objects, not the
185 * default / window-system FB object.
Brian Paul30590072009-01-21 11:06:11 -0700186 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
187 * the depth buffer attachment point.
Brian Pauld9468c92005-02-10 16:08:07 +0000188 */
Brian Paul84716042005-11-16 04:05:54 +0000189struct gl_renderbuffer_attachment *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400190_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
Brian Paul84716042005-11-16 04:05:54 +0000191 GLenum attachment)
Brian Paul3deaa012005-02-07 05:08:24 +0000192{
193 GLuint i;
194
Brian Paul36ede892012-01-12 09:17:23 -0700195 assert(_mesa_is_user_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600196
Brian Paul3deaa012005-02-07 05:08:24 +0000197 switch (attachment) {
198 case GL_COLOR_ATTACHMENT0_EXT:
199 case GL_COLOR_ATTACHMENT1_EXT:
200 case GL_COLOR_ATTACHMENT2_EXT:
201 case GL_COLOR_ATTACHMENT3_EXT:
202 case GL_COLOR_ATTACHMENT4_EXT:
203 case GL_COLOR_ATTACHMENT5_EXT:
204 case GL_COLOR_ATTACHMENT6_EXT:
205 case GL_COLOR_ATTACHMENT7_EXT:
206 case GL_COLOR_ATTACHMENT8_EXT:
207 case GL_COLOR_ATTACHMENT9_EXT:
208 case GL_COLOR_ATTACHMENT10_EXT:
209 case GL_COLOR_ATTACHMENT11_EXT:
210 case GL_COLOR_ATTACHMENT12_EXT:
211 case GL_COLOR_ATTACHMENT13_EXT:
212 case GL_COLOR_ATTACHMENT14_EXT:
213 case GL_COLOR_ATTACHMENT15_EXT:
Ian Romanick2e3a4ab2011-10-02 15:03:07 -0700214 /* Only OpenGL ES 1.x forbids color attachments other than
215 * GL_COLOR_ATTACHMENT0. For all other APIs the limit set by the
216 * hardware is used.
217 */
Brian Paul3deaa012005-02-07 05:08:24 +0000218 i = attachment - GL_COLOR_ATTACHMENT0_EXT;
Ian Romanick7e4cb322011-10-02 14:50:21 -0700219 if (i >= ctx->Const.MaxColorAttachments
Ian Romanick2e3a4ab2011-10-02 15:03:07 -0700220 || (i > 0 && ctx->API == API_OPENGLES)) {
Brian Paul3deaa012005-02-07 05:08:24 +0000221 return NULL;
222 }
Brian Paule4b23562005-05-04 20:11:35 +0000223 return &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paul30590072009-01-21 11:06:11 -0700224 case GL_DEPTH_STENCIL_ATTACHMENT:
Matt Turnerec8ee912012-11-15 22:13:48 -0800225 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
Ian Romanick7e4cb322011-10-02 14:50:21 -0700226 return NULL;
Brian Paul30590072009-01-21 11:06:11 -0700227 /* fall-through */
Brian Paul3deaa012005-02-07 05:08:24 +0000228 case GL_DEPTH_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000229 return &fb->Attachment[BUFFER_DEPTH];
Brian Paul3deaa012005-02-07 05:08:24 +0000230 case GL_STENCIL_ATTACHMENT_EXT:
Brian Paule4b23562005-05-04 20:11:35 +0000231 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul61ec2052010-06-22 08:37:44 -0600232 default:
233 return NULL;
234 }
235}
236
237
238/**
239 * As above, but only used for getting attachments of the default /
240 * window-system framebuffer (not user-created framebuffer objects).
241 */
242static struct gl_renderbuffer_attachment *
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400243_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
Brian Paul61ec2052010-06-22 08:37:44 -0600244 GLenum attachment)
245{
Brian Paul36ede892012-01-12 09:17:23 -0700246 assert(_mesa_is_winsys_fbo(fb));
Brian Paul61ec2052010-06-22 08:37:44 -0600247
Anuj Phogat2f2801f2012-12-11 20:08:13 -0800248 if (_mesa_is_gles3(ctx)) {
249 assert(attachment == GL_BACK ||
250 attachment == GL_DEPTH ||
251 attachment == GL_STENCIL);
252 switch (attachment) {
253 case GL_BACK:
254 /* Since there is no stereo rendering in ES 3.0, only return the
255 * LEFT bits.
256 */
257 if (ctx->DrawBuffer->Visual.doubleBufferMode)
258 return &fb->Attachment[BUFFER_BACK_LEFT];
259 return &fb->Attachment[BUFFER_FRONT_LEFT];
260 case GL_DEPTH:
261 return &fb->Attachment[BUFFER_DEPTH];
262 case GL_STENCIL:
263 return &fb->Attachment[BUFFER_STENCIL];
264 }
265 }
266
Brian Paul61ec2052010-06-22 08:37:44 -0600267 switch (attachment) {
Kristian Høgsberg80dfec32010-06-15 13:07:01 -0400268 case GL_FRONT_LEFT:
269 return &fb->Attachment[BUFFER_FRONT_LEFT];
270 case GL_FRONT_RIGHT:
271 return &fb->Attachment[BUFFER_FRONT_RIGHT];
272 case GL_BACK_LEFT:
273 return &fb->Attachment[BUFFER_BACK_LEFT];
274 case GL_BACK_RIGHT:
275 return &fb->Attachment[BUFFER_BACK_RIGHT];
Brian Paul61ec2052010-06-22 08:37:44 -0600276 case GL_AUX0:
277 if (fb->Visual.numAuxBuffers == 1) {
278 return &fb->Attachment[BUFFER_AUX0];
279 }
280 return NULL;
Ian Romanicka8328cc2011-10-03 12:02:18 -0700281
282 /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
283 *
284 * "If the default framebuffer is bound to target, then attachment must
285 * be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
286 * identifying a color buffer; DEPTH, identifying the depth buffer; or
287 * STENCIL, identifying the stencil buffer."
288 *
289 * Revision #34 of the ARB_framebuffer_object spec has essentially the same
290 * language. However, revision #33 of the ARB_framebuffer_object spec
291 * says:
292 *
293 * "If the default framebuffer is bound to <target>, then <attachment>
294 * must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
295 * DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
296 * depth buffer, or the stencil buffer, and <pname> may be
297 * FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
298 * FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
299 *
300 * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
301 * from glext.h, so shipping apps should not use those values.
302 *
303 * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
304 * support queries of the window system FBO.
305 */
306 case GL_DEPTH:
Brian Paul61ec2052010-06-22 08:37:44 -0600307 return &fb->Attachment[BUFFER_DEPTH];
Ian Romanicka8328cc2011-10-03 12:02:18 -0700308 case GL_STENCIL:
Brian Paul61ec2052010-06-22 08:37:44 -0600309 return &fb->Attachment[BUFFER_STENCIL];
Brian Paul3deaa012005-02-07 05:08:24 +0000310 default:
311 return NULL;
312 }
313}
314
315
Brian Paul61ec2052010-06-22 08:37:44 -0600316
Brian Pauld9468c92005-02-10 16:08:07 +0000317/**
318 * Remove any texture or renderbuffer attached to the given attachment
319 * point. Update reference counts, etc.
320 */
Brian Paule4b23562005-05-04 20:11:35 +0000321void
Brian Paulf9288542010-10-22 11:25:14 -0600322_mesa_remove_attachment(struct gl_context *ctx,
323 struct gl_renderbuffer_attachment *att)
Brian Paul3deaa012005-02-07 05:08:24 +0000324{
325 if (att->Type == GL_TEXTURE) {
326 ASSERT(att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100327 if (ctx->Driver.FinishRenderTexture) {
Brian Paul0e31e022005-12-01 00:25:00 +0000328 /* tell driver that we're done rendering to this texture. */
Brian9e01b912007-08-13 11:29:46 +0100329 ctx->Driver.FinishRenderTexture(ctx, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000330 }
Brian9e01b912007-08-13 11:29:46 +0100331 _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
332 ASSERT(!att->Texture);
Brian Paul3deaa012005-02-07 05:08:24 +0000333 }
Brian Paul0e31e022005-12-01 00:25:00 +0000334 if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul3deaa012005-02-07 05:08:24 +0000335 ASSERT(!att->Texture);
Brian9e01b912007-08-13 11:29:46 +0100336 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
337 ASSERT(!att->Renderbuffer);
Brian Paul3deaa012005-02-07 05:08:24 +0000338 }
339 att->Type = GL_NONE;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000340 att->Complete = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +0000341}
342
343
Brian Pauld9468c92005-02-10 16:08:07 +0000344/**
345 * Bind a texture object to an attachment point.
346 * The previous binding, if any, will be removed first.
347 */
Brian Paule4b23562005-05-04 20:11:35 +0000348void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400349_mesa_set_texture_attachment(struct gl_context *ctx,
Brian Paul519b23b2006-03-20 18:51:57 +0000350 struct gl_framebuffer *fb,
Brian Paule4b23562005-05-04 20:11:35 +0000351 struct gl_renderbuffer_attachment *att,
352 struct gl_texture_object *texObj,
353 GLenum texTarget, GLuint level, GLuint zoffset)
Brian Paul3deaa012005-02-07 05:08:24 +0000354{
Brian Paul0e31e022005-12-01 00:25:00 +0000355 if (att->Texture == texObj) {
356 /* re-attaching same texture */
357 ASSERT(att->Type == GL_TEXTURE);
Eric Anholt6b684822009-11-04 14:31:30 -0800358 if (ctx->Driver.FinishRenderTexture)
359 ctx->Driver.FinishRenderTexture(ctx, att);
Brian Paul0e31e022005-12-01 00:25:00 +0000360 }
361 else {
362 /* new attachment */
Eric Anholt6b684822009-11-04 14:31:30 -0800363 if (ctx->Driver.FinishRenderTexture && att->Texture)
364 ctx->Driver.FinishRenderTexture(ctx, att);
Brian Paul0e31e022005-12-01 00:25:00 +0000365 _mesa_remove_attachment(ctx, att);
366 att->Type = GL_TEXTURE;
Brian9e01b912007-08-13 11:29:46 +0100367 assert(!att->Texture);
368 _mesa_reference_texobj(&att->Texture, texObj);
Brian Paul0e31e022005-12-01 00:25:00 +0000369 }
370
371 /* always update these fields */
Brian Paul3deaa012005-02-07 05:08:24 +0000372 att->TextureLevel = level;
Brian Paul26f1ad62009-10-23 18:15:55 -0600373 att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
Brian Paul3deaa012005-02-07 05:08:24 +0000374 att->Zoffset = zoffset;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000375 att->Complete = GL_FALSE;
Brian Paul519b23b2006-03-20 18:51:57 +0000376
Brian Pauldb0f9e72011-04-05 07:51:01 -0600377 if (_mesa_get_attachment_teximage(att)) {
Brian Paulea4fe662006-03-26 05:22:17 +0000378 ctx->Driver.RenderTexture(ctx, fb, att);
Brian Paul519b23b2006-03-20 18:51:57 +0000379 }
Brian Paul72966362009-01-21 16:28:38 -0700380
381 invalidate_framebuffer(fb);
Brian Paul3deaa012005-02-07 05:08:24 +0000382}
383
384
Brian Pauld9468c92005-02-10 16:08:07 +0000385/**
386 * Bind a renderbuffer to an attachment point.
387 * The previous binding, if any, will be removed first.
388 */
Brian Paule4b23562005-05-04 20:11:35 +0000389void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400390_mesa_set_renderbuffer_attachment(struct gl_context *ctx,
Brian Paule4b23562005-05-04 20:11:35 +0000391 struct gl_renderbuffer_attachment *att,
392 struct gl_renderbuffer *rb)
Brian Paul3deaa012005-02-07 05:08:24 +0000393{
Brian Paulea4fe662006-03-26 05:22:17 +0000394 /* XXX check if re-doing same attachment, exit early */
Brian Paule4b23562005-05-04 20:11:35 +0000395 _mesa_remove_attachment(ctx, att);
Brian Paul3deaa012005-02-07 05:08:24 +0000396 att->Type = GL_RENDERBUFFER_EXT;
Brian Paul2c6f9112005-02-24 05:47:06 +0000397 att->Texture = NULL; /* just to be safe */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000398 att->Complete = GL_FALSE;
Briandccd9c42007-04-02 09:56:28 -0600399 _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
Brian Paul3deaa012005-02-07 05:08:24 +0000400}
401
Brian Paulddc82ee2005-02-05 19:56:45 +0000402
Brian Paulf0bbbf62005-02-09 03:50:30 +0000403/**
Brian Paule4b23562005-05-04 20:11:35 +0000404 * Fallback for ctx->Driver.FramebufferRenderbuffer()
Brian Paul84716042005-11-16 04:05:54 +0000405 * Attach a renderbuffer object to a framebuffer object.
Brian Paule4b23562005-05-04 20:11:35 +0000406 */
407void
Brian Paulf9288542010-10-22 11:25:14 -0600408_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
409 struct gl_framebuffer *fb,
Brian Paul84716042005-11-16 04:05:54 +0000410 GLenum attachment, struct gl_renderbuffer *rb)
Brian Paule4b23562005-05-04 20:11:35 +0000411{
Brian Paul84716042005-11-16 04:05:54 +0000412 struct gl_renderbuffer_attachment *att;
413
Brian Paulea4fe662006-03-26 05:22:17 +0000414 _glthread_LOCK_MUTEX(fb->Mutex);
Brian Paulea4fe662006-03-26 05:22:17 +0000415
Brian Paul84716042005-11-16 04:05:54 +0000416 att = _mesa_get_attachment(ctx, fb, attachment);
417 ASSERT(att);
Brian Paule4b23562005-05-04 20:11:35 +0000418 if (rb) {
419 _mesa_set_renderbuffer_attachment(ctx, att, rb);
Brian Paul30590072009-01-21 11:06:11 -0700420 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
421 /* do stencil attachment here (depth already done above) */
422 att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
423 assert(att);
424 _mesa_set_renderbuffer_attachment(ctx, att, rb);
425 }
Marek Olšákdf818d52011-03-06 05:26:12 +0100426 rb->AttachedAnytime = GL_TRUE;
Brian Paule4b23562005-05-04 20:11:35 +0000427 }
428 else {
429 _mesa_remove_attachment(ctx, att);
430 }
Brian Paulea4fe662006-03-26 05:22:17 +0000431
Brian Paul72966362009-01-21 16:28:38 -0700432 invalidate_framebuffer(fb);
433
Brian Paulea4fe662006-03-26 05:22:17 +0000434 _glthread_UNLOCK_MUTEX(fb->Mutex);
Brian Paule4b23562005-05-04 20:11:35 +0000435}
436
437
438/**
Brian Paul62c66b32011-01-24 19:38:52 -0700439 * Fallback for ctx->Driver.ValidateFramebuffer()
440 * Check if the renderbuffer's formats are supported by the software
441 * renderer.
442 * Drivers should probably override this.
443 */
444void
445_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
446{
447 gl_buffer_index buf;
448 for (buf = 0; buf < BUFFER_COUNT; buf++) {
449 const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
450 if (rb) {
451 switch (rb->_BaseFormat) {
452 case GL_ALPHA:
453 case GL_LUMINANCE_ALPHA:
454 case GL_LUMINANCE:
455 case GL_INTENSITY:
Brian Pauld3015652011-01-24 19:38:52 -0700456 case GL_RED:
457 case GL_RG:
Brian Paul62c66b32011-01-24 19:38:52 -0700458 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
459 return;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200460
461 default:
Marek Olšák9d7698c2011-04-26 02:18:24 +0200462 switch (rb->Format) {
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200463 /* XXX This list is likely incomplete. */
Marek Olšák9d7698c2011-04-26 02:18:24 +0200464 case MESA_FORMAT_RGB9_E5_FLOAT:
465 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
466 return;
467 default:;
Marek Olšáka3ac28a2011-05-14 04:42:29 +0200468 /* render buffer format is supported by software rendering */
Marek Olšák9d7698c2011-04-26 02:18:24 +0200469 }
Brian Paul62c66b32011-01-24 19:38:52 -0700470 }
471 }
472 }
473}
474
475
476/**
Brian Paul9f731c82009-02-17 16:47:54 -0700477 * For debug only.
478 */
479static void
480att_incomplete(const char *msg)
481{
Brian Paul93bcf782012-05-09 12:09:21 -0600482 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
483 _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
484 }
Brian Paul9f731c82009-02-17 16:47:54 -0700485}
486
487
488/**
Brian Paulc26c2002009-09-15 17:20:32 -0600489 * For debug only.
490 */
491static void
492fbo_incomplete(const char *msg, int index)
493{
Brian Paul93bcf782012-05-09 12:09:21 -0600494 if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
495 _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
496 }
Brian Paulc26c2002009-09-15 17:20:32 -0600497}
498
499
Brian Paule67f6ee2010-10-22 11:38:23 -0600500/**
501 * Is the given base format a legal format for a color renderbuffer?
502 */
Eric Anholt059cca92011-01-02 17:58:07 -0800503GLboolean
504_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
Brian Paule67f6ee2010-10-22 11:38:23 -0600505{
506 switch (baseFormat) {
507 case GL_RGB:
508 case GL_RGBA:
509 return GL_TRUE;
Marek Olšák6e618532010-10-02 21:53:03 +0200510 case GL_LUMINANCE:
511 case GL_LUMINANCE_ALPHA:
512 case GL_INTENSITY:
Brian Paule67f6ee2010-10-22 11:38:23 -0600513 case GL_ALPHA:
Jordan Justencf300ea2012-12-27 12:41:10 -0800514 return ctx->API == API_OPENGL_COMPAT &&
515 ctx->Extensions.ARB_framebuffer_object;
Brian Paule67f6ee2010-10-22 11:38:23 -0600516 case GL_RED:
517 case GL_RG:
518 return ctx->Extensions.ARB_texture_rg;
519 default:
520 return GL_FALSE;
521 }
522}
523
524
525/**
Jordan Justen6c7fa722012-12-27 13:34:44 -0800526 * Is the given base format a legal format for a color renderbuffer?
527 */
528static GLboolean
529is_format_color_renderable(const struct gl_context *ctx, gl_format format, GLenum internalFormat)
530{
531 const GLenum baseFormat =
532 _mesa_get_format_base_format(format);
533 GLboolean valid;
534
535 valid = _mesa_is_legal_color_format(ctx, baseFormat);
536 if (!valid || _mesa_is_desktop_gl(ctx)) {
537 return valid;
538 }
539
540 /* Reject additional cases for GLES */
541 switch (internalFormat) {
542 case GL_RGBA8_SNORM:
543 case GL_RGB32F:
544 case GL_RGB32I:
545 case GL_RGB32UI:
546 case GL_RGB16F:
547 case GL_RGB16I:
548 case GL_RGB16UI:
549 case GL_RGB8_SNORM:
550 case GL_RGB8I:
551 case GL_RGB8UI:
552 case GL_SRGB8:
553 case GL_RGB9_E5:
554 case GL_RG8_SNORM:
555 case GL_R8_SNORM:
556 return GL_FALSE;
557 default:
558 break;
559 }
560
561 if (format == MESA_FORMAT_ARGB2101010 && internalFormat != GL_RGB10_A2) {
562 return GL_FALSE;
563 }
564
565 return GL_TRUE;
566}
567
568
569/**
Brian Paule67f6ee2010-10-22 11:38:23 -0600570 * Is the given base format a legal format for a depth/stencil renderbuffer?
571 */
572static GLboolean
573is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
574{
575 switch (baseFormat) {
576 case GL_DEPTH_COMPONENT:
577 case GL_DEPTH_STENCIL_EXT:
578 return GL_TRUE;
579 default:
580 return GL_FALSE;
581 }
582}
Brian Paulc26c2002009-09-15 17:20:32 -0600583
584
585/**
Brian Paulf0bbbf62005-02-09 03:50:30 +0000586 * Test if an attachment point is complete and update its Complete field.
587 * \param format if GL_COLOR, this is a color attachment point,
588 * if GL_DEPTH, this is a depth component attachment point,
589 * if GL_STENCIL, this is a stencil component attachment point.
590 */
591static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -0400592test_attachment_completeness(const struct gl_context *ctx, GLenum format,
Brian Paul2c6f9112005-02-24 05:47:06 +0000593 struct gl_renderbuffer_attachment *att)
Brian Paulf0bbbf62005-02-09 03:50:30 +0000594{
595 assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
596
597 /* assume complete */
598 att->Complete = GL_TRUE;
599
Brian Paulf0bbbf62005-02-09 03:50:30 +0000600 /* Look for reasons why the attachment might be incomplete */
601 if (att->Type == GL_TEXTURE) {
Brian Paule4b23562005-05-04 20:11:35 +0000602 const struct gl_texture_object *texObj = att->Texture;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000603 struct gl_texture_image *texImage;
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600604 GLenum baseFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000605
Brian Paule4b23562005-05-04 20:11:35 +0000606 if (!texObj) {
Brian Paul9f731c82009-02-17 16:47:54 -0700607 att_incomplete("no texobj");
Brian Paule4b23562005-05-04 20:11:35 +0000608 att->Complete = GL_FALSE;
609 return;
610 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000611
612 texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
613 if (!texImage) {
Brian Paul9f731c82009-02-17 16:47:54 -0700614 att_incomplete("no teximage");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000615 att->Complete = GL_FALSE;
616 return;
617 }
618 if (texImage->Width < 1 || texImage->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700619 att_incomplete("teximage width/height=0");
Kristian Høgsberg298be2b2010-02-19 12:32:24 -0500620 printf("texobj = %u\n", texObj->Name);
621 printf("level = %d\n", att->TextureLevel);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000622 att->Complete = GL_FALSE;
623 return;
624 }
625 if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) {
Brian Paul9f731c82009-02-17 16:47:54 -0700626 att_incomplete("bad z offset");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000627 att->Complete = GL_FALSE;
628 return;
629 }
630
Brian Paul1f7c9142009-09-30 20:28:45 -0600631 baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600632
Brian Paulf0bbbf62005-02-09 03:50:30 +0000633 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800634 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700635 att_incomplete("bad format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000636 att->Complete = GL_FALSE;
637 return;
638 }
Brian Paul1f7c9142009-09-30 20:28:45 -0600639 if (_mesa_is_format_compressed(texImage->TexFormat)) {
Eric Anholt957f3c82009-05-15 16:24:59 -0700640 att_incomplete("compressed internalformat");
641 att->Complete = GL_FALSE;
642 return;
643 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000644 }
645 else if (format == GL_DEPTH) {
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600646 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000647 /* OK */
648 }
649 else if (ctx->Extensions.EXT_packed_depth_stencil &&
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600650 ctx->Extensions.ARB_depth_texture &&
Brian Paul5cf5d4b2009-09-27 20:51:18 -0600651 baseFormat == GL_DEPTH_STENCIL_EXT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000652 /* OK */
653 }
654 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000655 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700656 att_incomplete("bad depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000657 return;
658 }
659 }
660 else {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600661 ASSERT(format == GL_STENCIL);
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600662 if (ctx->Extensions.EXT_packed_depth_stencil &&
663 ctx->Extensions.ARB_depth_texture &&
Brian Paul45e76d22009-10-08 20:27:27 -0600664 baseFormat == GL_DEPTH_STENCIL_EXT) {
Mathias Fröhlich042d9a52009-05-19 09:59:01 -0600665 /* OK */
666 }
667 else {
668 /* no such thing as stencil-only textures */
669 att_incomplete("illegal stencil texture");
670 att->Complete = GL_FALSE;
671 return;
672 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000673 }
674 }
Brian Paule4b23562005-05-04 20:11:35 +0000675 else if (att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul45e76d22009-10-08 20:27:27 -0600676 const GLenum baseFormat =
677 _mesa_get_format_base_format(att->Renderbuffer->Format);
678
Brian Paul49918882006-03-20 15:27:55 +0000679 ASSERT(att->Renderbuffer);
680 if (!att->Renderbuffer->InternalFormat ||
681 att->Renderbuffer->Width < 1 ||
682 att->Renderbuffer->Height < 1) {
Brian Paul9f731c82009-02-17 16:47:54 -0700683 att_incomplete("0x0 renderbuffer");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000684 att->Complete = GL_FALSE;
685 return;
686 }
687 if (format == GL_COLOR) {
Eric Anholt059cca92011-01-02 17:58:07 -0800688 if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
Brian Paul9f731c82009-02-17 16:47:54 -0700689 att_incomplete("bad renderbuffer color format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000690 att->Complete = GL_FALSE;
691 return;
692 }
693 }
694 else if (format == GL_DEPTH) {
Brian Paul45e76d22009-10-08 20:27:27 -0600695 if (baseFormat == GL_DEPTH_COMPONENT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000696 /* OK */
697 }
698 else if (ctx->Extensions.EXT_packed_depth_stencil &&
Brian Paul45e76d22009-10-08 20:27:27 -0600699 baseFormat == GL_DEPTH_STENCIL_EXT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000700 /* OK */
701 }
702 else {
Brian Paul9f731c82009-02-17 16:47:54 -0700703 att_incomplete("bad renderbuffer depth format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000704 att->Complete = GL_FALSE;
705 return;
706 }
707 }
708 else {
709 assert(format == GL_STENCIL);
Brian Paul45e76d22009-10-08 20:27:27 -0600710 if (baseFormat == GL_STENCIL_INDEX) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000711 /* OK */
712 }
713 else if (ctx->Extensions.EXT_packed_depth_stencil &&
Brian Paul45e76d22009-10-08 20:27:27 -0600714 baseFormat == GL_DEPTH_STENCIL_EXT) {
Brian Paul1ad7b992005-09-28 02:29:50 +0000715 /* OK */
716 }
717 else {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000718 att->Complete = GL_FALSE;
Brian Paul9f731c82009-02-17 16:47:54 -0700719 att_incomplete("bad renderbuffer stencil format");
Brian Paulf0bbbf62005-02-09 03:50:30 +0000720 return;
721 }
722 }
723 }
Brian Paule4b23562005-05-04 20:11:35 +0000724 else {
725 ASSERT(att->Type == GL_NONE);
726 /* complete */
727 return;
728 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000729}
730
731
732/**
733 * Test if the given framebuffer object is complete and update its
734 * Status field with the results.
Brian Paul3528f692009-01-22 15:13:18 -0700735 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
736 * driver to make hardware-specific validation/completeness checks.
Brian Paule4b23562005-05-04 20:11:35 +0000737 * Also update the framebuffer's Width and Height fields if the
738 * framebuffer is complete.
Brian Paulf0bbbf62005-02-09 03:50:30 +0000739 */
Brian Paule4b23562005-05-04 20:11:35 +0000740void
Brian Paulf9288542010-10-22 11:25:14 -0600741_mesa_test_framebuffer_completeness(struct gl_context *ctx,
742 struct gl_framebuffer *fb)
Brian Paulf0bbbf62005-02-09 03:50:30 +0000743{
Brian Paul989edea2009-01-22 15:05:13 -0700744 GLuint numImages;
745 GLenum intFormat = GL_NONE; /* color buffers' internal format */
746 GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
Brian Paul722d9762009-01-20 16:58:49 -0700747 GLint numSamples = -1;
Brian Paule4b23562005-05-04 20:11:35 +0000748 GLint i;
Brian Paul28b014e2006-04-05 03:05:17 +0000749 GLuint j;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000750
Brian Paul36ede892012-01-12 09:17:23 -0700751 assert(_mesa_is_user_fbo(fb));
Brian Paulc7264412005-06-01 00:50:23 +0000752
Marek Olšáke06d6162012-08-04 13:37:03 +0200753 /* we're changing framebuffer fields here */
754 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
755
Brian Paulf0bbbf62005-02-09 03:50:30 +0000756 numImages = 0;
Brian Paule4b23562005-05-04 20:11:35 +0000757 fb->Width = 0;
758 fb->Height = 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000759
Brian Paul989edea2009-01-22 15:05:13 -0700760 /* Start at -2 to more easily loop over all attachment points.
761 * -2: depth buffer
762 * -1: stencil buffer
763 * >=0: color buffer
764 */
Brian Paule4b23562005-05-04 20:11:35 +0000765 for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +0000766 struct gl_renderbuffer_attachment *att;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000767 GLenum f;
Brian Paulca1b5512011-02-28 18:23:23 -0700768 gl_format attFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000769
Brian Paul1bc59bf2009-01-22 15:07:34 -0700770 /*
771 * XXX for ARB_fbo, only check color buffers that are named by
772 * GL_READ_BUFFER and GL_DRAW_BUFFERi.
773 */
774
Brian Paul989edea2009-01-22 15:05:13 -0700775 /* check for attachment completeness
776 */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000777 if (i == -2) {
Brian Paule4b23562005-05-04 20:11:35 +0000778 att = &fb->Attachment[BUFFER_DEPTH];
Brian Paulf0bbbf62005-02-09 03:50:30 +0000779 test_attachment_completeness(ctx, GL_DEPTH, att);
780 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +0000781 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000782 fbo_incomplete("depth attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000783 return;
784 }
785 }
786 else if (i == -1) {
Brian Paule4b23562005-05-04 20:11:35 +0000787 att = &fb->Attachment[BUFFER_STENCIL];
Brian Paulf0bbbf62005-02-09 03:50:30 +0000788 test_attachment_completeness(ctx, GL_STENCIL, att);
789 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +0000790 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000791 fbo_incomplete("stencil attachment incomplete", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000792 return;
793 }
794 }
795 else {
Brian Paule4b23562005-05-04 20:11:35 +0000796 att = &fb->Attachment[BUFFER_COLOR0 + i];
Brian Paulf0bbbf62005-02-09 03:50:30 +0000797 test_attachment_completeness(ctx, GL_COLOR, att);
798 if (!att->Complete) {
Brian Paule4b23562005-05-04 20:11:35 +0000799 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000800 fbo_incomplete("color attachment incomplete", i);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000801 return;
802 }
803 }
804
Brian Paul989edea2009-01-22 15:05:13 -0700805 /* get width, height, format of the renderbuffer/texture
806 */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000807 if (att->Type == GL_TEXTURE) {
Brian Pauldb0f9e72011-04-05 07:51:01 -0600808 const struct gl_texture_image *texImg =
809 _mesa_get_attachment_teximage(att);
Brian Paul989edea2009-01-22 15:05:13 -0700810 minWidth = MIN2(minWidth, texImg->Width);
811 maxWidth = MAX2(maxWidth, texImg->Width);
812 minHeight = MIN2(minHeight, texImg->Height);
813 maxHeight = MAX2(maxHeight, texImg->Height);
Brian Paula9fc8ba2005-10-05 01:48:07 +0000814 f = texImg->_BaseFormat;
Brian Paulca1b5512011-02-28 18:23:23 -0700815 attFormat = texImg->TexFormat;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000816 numImages++;
Jordan Justen6c7fa722012-12-27 13:34:44 -0800817 if (!is_format_color_renderable(ctx, attFormat, texImg->InternalFormat) &&
Brian Paule67f6ee2010-10-22 11:38:23 -0600818 !is_legal_depth_format(ctx, f)) {
Brian Pauled7f3ae2005-06-07 15:03:40 +0000819 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000820 fbo_incomplete("texture attachment incomplete", -1);
Brian Pauled7f3ae2005-06-07 15:03:40 +0000821 return;
822 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000823 }
824 else if (att->Type == GL_RENDERBUFFER_EXT) {
Brian Paul989edea2009-01-22 15:05:13 -0700825 minWidth = MIN2(minWidth, att->Renderbuffer->Width);
826 maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
827 minHeight = MIN2(minHeight, att->Renderbuffer->Height);
828 maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000829 f = att->Renderbuffer->InternalFormat;
Brian Paulca1b5512011-02-28 18:23:23 -0700830 attFormat = att->Renderbuffer->Format;
Brian Paulf0bbbf62005-02-09 03:50:30 +0000831 numImages++;
832 }
833 else {
834 assert(att->Type == GL_NONE);
835 continue;
836 }
837
Fabian Bielerc7339d42011-04-05 07:51:01 -0600838 if (att->Renderbuffer && numSamples < 0) {
Brian Paul72966362009-01-21 16:28:38 -0700839 /* first buffer */
840 numSamples = att->Renderbuffer->NumSamples;
841 }
842
Brian Paulc7d18372010-10-23 09:38:45 -0600843 /* check if integer color */
Brian Paulca1b5512011-02-28 18:23:23 -0700844 fb->_IntegerColor = _mesa_is_format_integer_color(attFormat);
Brian Paulc7d18372010-10-23 09:38:45 -0600845
Brian Paul722d9762009-01-20 16:58:49 -0700846 /* Error-check width, height, format, samples
Brian Paul989edea2009-01-22 15:05:13 -0700847 */
Brian Paulf0bbbf62005-02-09 03:50:30 +0000848 if (numImages == 1) {
Brian Paul722d9762009-01-20 16:58:49 -0700849 /* save format, num samples */
850 if (i >= 0) {
Brian Paulf0bbbf62005-02-09 03:50:30 +0000851 intFormat = f;
Brian Paul722d9762009-01-20 16:58:49 -0700852 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000853 }
854 else {
Brian Paul989edea2009-01-22 15:05:13 -0700855 if (!ctx->Extensions.ARB_framebuffer_object) {
856 /* check that width, height, format are same */
857 if (minWidth != maxWidth || minHeight != maxHeight) {
858 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
859 fbo_incomplete("width or height mismatch", -1);
860 return;
861 }
Brian Paul45bd5c42011-12-16 08:44:43 -0700862 /* check that all color buffers are the same format */
Brian Paul989edea2009-01-22 15:05:13 -0700863 if (intFormat != GL_NONE && f != intFormat) {
864 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
865 fbo_incomplete("format mismatch", -1);
866 return;
867 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000868 }
Brian Paul722d9762009-01-20 16:58:49 -0700869 if (att->Renderbuffer &&
870 att->Renderbuffer->NumSamples != numSamples) {
Brian Paul72966362009-01-21 16:28:38 -0700871 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
Brian Paul722d9762009-01-20 16:58:49 -0700872 fbo_incomplete("inconsistant number of samples", i);
873 return;
Brian Paul45bd5c42011-12-16 08:44:43 -0700874 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000875 }
Marek Olšáka82227c2012-06-15 17:21:05 +0200876
877 /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
878 */
879 if (att->Type == GL_RENDERBUFFER &&
880 att->Renderbuffer->Format == MESA_FORMAT_NONE) {
881 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
882 fbo_incomplete("unsupported renderbuffer format", i);
883 return;
884 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000885 }
886
Jordan Justen09714c02012-07-19 11:27:16 -0700887 if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
Kristian Høgsberge88cef32010-05-24 16:56:12 -0400888 /* Check that all DrawBuffers are present */
889 for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
890 if (fb->ColorDrawBuffer[j] != GL_NONE) {
891 const struct gl_renderbuffer_attachment *att
892 = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
893 assert(att);
894 if (att->Type == GL_NONE) {
895 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
896 fbo_incomplete("missing drawbuffer", j);
897 return;
898 }
899 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000900 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000901
Kristian Høgsberge88cef32010-05-24 16:56:12 -0400902 /* Check that the ReadBuffer is present */
903 if (fb->ColorReadBuffer != GL_NONE) {
904 const struct gl_renderbuffer_attachment *att
905 = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
906 assert(att);
907 if (att->Type == GL_NONE) {
908 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000909 fbo_incomplete("missing readbuffer", -1);
Kristian Høgsberge88cef32010-05-24 16:56:12 -0400910 return;
911 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000912 }
913 }
914
915 if (numImages == 0) {
Brian Paule4b23562005-05-04 20:11:35 +0000916 fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
Brian Paul49918882006-03-20 15:27:55 +0000917 fbo_incomplete("no attachments", -1);
Brian Paulf0bbbf62005-02-09 03:50:30 +0000918 return;
919 }
Brian Paulf0bbbf62005-02-09 03:50:30 +0000920
Brian Paul3528f692009-01-22 15:13:18 -0700921 /* Provisionally set status = COMPLETE ... */
Brian Paule4b23562005-05-04 20:11:35 +0000922 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
Brian Paul3528f692009-01-22 15:13:18 -0700923
Brian Paul777a2ef2009-01-22 15:17:42 -0700924 /* ... but the driver may say the FB is incomplete.
925 * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
926 * if anything.
927 */
Brian Paul3528f692009-01-22 15:13:18 -0700928 if (ctx->Driver.ValidateFramebuffer) {
929 ctx->Driver.ValidateFramebuffer(ctx, fb);
Brian Paul1f32c412009-01-19 17:34:19 -0700930 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
931 fbo_incomplete("driver marked FBO as incomplete", -1);
932 }
Brian Paul3528f692009-01-22 15:13:18 -0700933 }
934
935 if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
936 /*
937 * Note that if ARB_framebuffer_object is supported and the attached
938 * renderbuffers/textures are different sizes, the framebuffer
939 * width/height will be set to the smallest width/height.
940 */
941 fb->Width = minWidth;
942 fb->Height = minHeight;
Brian Paul38768db2009-01-27 09:49:27 -0700943
944 /* finally, update the visual info for the framebuffer */
Eric Anholt059cca92011-01-02 17:58:07 -0800945 _mesa_update_framebuffer_visual(ctx, fb);
Brian Paul3528f692009-01-22 15:13:18 -0700946 }
Brian Paule4b23562005-05-04 20:11:35 +0000947}
Brian Paulf0bbbf62005-02-09 03:50:30 +0000948
949
Brian Paul1864c7d2005-02-08 03:46:37 +0000950GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -0800951_mesa_IsRenderbuffer(GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +0000952{
Brian Paulddc82ee2005-02-05 19:56:45 +0000953 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +0000954 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Brian Paulbc6cced2005-10-04 15:01:27 +0000955 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +0000956 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paulbc6cced2005-10-04 15:01:27 +0000957 if (rb != NULL && rb != &DummyRenderbuffer)
958 return GL_TRUE;
959 }
960 return GL_FALSE;
Brian Paulddc82ee2005-02-05 19:56:45 +0000961}
962
963
Brian Paul1864c7d2005-02-08 03:46:37 +0000964void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -0800965_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +0000966{
Brian42aaa542007-03-25 10:39:36 -0600967 struct gl_renderbuffer *newRb;
Brian Paulddc82ee2005-02-05 19:56:45 +0000968 GET_CURRENT_CONTEXT(ctx);
969
Brian Paul3deaa012005-02-07 05:08:24 +0000970 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul4de18fb2009-11-02 15:30:51 -0700971 _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +0000972 return;
973 }
974
Brian Paul800e5532009-11-02 15:39:39 -0700975 /* No need to flush here since the render buffer binding has no
976 * effect on rendering state.
977 */
Brian Paul474f28e2005-10-08 14:41:17 +0000978
Brian Paul3deaa012005-02-07 05:08:24 +0000979 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +0000980 newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +0000981 if (newRb == &DummyRenderbuffer) {
982 /* ID was reserved, but no real renderbuffer object made yet */
983 newRb = NULL;
984 }
Ian Romanicka13f9df2012-12-01 10:50:57 -0800985 else if (!newRb
986 && _mesa_is_desktop_gl(ctx)
987 && ctx->Extensions.ARB_framebuffer_object) {
Brian Paul1bc59bf2009-01-22 15:07:34 -0700988 /* All RB IDs must be Gen'd */
989 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
990 return;
991 }
992
Brian Paul3deaa012005-02-07 05:08:24 +0000993 if (!newRb) {
994 /* create new renderbuffer object */
Brian Paul2c6f9112005-02-24 05:47:06 +0000995 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
Brian Paul3deaa012005-02-07 05:08:24 +0000996 if (!newRb) {
997 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
998 return;
999 }
Brian Paul2c6f9112005-02-24 05:47:06 +00001000 ASSERT(newRb->AllocStorage);
Brian Paul1864c7d2005-02-08 03:46:37 +00001001 _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
Brian42aaa542007-03-25 10:39:36 -06001002 newRb->RefCount = 1; /* referenced by hash table */
Brian Paul3deaa012005-02-07 05:08:24 +00001003 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001004 }
Brian Paul463642c2005-02-08 02:06:00 +00001005 else {
1006 newRb = NULL;
1007 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001008
Brian Paul1864c7d2005-02-08 03:46:37 +00001009 ASSERT(newRb != &DummyRenderbuffer);
1010
Brian42aaa542007-03-25 10:39:36 -06001011 _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
Brian Paulddc82ee2005-02-05 19:56:45 +00001012}
1013
1014
Brian Pauld0f13fa2009-01-21 11:17:45 -07001015/**
1016 * If the given renderbuffer is anywhere attached to the framebuffer, detach
1017 * the renderbuffer.
1018 * This is used when a renderbuffer object is deleted.
1019 * The spec calls for unbinding.
1020 */
1021static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001022detach_renderbuffer(struct gl_context *ctx,
Brian Pauld0f13fa2009-01-21 11:17:45 -07001023 struct gl_framebuffer *fb,
1024 struct gl_renderbuffer *rb)
1025{
1026 GLuint i;
1027 for (i = 0; i < BUFFER_COUNT; i++) {
1028 if (fb->Attachment[i].Renderbuffer == rb) {
1029 _mesa_remove_attachment(ctx, &fb->Attachment[i]);
1030 }
1031 }
Brian Paul72966362009-01-21 16:28:38 -07001032 invalidate_framebuffer(fb);
Brian Pauld0f13fa2009-01-21 11:17:45 -07001033}
1034
1035
Brian Paul1864c7d2005-02-08 03:46:37 +00001036void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001037_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001038{
1039 GLint i;
1040 GET_CURRENT_CONTEXT(ctx);
1041
Brian Paul474f28e2005-10-08 14:41:17 +00001042 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00001043
1044 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001045 if (renderbuffers[i] > 0) {
1046 struct gl_renderbuffer *rb;
Brian Paulea4fe662006-03-26 05:22:17 +00001047 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
Brian Paul3deaa012005-02-07 05:08:24 +00001048 if (rb) {
Brian Paul91802fd2005-10-04 16:01:02 +00001049 /* check if deleting currently bound renderbuffer object */
1050 if (rb == ctx->CurrentRenderbuffer) {
1051 /* bind default */
1052 ASSERT(rb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001053 _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
Brian Paul91802fd2005-10-04 16:01:02 +00001054 }
1055
Brian Paul36ede892012-01-12 09:17:23 -07001056 if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
Brian Pauld0f13fa2009-01-21 11:17:45 -07001057 detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
1058 }
Brian Paul36ede892012-01-12 09:17:23 -07001059 if (_mesa_is_user_fbo(ctx->ReadBuffer)
Brian Paulfc8c4a32011-06-16 07:31:58 -06001060 && ctx->ReadBuffer != ctx->DrawBuffer) {
Brian Pauld0f13fa2009-01-21 11:17:45 -07001061 detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
1062 }
1063
Brian42aaa542007-03-25 10:39:36 -06001064 /* Remove from hash table immediately, to free the ID.
1065 * But the object will not be freed until it's no longer
1066 * referenced anywhere else.
1067 */
Brian Paul3deaa012005-02-07 05:08:24 +00001068 _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00001069
Brian Paul1864c7d2005-02-08 03:46:37 +00001070 if (rb != &DummyRenderbuffer) {
Brian42aaa542007-03-25 10:39:36 -06001071 /* no longer referenced by hash table */
1072 _mesa_reference_renderbuffer(&rb, NULL);
Brian Paul3deaa012005-02-07 05:08:24 +00001073 }
1074 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001075 }
1076 }
1077}
1078
1079
Brian Paul1864c7d2005-02-08 03:46:37 +00001080void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001081_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001082{
1083 GET_CURRENT_CONTEXT(ctx);
1084 GLuint first;
1085 GLint i;
1086
Brian Paulddc82ee2005-02-05 19:56:45 +00001087 if (n < 0) {
1088 _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
1089 return;
1090 }
1091
1092 if (!renderbuffers)
1093 return;
1094
1095 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1096
1097 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001098 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001099 renderbuffers[i] = name;
Brian Paul1864c7d2005-02-08 03:46:37 +00001100 /* insert dummy placeholder into hash table */
Brian Paulddc82ee2005-02-05 19:56:45 +00001101 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
Brian Paul1864c7d2005-02-08 03:46:37 +00001102 _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
Brian Paulddc82ee2005-02-05 19:56:45 +00001103 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
Brian Paulddc82ee2005-02-05 19:56:45 +00001104 }
1105}
1106
1107
Brian Pauld9468c92005-02-10 16:08:07 +00001108/**
Brian Paulf41bbc72011-01-24 19:38:52 -07001109 * Given an internal format token for a render buffer, return the
Brian Paul976ea9d2011-01-24 19:38:52 -07001110 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
1111 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
1112 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
Brian Paulf41bbc72011-01-24 19:38:52 -07001113 *
Brian Paul976ea9d2011-01-24 19:38:52 -07001114 * This is similar to _mesa_base_tex_format() but the set of valid
1115 * internal formats is different.
Brian Paulf41bbc72011-01-24 19:38:52 -07001116 *
Brian Paul976ea9d2011-01-24 19:38:52 -07001117 * Note that even if a format is determined to be legal here, validation
Brian Paulb3cfcdf2011-01-28 20:25:26 -07001118 * of the FBO may fail if the format is not supported by the driver/GPU.
Brian Paul976ea9d2011-01-24 19:38:52 -07001119 *
1120 * \param internalFormat as passed to glRenderbufferStorage()
1121 * \return the base internal format, or 0 if internalFormat is illegal
Brian Pauld9468c92005-02-10 16:08:07 +00001122 */
Brian Paul59e0faa2006-03-15 17:48:00 +00001123GLenum
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001124_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
Brian Paul463642c2005-02-08 02:06:00 +00001125{
Brian Paul976ea9d2011-01-24 19:38:52 -07001126 /*
1127 * Notes: some formats such as alpha, luminance, etc. were added
1128 * with GL_ARB_framebuffer_object.
1129 */
Brian Paul463642c2005-02-08 02:06:00 +00001130 switch (internalFormat) {
Brian Paulf41bbc72011-01-24 19:38:52 -07001131 case GL_ALPHA:
1132 case GL_ALPHA4:
1133 case GL_ALPHA8:
1134 case GL_ALPHA12:
1135 case GL_ALPHA16:
Paul Berrydbd61352012-11-27 12:26:51 -08001136 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001137 ? GL_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07001138 case GL_LUMINANCE:
1139 case GL_LUMINANCE4:
1140 case GL_LUMINANCE8:
1141 case GL_LUMINANCE12:
1142 case GL_LUMINANCE16:
Paul Berrydbd61352012-11-27 12:26:51 -08001143 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001144 ? GL_LUMINANCE : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07001145 case GL_LUMINANCE_ALPHA:
1146 case GL_LUMINANCE4_ALPHA4:
1147 case GL_LUMINANCE6_ALPHA2:
1148 case GL_LUMINANCE8_ALPHA8:
1149 case GL_LUMINANCE12_ALPHA4:
1150 case GL_LUMINANCE12_ALPHA12:
1151 case GL_LUMINANCE16_ALPHA16:
Paul Berrydbd61352012-11-27 12:26:51 -08001152 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001153 ? GL_LUMINANCE_ALPHA : 0;
Brian Paul976ea9d2011-01-24 19:38:52 -07001154 case GL_INTENSITY:
1155 case GL_INTENSITY4:
1156 case GL_INTENSITY8:
1157 case GL_INTENSITY12:
1158 case GL_INTENSITY16:
Paul Berrydbd61352012-11-27 12:26:51 -08001159 return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
Ian Romanickf0c99d02012-07-27 08:31:12 -07001160 ? GL_INTENSITY : 0;
1161 case GL_RGB8:
1162 return GL_RGB;
Brian Paulf41bbc72011-01-24 19:38:52 -07001163 case GL_RGB:
1164 case GL_R3_G3_B2:
1165 case GL_RGB4:
1166 case GL_RGB5:
Brian Paulf41bbc72011-01-24 19:38:52 -07001167 case GL_RGB10:
1168 case GL_RGB12:
1169 case GL_RGB16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001170 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001171 case GL_SRGB8_EXT:
Matt Turnercbef5372012-11-20 13:45:03 -08001172 return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001173 case GL_RGBA4:
1174 case GL_RGB5_A1:
1175 case GL_RGBA8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001176 return GL_RGBA;
1177 case GL_RGBA:
1178 case GL_RGBA2:
Brian Paulf41bbc72011-01-24 19:38:52 -07001179 case GL_RGBA12:
1180 case GL_RGBA16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001181 return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
1182 case GL_RGB10_A2:
Brian Paulf41bbc72011-01-24 19:38:52 -07001183 case GL_SRGB8_ALPHA8_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001184 return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001185 case GL_STENCIL_INDEX:
1186 case GL_STENCIL_INDEX1_EXT:
1187 case GL_STENCIL_INDEX4_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00001188 case GL_STENCIL_INDEX16_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001189 /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
1190 * OpenGL ES, but Mesa does not currently support them.
1191 */
1192 return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
1193 case GL_STENCIL_INDEX8_EXT:
Brian Paulf0bbbf62005-02-09 03:50:30 +00001194 return GL_STENCIL_INDEX;
1195 case GL_DEPTH_COMPONENT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001196 case GL_DEPTH_COMPONENT32:
1197 return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
Brian Paul2c6f9112005-02-24 05:47:06 +00001198 case GL_DEPTH_COMPONENT16:
1199 case GL_DEPTH_COMPONENT24:
Brian Paulf0bbbf62005-02-09 03:50:30 +00001200 return GL_DEPTH_COMPONENT;
Brian Paulf41bbc72011-01-24 19:38:52 -07001201 case GL_DEPTH_STENCIL_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001202 return _mesa_is_desktop_gl(ctx)
1203 && ctx->Extensions.EXT_packed_depth_stencil
1204 ? GL_DEPTH_STENCIL_EXT : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001205 case GL_DEPTH24_STENCIL8_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001206 return ctx->Extensions.EXT_packed_depth_stencil
1207 ? GL_DEPTH_STENCIL_EXT : 0;
Marek Olšák11652802011-06-01 15:48:51 +02001208 case GL_DEPTH_COMPONENT32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001209 return ctx->Version >= 30
Paul Berrydbd61352012-11-27 12:26:51 -08001210 || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07001211 ? GL_DEPTH_COMPONENT : 0;
Marek Olšák11652802011-06-01 15:48:51 +02001212 case GL_DEPTH32F_STENCIL8:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001213 return ctx->Version >= 30
Paul Berrydbd61352012-11-27 12:26:51 -08001214 || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07001215 ? GL_DEPTH_STENCIL : 0;
Brian Pauld3015652011-01-24 19:38:52 -07001216 case GL_RED:
Brian Pauld3015652011-01-24 19:38:52 -07001217 case GL_R16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001218 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1219 ? GL_RED : 0;
1220 case GL_R8:
1221 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1222 ? GL_RED : 0;
Brian Pauld3015652011-01-24 19:38:52 -07001223 case GL_RG:
Brian Pauld3015652011-01-24 19:38:52 -07001224 case GL_RG16:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001225 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1226 ? GL_RG : 0;
1227 case GL_RG8:
1228 return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1229 ? GL_RG : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01001230 /* signed normalized texture formats */
Ian Romanickf0c99d02012-07-27 08:31:12 -07001231 case GL_RED_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001232 case GL_R8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001233 case GL_R16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001234 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1235 ? GL_RED : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07001236 case GL_RG_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001237 case GL_RG8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001238 case GL_RG16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001239 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1240 ? GL_RG : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07001241 case GL_RGB_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001242 case GL_RGB8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001243 case GL_RGB16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001244 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1245 ? GL_RGB : 0;
Ian Romanickf0c99d02012-07-27 08:31:12 -07001246 case GL_RGBA_SNORM:
Ian Romanick2aae3ab2012-12-04 10:36:10 -08001247 case GL_RGBA8_SNORM:
Marek Olšák0be36992011-03-18 13:44:51 +01001248 case GL_RGBA16_SNORM:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001249 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1250 ? GL_RGBA : 0;
Marek Olšák0be36992011-03-18 13:44:51 +01001251 case GL_ALPHA_SNORM:
1252 case GL_ALPHA8_SNORM:
1253 case GL_ALPHA16_SNORM:
Paul Berrydbd61352012-11-27 12:26:51 -08001254 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001255 ctx->Extensions.EXT_texture_snorm &&
Marek Olšák0be36992011-03-18 13:44:51 +01001256 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001257 case GL_R16F:
1258 case GL_R32F:
Jordan Justen119002a2013-01-10 17:29:27 -08001259 return ((_mesa_is_desktop_gl(ctx) &&
1260 ctx->Extensions.ARB_texture_rg &&
1261 ctx->Extensions.ARB_texture_float) ||
1262 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1263 ? GL_RED : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001264 case GL_RG16F:
1265 case GL_RG32F:
Jordan Justen119002a2013-01-10 17:29:27 -08001266 return ((_mesa_is_desktop_gl(ctx) &&
1267 ctx->Extensions.ARB_texture_rg &&
1268 ctx->Extensions.ARB_texture_float) ||
1269 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1270 ? GL_RG : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001271 case GL_RGB16F:
1272 case GL_RGB32F:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001273 return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
Ian Romanickf0c99d02012-07-27 08:31:12 -07001274 ? GL_RGB : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001275 case GL_RGBA16F:
1276 case GL_RGBA32F:
Jordan Justen119002a2013-01-10 17:29:27 -08001277 return ((_mesa_is_desktop_gl(ctx) &&
1278 ctx->Extensions.ARB_texture_float) ||
1279 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Ian Romanickf0c99d02012-07-27 08:31:12 -07001280 ? GL_RGBA : 0;
Marek Olšák15f99d12011-02-16 00:35:44 +01001281 case GL_ALPHA16F_ARB:
1282 case GL_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001283 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001284 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001285 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1286 case GL_LUMINANCE16F_ARB:
1287 case GL_LUMINANCE32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001288 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001289 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001290 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1291 case GL_LUMINANCE_ALPHA16F_ARB:
1292 case GL_LUMINANCE_ALPHA32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001293 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001294 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001295 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1296 case GL_INTENSITY16F_ARB:
1297 case GL_INTENSITY32F_ARB:
Paul Berrydbd61352012-11-27 12:26:51 -08001298 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001299 ctx->Extensions.ARB_texture_float &&
Marek Olšák15f99d12011-02-16 00:35:44 +01001300 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
Marek Olšák9d7698c2011-04-26 02:18:24 +02001301 case GL_RGB9_E5:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001302 return (_mesa_is_desktop_gl(ctx)
1303 && ctx->Extensions.EXT_texture_shared_exponent)
Matt Turnercbef5372012-11-20 13:45:03 -08001304 ? GL_RGB : 0;
Marek Olšák631d23d2011-04-26 02:27:25 +02001305 case GL_R11F_G11F_B10F:
Jordan Justen119002a2013-01-10 17:29:27 -08001306 return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
1307 _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
Matt Turnercbef5372012-11-20 13:45:03 -08001308 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001309
1310 case GL_RGBA8UI_EXT:
1311 case GL_RGBA16UI_EXT:
1312 case GL_RGBA32UI_EXT:
1313 case GL_RGBA8I_EXT:
1314 case GL_RGBA16I_EXT:
1315 case GL_RGBA32I_EXT:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001316 return ctx->Version >= 30
1317 || (_mesa_is_desktop_gl(ctx) &&
1318 ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001319
1320 case GL_RGB8UI_EXT:
1321 case GL_RGB16UI_EXT:
1322 case GL_RGB32UI_EXT:
1323 case GL_RGB8I_EXT:
1324 case GL_RGB16I_EXT:
1325 case GL_RGB32I_EXT:
Ian Romanicka86d6292012-12-03 11:55:12 -08001326 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
1327 ? GL_RGB : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001328 case GL_R8UI:
1329 case GL_R8I:
1330 case GL_R16UI:
1331 case GL_R16I:
1332 case GL_R32UI:
1333 case GL_R32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001334 return ctx->Version >= 30
1335 || (_mesa_is_desktop_gl(ctx) &&
1336 ctx->Extensions.ARB_texture_rg &&
1337 ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
Dave Airlie9c697a92011-10-04 20:59:40 +01001338
1339 case GL_RG8UI:
1340 case GL_RG8I:
1341 case GL_RG16UI:
1342 case GL_RG16I:
1343 case GL_RG32UI:
1344 case GL_RG32I:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001345 return ctx->Version >= 30
1346 || (_mesa_is_desktop_gl(ctx) &&
1347 ctx->Extensions.ARB_texture_rg &&
1348 ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
Brian Paul45bd5c42011-12-16 08:44:43 -07001349
Dave Airlie9c697a92011-10-04 20:59:40 +01001350 case GL_INTENSITY8I_EXT:
1351 case GL_INTENSITY8UI_EXT:
1352 case GL_INTENSITY16I_EXT:
1353 case GL_INTENSITY16UI_EXT:
1354 case GL_INTENSITY32I_EXT:
1355 case GL_INTENSITY32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001356 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001357 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01001358 ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1359
1360 case GL_LUMINANCE8I_EXT:
1361 case GL_LUMINANCE8UI_EXT:
1362 case GL_LUMINANCE16I_EXT:
1363 case GL_LUMINANCE16UI_EXT:
1364 case GL_LUMINANCE32I_EXT:
1365 case GL_LUMINANCE32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001366 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001367 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01001368 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1369
1370 case GL_LUMINANCE_ALPHA8I_EXT:
1371 case GL_LUMINANCE_ALPHA8UI_EXT:
1372 case GL_LUMINANCE_ALPHA16I_EXT:
1373 case GL_LUMINANCE_ALPHA16UI_EXT:
1374 case GL_LUMINANCE_ALPHA32I_EXT:
1375 case GL_LUMINANCE_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001376 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001377 ctx->Extensions.EXT_texture_integer &&
Dave Airlie9c697a92011-10-04 20:59:40 +01001378 ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
Dave Airlief449be62011-11-27 16:21:02 +00001379
Marek Olšák636802f2012-01-22 20:21:36 +01001380 case GL_ALPHA8I_EXT:
1381 case GL_ALPHA8UI_EXT:
1382 case GL_ALPHA16I_EXT:
1383 case GL_ALPHA16UI_EXT:
1384 case GL_ALPHA32I_EXT:
1385 case GL_ALPHA32UI_EXT:
Paul Berrydbd61352012-11-27 12:26:51 -08001386 return ctx->API == API_OPENGL_COMPAT &&
Ian Romanickf0c99d02012-07-27 08:31:12 -07001387 ctx->Extensions.EXT_texture_integer &&
Marek Olšák636802f2012-01-22 20:21:36 +01001388 ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1389
Dave Airlief449be62011-11-27 16:21:02 +00001390 case GL_RGB10_A2UI:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001391 return (_mesa_is_desktop_gl(ctx) &&
1392 ctx->Extensions.ARB_texture_rgb10_a2ui)
1393 || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
Marek Olšák1a06e842012-07-12 14:07:41 +02001394
1395 case GL_RGB565:
Ian Romanickf0c99d02012-07-27 08:31:12 -07001396 return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
1397 ? GL_RGB : 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001398 default:
Eric Anholt65c41d52011-01-13 10:05:50 -08001399 return 0;
Brian Paulf41bbc72011-01-24 19:38:52 -07001400 }
Brian Paul463642c2005-02-08 02:06:00 +00001401}
1402
1403
Marek Olšákdf818d52011-03-06 05:26:12 +01001404/**
1405 * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk().
1406 */
1407static void
1408invalidate_rb(GLuint key, void *data, void *userData)
1409{
1410 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
1411 struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
1412
1413 /* If this is a user-created FBO */
Brian Paul36ede892012-01-12 09:17:23 -07001414 if (_mesa_is_user_fbo(fb)) {
Marek Olšákdf818d52011-03-06 05:26:12 +01001415 GLuint i;
1416 for (i = 0; i < BUFFER_COUNT; i++) {
1417 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1418 if (att->Type == GL_RENDERBUFFER &&
1419 att->Renderbuffer == rb) {
1420 /* Mark fb status as indeterminate to force re-validation */
1421 fb->_Status = 0;
Marek Olšáka674ef72011-03-07 23:33:36 +01001422 return;
Marek Olšákdf818d52011-03-06 05:26:12 +01001423 }
1424 }
1425 }
1426}
1427
1428
Brian Paul4f3514e2009-01-22 15:19:56 -07001429/** sentinal value, see below */
1430#define NO_SAMPLES 1000
1431
1432
1433/**
Paul Berry1a1db172012-11-06 08:57:59 -08001434 * Helper function used by _mesa_RenderbufferStorage() and
Brian Paul4f3514e2009-01-22 15:19:56 -07001435 * _mesa_RenderbufferStorageMultisample().
Paul Berry1a1db172012-11-06 08:57:59 -08001436 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
Brian Paul4f3514e2009-01-22 15:19:56 -07001437 */
1438static void
1439renderbuffer_storage(GLenum target, GLenum internalFormat,
1440 GLsizei width, GLsizei height, GLsizei samples)
Brian Paulddc82ee2005-02-05 19:56:45 +00001441{
Brian Paul4f3514e2009-01-22 15:19:56 -07001442 const char *func = samples == NO_SAMPLES ?
Jordan Justen275620c2013-01-12 14:19:30 -08001443 "glRenderbufferStorage" : "glRenderbufferStorageMultisample";
Brian Paul2c6f9112005-02-24 05:47:06 +00001444 struct gl_renderbuffer *rb;
Brian Paul463642c2005-02-08 02:06:00 +00001445 GLenum baseFormat;
Brian Paulddc82ee2005-02-05 19:56:45 +00001446 GET_CURRENT_CONTEXT(ctx);
1447
Jordan Justen275620c2013-01-12 14:19:30 -08001448 if (MESA_VERBOSE & VERBOSE_API) {
1449 if (samples == NO_SAMPLES)
1450 _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
1451 func,
1452 _mesa_lookup_enum_by_nr(target),
1453 _mesa_lookup_enum_by_nr(internalFormat),
1454 width, height);
1455 else
1456 _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
1457 func,
1458 _mesa_lookup_enum_by_nr(target),
1459 _mesa_lookup_enum_by_nr(internalFormat),
1460 width, height, samples);
1461 }
1462
Brian Paul463642c2005-02-08 02:06:00 +00001463 if (target != GL_RENDERBUFFER_EXT) {
Brian Paul4f3514e2009-01-22 15:19:56 -07001464 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00001465 return;
1466 }
1467
Brian Paul59e0faa2006-03-15 17:48:00 +00001468 baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
Brian Paul463642c2005-02-08 02:06:00 +00001469 if (baseFormat == 0) {
Jordan Justen119002a2013-01-10 17:29:27 -08001470 _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
1471 func, _mesa_lookup_enum_by_nr(internalFormat));
Brian Paulddc82ee2005-02-05 19:56:45 +00001472 return;
1473 }
1474
Yuanhan Liu49f84472011-10-25 15:36:59 +08001475 if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Brian Paul4f3514e2009-01-22 15:19:56 -07001476 _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00001477 return;
1478 }
1479
Yuanhan Liu49f84472011-10-25 15:36:59 +08001480 if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
Brian Paul4f3514e2009-01-22 15:19:56 -07001481 _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
1482 return;
1483 }
1484
1485 if (samples == NO_SAMPLES) {
1486 /* NumSamples == 0 indicates non-multisampling */
1487 samples = 0;
1488 }
Brian Paulca0d0482010-01-27 17:01:54 -07001489 else if (samples > (GLsizei) ctx->Const.MaxSamples) {
Brian Paul722d9762009-01-20 16:58:49 -07001490 /* note: driver may choose to use more samples than what's requested */
Brian Paul4f3514e2009-01-22 15:19:56 -07001491 _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func);
Brian Paulddc82ee2005-02-05 19:56:45 +00001492 return;
1493 }
1494
Brian Paul2c6f9112005-02-24 05:47:06 +00001495 rb = ctx->CurrentRenderbuffer;
Brian Paul2c6f9112005-02-24 05:47:06 +00001496 if (!rb) {
Vinson Leec5dde532010-09-02 16:03:32 -07001497 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
Brian Paul463642c2005-02-08 02:06:00 +00001498 return;
1499 }
1500
Brian Paul474f28e2005-10-08 14:41:17 +00001501 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1502
Brian Paul311bcf52005-11-18 02:24:14 +00001503 if (rb->InternalFormat == internalFormat &&
Brian Paul13abf912006-04-13 19:17:13 +00001504 rb->Width == (GLuint) width &&
Eric Anholt0e8d1562012-01-11 13:46:43 -08001505 rb->Height == (GLuint) height &&
1506 rb->NumSamples == samples) {
Brian Paul311bcf52005-11-18 02:24:14 +00001507 /* no change in allocation needed */
1508 return;
1509 }
1510
Brian Paulea4fe662006-03-26 05:22:17 +00001511 /* These MUST get set by the AllocStorage func */
Brian Paul45e76d22009-10-08 20:27:27 -06001512 rb->Format = MESA_FORMAT_NONE;
Brian Paul4f3514e2009-01-22 15:19:56 -07001513 rb->NumSamples = samples;
Brian Paulea4fe662006-03-26 05:22:17 +00001514
Brian Paul2c6f9112005-02-24 05:47:06 +00001515 /* Now allocate the storage */
1516 ASSERT(rb->AllocStorage);
1517 if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
1518 /* No error - check/set fields now */
Marek Olšáka82227c2012-06-15 17:21:05 +02001519 /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
Brian Paul13abf912006-04-13 19:17:13 +00001520 assert(rb->Width == (GLuint) width);
1521 assert(rb->Height == (GLuint) height);
Brian Paulea4fe662006-03-26 05:22:17 +00001522 rb->InternalFormat = internalFormat;
Brian Paula8dafe72010-02-25 19:03:55 -07001523 rb->_BaseFormat = baseFormat;
Brian Paul45e76d22009-10-08 20:27:27 -06001524 assert(rb->_BaseFormat != 0);
Brian Paul2c6f9112005-02-24 05:47:06 +00001525 }
1526 else {
1527 /* Probably ran out of memory - clear the fields */
1528 rb->Width = 0;
1529 rb->Height = 0;
Brian Paul45e76d22009-10-08 20:27:27 -06001530 rb->Format = MESA_FORMAT_NONE;
Brian Paul2c6f9112005-02-24 05:47:06 +00001531 rb->InternalFormat = GL_NONE;
1532 rb->_BaseFormat = GL_NONE;
Brian Paul4f3514e2009-01-22 15:19:56 -07001533 rb->NumSamples = 0;
Brian Paul463642c2005-02-08 02:06:00 +00001534 }
1535
Marek Olšákdf818d52011-03-06 05:26:12 +01001536 /* Invalidate the framebuffers the renderbuffer is attached in. */
1537 if (rb->AttachedAnytime) {
1538 _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
1539 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001540}
1541
Brian Paul23c5b212010-05-28 13:33:03 -06001542
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001543void GLAPIENTRY
Brian Paul23c5b212010-05-28 13:33:03 -06001544_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001545{
Brian Paul51b79922010-02-24 11:57:26 -07001546 struct gl_renderbuffer *rb;
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001547 GET_CURRENT_CONTEXT(ctx);
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001548
Chia-I Wu2002e4d02010-04-06 17:46:17 +08001549 if (!ctx->Extensions.OES_EGL_image) {
1550 _mesa_error(ctx, GL_INVALID_OPERATION,
1551 "glEGLImageTargetRenderbufferStorageOES(unsupported)");
1552 return;
1553 }
1554
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001555 if (target != GL_RENDERBUFFER) {
Brian Paul23c5b212010-05-28 13:33:03 -06001556 _mesa_error(ctx, GL_INVALID_ENUM,
1557 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001558 return;
1559 }
1560
1561 rb = ctx->CurrentRenderbuffer;
1562 if (!rb) {
Brian Paul23c5b212010-05-28 13:33:03 -06001563 _mesa_error(ctx, GL_INVALID_OPERATION,
1564 "EGLImageTargetRenderbufferStorageOES");
Kristian Høgsbergd1dc5b12010-02-11 17:42:30 -05001565 return;
1566 }
1567
1568 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1569
1570 ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
1571}
Brian Paulddc82ee2005-02-05 19:56:45 +00001572
Brian Paul23c5b212010-05-28 13:33:03 -06001573
Brian Paul45e76d22009-10-08 20:27:27 -06001574/**
Paul Berry1a1db172012-11-06 08:57:59 -08001575 * Helper function for _mesa_GetRenderbufferParameteriv() and
1576 * _mesa_GetFramebufferAttachmentParameteriv()
Brian Paul45e76d22009-10-08 20:27:27 -06001577 * We have to be careful to respect the base format. For example, if a
1578 * renderbuffer/texture was created with internalFormat=GL_RGB but the
1579 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
1580 * we need to return zero.
1581 */
1582static GLint
1583get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
1584{
Brian Paulf0b6e9a2011-11-23 15:33:45 -07001585 if (_mesa_base_format_has_channel(baseFormat, pname))
1586 return _mesa_get_format_bits(format, pname);
1587 else
Brian Paul45e76d22009-10-08 20:27:27 -06001588 return 0;
Brian Paul45e76d22009-10-08 20:27:27 -06001589}
1590
1591
1592
Brian Paul1864c7d2005-02-08 03:46:37 +00001593void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001594_mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
Brian Paul4f3514e2009-01-22 15:19:56 -07001595 GLsizei width, GLsizei height)
1596{
Brian Paul722d9762009-01-20 16:58:49 -07001597 /* GL_ARB_fbo says calling this function is equivalent to calling
1598 * glRenderbufferStorageMultisample() with samples=0. We pass in
1599 * a token value here just for error reporting purposes.
1600 */
Brian Paul4f3514e2009-01-22 15:19:56 -07001601 renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
1602}
1603
1604
1605void GLAPIENTRY
Brian Paul777a2ef2009-01-22 15:17:42 -07001606_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
Brian Paul4f3514e2009-01-22 15:19:56 -07001607 GLenum internalFormat,
Brian Paul777a2ef2009-01-22 15:17:42 -07001608 GLsizei width, GLsizei height)
1609{
Brian Paul4f3514e2009-01-22 15:19:56 -07001610 renderbuffer_storage(target, internalFormat, width, height, samples);
Brian Paul777a2ef2009-01-22 15:17:42 -07001611}
1612
Brian Paul23c5b212010-05-28 13:33:03 -06001613
1614/**
1615 * OpenGL ES version of glRenderBufferStorage.
1616 */
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04001617void GLAPIENTRY
1618_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1619 GLsizei width, GLsizei height)
1620{
1621 switch (internalFormat) {
1622 case GL_RGB565:
1623 /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
1624 /* choose a closest format */
1625 internalFormat = GL_RGB5;
1626 break;
1627 default:
1628 break;
1629 }
Brian Paul777a2ef2009-01-22 15:17:42 -07001630
Kristian Høgsberg61d94dd2010-04-22 21:11:56 -04001631 renderbuffer_storage(target, internalFormat, width, height, 0);
1632}
Brian Paul777a2ef2009-01-22 15:17:42 -07001633
Brian Paul23c5b212010-05-28 13:33:03 -06001634
Brian Paul777a2ef2009-01-22 15:17:42 -07001635void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001636_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
Brian Paulddc82ee2005-02-05 19:56:45 +00001637{
Brian Paul722d9762009-01-20 16:58:49 -07001638 struct gl_renderbuffer *rb;
Brian Paulddc82ee2005-02-05 19:56:45 +00001639 GET_CURRENT_CONTEXT(ctx);
1640
Brian Paul463642c2005-02-08 02:06:00 +00001641 if (target != GL_RENDERBUFFER_EXT) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001642 _mesa_error(ctx, GL_INVALID_ENUM,
1643 "glGetRenderbufferParameterivEXT(target)");
1644 return;
1645 }
1646
Brian Paul722d9762009-01-20 16:58:49 -07001647 rb = ctx->CurrentRenderbuffer;
1648 if (!rb) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001649 _mesa_error(ctx, GL_INVALID_OPERATION,
1650 "glGetRenderbufferParameterivEXT");
1651 return;
1652 }
1653
Brian Paul800e5532009-11-02 15:39:39 -07001654 /* No need to flush here since we're just quering state which is
1655 * not effected by rendering.
1656 */
Brian Paul474f28e2005-10-08 14:41:17 +00001657
Brian Paul463642c2005-02-08 02:06:00 +00001658 switch (pname) {
1659 case GL_RENDERBUFFER_WIDTH_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07001660 *params = rb->Width;
Brian Paul463642c2005-02-08 02:06:00 +00001661 return;
1662 case GL_RENDERBUFFER_HEIGHT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07001663 *params = rb->Height;
Brian Paul463642c2005-02-08 02:06:00 +00001664 return;
1665 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
Brian Paul722d9762009-01-20 16:58:49 -07001666 *params = rb->InternalFormat;
Brian Paul463642c2005-02-08 02:06:00 +00001667 return;
Brian Paul1b939532005-05-31 23:55:21 +00001668 case GL_RENDERBUFFER_RED_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001669 case GL_RENDERBUFFER_GREEN_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001670 case GL_RENDERBUFFER_BLUE_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001671 case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001672 case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
Brian Paul1b939532005-05-31 23:55:21 +00001673 case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
Brian Paul45e76d22009-10-08 20:27:27 -06001674 *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
Brian Paul1b939532005-05-31 23:55:21 +00001675 break;
Brian Paul722d9762009-01-20 16:58:49 -07001676 case GL_RENDERBUFFER_SAMPLES:
Ian Romanickae86ebf2012-07-27 07:49:49 -07001677 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
1678 || _mesa_is_gles3(ctx)) {
Brian Paul722d9762009-01-20 16:58:49 -07001679 *params = rb->NumSamples;
1680 break;
1681 }
1682 /* fallthrough */
Brian Paul463642c2005-02-08 02:06:00 +00001683 default:
1684 _mesa_error(ctx, GL_INVALID_ENUM,
1685 "glGetRenderbufferParameterivEXT(target)");
1686 return;
1687 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001688}
1689
1690
Brian Paul1864c7d2005-02-08 03:46:37 +00001691GLboolean GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001692_mesa_IsFramebuffer(GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001693{
Brian Paulddc82ee2005-02-05 19:56:45 +00001694 GET_CURRENT_CONTEXT(ctx);
Brian Paulddc82ee2005-02-05 19:56:45 +00001695 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
Brian Paulbc6cced2005-10-04 15:01:27 +00001696 if (framebuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00001697 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
Brian Paulbc6cced2005-10-04 15:01:27 +00001698 if (rb != NULL && rb != &DummyFramebuffer)
1699 return GL_TRUE;
1700 }
1701 return GL_FALSE;
Brian Paulddc82ee2005-02-05 19:56:45 +00001702}
1703
1704
briana492ab72009-11-10 15:33:31 -07001705/**
1706 * Check if any of the attachments of the given framebuffer are textures
1707 * (render to texture). Call ctx->Driver.RenderTexture() for such
1708 * attachments.
1709 */
Brian Paulea4fe662006-03-26 05:22:17 +00001710static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001711check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paulea4fe662006-03-26 05:22:17 +00001712{
1713 GLuint i;
1714 ASSERT(ctx->Driver.RenderTexture);
briana65b84d2009-11-10 18:02:03 -07001715
Brian Paul36ede892012-01-12 09:17:23 -07001716 if (_mesa_is_winsys_fbo(fb))
briana65b84d2009-11-10 18:02:03 -07001717 return; /* can't render to texture with winsys framebuffers */
1718
Brian Paulea4fe662006-03-26 05:22:17 +00001719 for (i = 0; i < BUFFER_COUNT; i++) {
1720 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Brian Pauldb0f9e72011-04-05 07:51:01 -06001721 if (att->Texture && _mesa_get_attachment_teximage(att)) {
Brian Paulea4fe662006-03-26 05:22:17 +00001722 ctx->Driver.RenderTexture(ctx, fb, att);
1723 }
1724 }
1725}
1726
1727
Brian Paul0e31e022005-12-01 00:25:00 +00001728/**
1729 * Examine all the framebuffer's attachments to see if any are textures.
1730 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
1731 * notify the device driver that the texture image may have changed.
1732 */
1733static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04001734check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
Brian Paul0e31e022005-12-01 00:25:00 +00001735{
Brian Paul36ede892012-01-12 09:17:23 -07001736 if (_mesa_is_winsys_fbo(fb))
briana65b84d2009-11-10 18:02:03 -07001737 return; /* can't render to texture with winsys framebuffers */
1738
Brian Paul0e31e022005-12-01 00:25:00 +00001739 if (ctx->Driver.FinishRenderTexture) {
1740 GLuint i;
1741 for (i = 0; i < BUFFER_COUNT; i++) {
1742 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
Brian8b361662007-11-09 08:55:49 -07001743 if (att->Texture && att->Renderbuffer) {
Brian Paul519b23b2006-03-20 18:51:57 +00001744 ctx->Driver.FinishRenderTexture(ctx, att);
Brian Paul0e31e022005-12-01 00:25:00 +00001745 }
1746 }
1747 }
1748}
1749
1750
Brian Paul1864c7d2005-02-08 03:46:37 +00001751void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001752_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
Brian Paulddc82ee2005-02-05 19:56:45 +00001753{
briane6f60d32009-11-10 15:47:34 -07001754 struct gl_framebuffer *newDrawFb, *newReadFb;
briand96e55f2009-11-10 15:50:22 -07001755 struct gl_framebuffer *oldDrawFb, *oldReadFb;
Brian Paul0bffb112005-11-08 14:45:48 +00001756 GLboolean bindReadBuf, bindDrawBuf;
Brian Paulddc82ee2005-02-05 19:56:45 +00001757 GET_CURRENT_CONTEXT(ctx);
1758
Brian Paul1bc59bf2009-01-22 15:07:34 -07001759#ifdef DEBUG
1760 if (ctx->Extensions.ARB_framebuffer_object) {
1761 ASSERT(ctx->Extensions.EXT_framebuffer_object);
1762 ASSERT(ctx->Extensions.EXT_framebuffer_blit);
1763 }
1764#endif
1765
Brian Paulea4fe662006-03-26 05:22:17 +00001766 if (!ctx->Extensions.EXT_framebuffer_object) {
1767 _mesa_error(ctx, GL_INVALID_OPERATION,
1768 "glBindFramebufferEXT(unsupported)");
1769 return;
1770 }
1771
Brian Paul0bffb112005-11-08 14:45:48 +00001772 switch (target) {
Brian Paul0bffb112005-11-08 14:45:48 +00001773 case GL_DRAW_FRAMEBUFFER_EXT:
1774 if (!ctx->Extensions.EXT_framebuffer_blit) {
1775 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1776 return;
1777 }
1778 bindDrawBuf = GL_TRUE;
1779 bindReadBuf = GL_FALSE;
1780 break;
1781 case GL_READ_FRAMEBUFFER_EXT:
1782 if (!ctx->Extensions.EXT_framebuffer_blit) {
1783 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
1784 return;
1785 }
1786 bindDrawBuf = GL_FALSE;
1787 bindReadBuf = GL_TRUE;
1788 break;
Brian Paul0bffb112005-11-08 14:45:48 +00001789 case GL_FRAMEBUFFER_EXT:
1790 bindDrawBuf = GL_TRUE;
1791 bindReadBuf = GL_TRUE;
1792 break;
1793 default:
Brian Pauleba4ff62005-09-06 21:22:16 +00001794 _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00001795 return;
1796 }
1797
Brian Paul3deaa012005-02-07 05:08:24 +00001798 if (framebuffer) {
Brian Paule4b23562005-05-04 20:11:35 +00001799 /* Binding a user-created framebuffer object */
briane6f60d32009-11-10 15:47:34 -07001800 newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
1801 if (newDrawFb == &DummyFramebuffer) {
Brian Paul923b6fc2005-02-08 04:08:56 +00001802 /* ID was reserved, but no real framebuffer object made yet */
briane6f60d32009-11-10 15:47:34 -07001803 newDrawFb = NULL;
Brian Paul1864c7d2005-02-08 03:46:37 +00001804 }
Ian Romanicka13f9df2012-12-01 10:50:57 -08001805 else if (!newDrawFb
1806 && _mesa_is_desktop_gl(ctx)
1807 && ctx->Extensions.ARB_framebuffer_object) {
Brian Paul1bc59bf2009-01-22 15:07:34 -07001808 /* All FBO IDs must be Gen'd */
1809 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
1810 return;
1811 }
1812
briane6f60d32009-11-10 15:47:34 -07001813 if (!newDrawFb) {
Brian Paul3deaa012005-02-07 05:08:24 +00001814 /* create new framebuffer object */
briane6f60d32009-11-10 15:47:34 -07001815 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
1816 if (!newDrawFb) {
Brian Paul3deaa012005-02-07 05:08:24 +00001817 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
1818 return;
1819 }
briane6f60d32009-11-10 15:47:34 -07001820 _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
Brian Paul3deaa012005-02-07 05:08:24 +00001821 }
briane6f60d32009-11-10 15:47:34 -07001822 newReadFb = newDrawFb;
Brian Paul3deaa012005-02-07 05:08:24 +00001823 }
Brian Paul463642c2005-02-08 02:06:00 +00001824 else {
Brian Paule4b23562005-05-04 20:11:35 +00001825 /* Binding the window system framebuffer (which was originally set
1826 * with MakeCurrent).
1827 */
briane6f60d32009-11-10 15:47:34 -07001828 newDrawFb = ctx->WinSysDrawBuffer;
1829 newReadFb = ctx->WinSysReadBuffer;
Brian Paul3deaa012005-02-07 05:08:24 +00001830 }
1831
briane6f60d32009-11-10 15:47:34 -07001832 ASSERT(newDrawFb);
1833 ASSERT(newDrawFb != &DummyFramebuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00001834
briana65b84d2009-11-10 18:02:03 -07001835 /* save pointers to current/old framebuffers */
briand96e55f2009-11-10 15:50:22 -07001836 oldDrawFb = ctx->DrawBuffer;
1837 oldReadFb = ctx->ReadBuffer;
1838
briana65b84d2009-11-10 18:02:03 -07001839 /* check if really changing bindings */
1840 if (oldDrawFb == newDrawFb)
1841 bindDrawBuf = GL_FALSE;
1842 if (oldReadFb == newReadFb)
1843 bindReadBuf = GL_FALSE;
1844
Brian Paulea4fe662006-03-26 05:22:17 +00001845 /*
Brian Paul16144632009-02-26 14:49:24 -07001846 * OK, now bind the new Draw/Read framebuffers, if they're changing.
briana65b84d2009-11-10 18:02:03 -07001847 *
1848 * We also check if we're beginning and/or ending render-to-texture.
1849 * When a framebuffer with texture attachments is unbound, call
1850 * ctx->Driver.FinishRenderTexture().
1851 * When a framebuffer with texture attachments is bound, call
1852 * ctx->Driver.RenderTexture().
1853 *
1854 * Note that if the ReadBuffer has texture attachments we don't consider
1855 * that a render-to-texture case.
Brian Paulea4fe662006-03-26 05:22:17 +00001856 */
Brian Paul0bffb112005-11-08 14:45:48 +00001857 if (bindReadBuf) {
briana65b84d2009-11-10 18:02:03 -07001858 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
brianbc569cd2009-11-10 16:00:35 -07001859
briana65b84d2009-11-10 18:02:03 -07001860 /* check if old readbuffer was render-to-texture */
1861 check_end_texture_render(ctx, oldReadFb);
1862
1863 _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
Brian Paul0bffb112005-11-08 14:45:48 +00001864 }
1865
1866 if (bindDrawBuf) {
briana65b84d2009-11-10 18:02:03 -07001867 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian32d86eb2007-08-16 18:52:48 +01001868
Eric Anholta1fd13f2012-02-10 12:05:16 -08001869 /* check if old framebuffer had any texture attachments */
1870 if (oldDrawFb)
briana65b84d2009-11-10 18:02:03 -07001871 check_end_texture_render(ctx, oldDrawFb);
brianbc569cd2009-11-10 16:00:35 -07001872
briana65b84d2009-11-10 18:02:03 -07001873 /* check if newly bound framebuffer has any texture attachments */
1874 check_begin_texture_render(ctx, newDrawFb);
1875
1876 _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
Brian Paul0bffb112005-11-08 14:45:48 +00001877 }
Brian Paul59e0faa2006-03-15 17:48:00 +00001878
Brian Paul16144632009-02-26 14:49:24 -07001879 if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
briane6f60d32009-11-10 15:47:34 -07001880 ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
Brian Paul59e0faa2006-03-15 17:48:00 +00001881 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001882}
1883
1884
Brian Paul1864c7d2005-02-08 03:46:37 +00001885void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001886_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001887{
1888 GLint i;
1889 GET_CURRENT_CONTEXT(ctx);
1890
Brian Paul800e5532009-11-02 15:39:39 -07001891 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00001892
1893 for (i = 0; i < n; i++) {
Brian Paul2c6f9112005-02-24 05:47:06 +00001894 if (framebuffers[i] > 0) {
1895 struct gl_framebuffer *fb;
Brian Paulea4fe662006-03-26 05:22:17 +00001896 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
Brian Paul3deaa012005-02-07 05:08:24 +00001897 if (fb) {
Brian Paule4b23562005-05-04 20:11:35 +00001898 ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
Brian Paul91802fd2005-10-04 16:01:02 +00001899
1900 /* check if deleting currently bound framebuffer object */
Erik Wien68ca19a2010-01-26 13:19:30 -07001901 if (ctx->Extensions.EXT_framebuffer_blit) {
1902 /* separate draw/read binding points */
1903 if (fb == ctx->DrawBuffer) {
1904 /* bind default */
1905 ASSERT(fb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001906 _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
Erik Wien68ca19a2010-01-26 13:19:30 -07001907 }
1908 if (fb == ctx->ReadBuffer) {
1909 /* bind default */
1910 ASSERT(fb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001911 _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
Erik Wien68ca19a2010-01-26 13:19:30 -07001912 }
Brian Pauld0f13fa2009-01-21 11:17:45 -07001913 }
Erik Wien68ca19a2010-01-26 13:19:30 -07001914 else {
1915 /* only one binding point for read/draw buffers */
1916 if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
1917 /* bind default */
1918 ASSERT(fb->RefCount >= 2);
Paul Berry1a1db172012-11-06 08:57:59 -08001919 _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
Brian Paul45bd5c42011-12-16 08:44:43 -07001920 }
Brian Paul91802fd2005-10-04 16:01:02 +00001921 }
1922
Brian Paul3deaa012005-02-07 05:08:24 +00001923 /* remove from hash table immediately, to free the ID */
1924 _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
Brian Paulddc82ee2005-02-05 19:56:45 +00001925
Brian Paul1864c7d2005-02-08 03:46:37 +00001926 if (fb != &DummyFramebuffer) {
1927 /* But the object will not be freed until it's no longer
1928 * bound in any context.
1929 */
Brian Pauld5229442009-02-09 08:30:55 -07001930 _mesa_reference_framebuffer(&fb, NULL);
Brian Paul3deaa012005-02-07 05:08:24 +00001931 }
1932 }
Brian Paulddc82ee2005-02-05 19:56:45 +00001933 }
1934 }
1935}
1936
1937
Brian Paul1864c7d2005-02-08 03:46:37 +00001938void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001939_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
Brian Paulddc82ee2005-02-05 19:56:45 +00001940{
1941 GET_CURRENT_CONTEXT(ctx);
1942 GLuint first;
1943 GLint i;
1944
Brian Paulddc82ee2005-02-05 19:56:45 +00001945 if (n < 0) {
1946 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
1947 return;
1948 }
1949
1950 if (!framebuffers)
1951 return;
1952
1953 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
1954
1955 for (i = 0; i < n; i++) {
Brian Paulddc82ee2005-02-05 19:56:45 +00001956 GLuint name = first + i;
Brian Paulf0bbbf62005-02-09 03:50:30 +00001957 framebuffers[i] = name;
1958 /* insert dummy placeholder into hash table */
Brian Paulddc82ee2005-02-05 19:56:45 +00001959 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
Brian Paul1864c7d2005-02-08 03:46:37 +00001960 _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
Brian Paulddc82ee2005-02-05 19:56:45 +00001961 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
Brian Paulddc82ee2005-02-05 19:56:45 +00001962 }
1963}
1964
1965
1966
Brian Paul1864c7d2005-02-08 03:46:37 +00001967GLenum GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08001968_mesa_CheckFramebufferStatus(GLenum target)
Brian Paulddc82ee2005-02-05 19:56:45 +00001969{
Brian Paul0bffb112005-11-08 14:45:48 +00001970 struct gl_framebuffer *buffer;
Brian Paulddc82ee2005-02-05 19:56:45 +00001971 GET_CURRENT_CONTEXT(ctx);
1972
Brian Paule4b23562005-05-04 20:11:35 +00001973 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00001974
Jordan Justen7f867852013-01-12 19:21:54 -08001975 if (MESA_VERBOSE & VERBOSE_API)
1976 _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
1977 _mesa_lookup_enum_by_nr(target));
1978
Brian Paulc6991432011-02-28 18:24:25 -07001979 buffer = get_framebuffer_target(ctx, target);
1980 if (!buffer) {
Brian Paulf0bbbf62005-02-09 03:50:30 +00001981 _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
Brian Paulc6991432011-02-28 18:24:25 -07001982 return 0;
Brian Paulddc82ee2005-02-05 19:56:45 +00001983 }
1984
Brian Paul36ede892012-01-12 09:17:23 -07001985 if (_mesa_is_winsys_fbo(buffer)) {
Brian Paulf0bbbf62005-02-09 03:50:30 +00001986 /* The window system / default framebuffer is always complete */
1987 return GL_FRAMEBUFFER_COMPLETE_EXT;
1988 }
1989
Brian Paul800e5532009-11-02 15:39:39 -07001990 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00001991
Brian Paul72966362009-01-21 16:28:38 -07001992 if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
1993 _mesa_test_framebuffer_completeness(ctx, buffer);
1994 }
1995
Brian Paul0bffb112005-11-08 14:45:48 +00001996 return buffer->_Status;
Brian Paulddc82ee2005-02-05 19:56:45 +00001997}
1998
Brian Paul45bd5c42011-12-16 08:44:43 -07001999
Chad Versacebf8ad172011-11-10 10:19:20 -08002000/**
2001 * Replicate the src attachment point. Used by framebuffer_texture() when
2002 * the same texture is attached at GL_DEPTH_ATTACHMENT and
2003 * GL_STENCIL_ATTACHMENT.
2004 */
2005static void
2006reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
2007 gl_buffer_index dst,
2008 gl_buffer_index src)
2009{
2010 struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
2011 struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
Brian Paulddc82ee2005-02-05 19:56:45 +00002012
Chad Versacebf8ad172011-11-10 10:19:20 -08002013 assert(src_att->Texture != NULL);
Brian Paul45bd5c42011-12-16 08:44:43 -07002014 assert(src_att->Renderbuffer != NULL);
Chad Versacebf8ad172011-11-10 10:19:20 -08002015
2016 _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
2017 _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
2018 dst_att->Type = src_att->Type;
2019 dst_att->Complete = src_att->Complete;
2020 dst_att->TextureLevel = src_att->TextureLevel;
2021 dst_att->Zoffset = src_att->Zoffset;
2022}
Brian Paulddc82ee2005-02-05 19:56:45 +00002023
Brian Paul45bd5c42011-12-16 08:44:43 -07002024
Brian Paulddc82ee2005-02-05 19:56:45 +00002025/**
Brian Paul534cbbe2012-03-12 11:03:59 -06002026 * Common code called by glFramebufferTexture1D/2D/3DEXT() and
2027 * glFramebufferTextureLayerEXT().
2028 * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll
2029 * get textarget=0 in that case.
Brian Paulddc82ee2005-02-05 19:56:45 +00002030 */
Brian Paulea4fe662006-03-26 05:22:17 +00002031static void
Kristian Høgsbergf9995b32010-10-12 12:26:10 -04002032framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002033 GLenum attachment, GLenum textarget, GLuint texture,
Brian Paulea4fe662006-03-26 05:22:17 +00002034 GLint level, GLint zoffset)
Brian Paulddc82ee2005-02-05 19:56:45 +00002035{
Brian Paul2c6f9112005-02-24 05:47:06 +00002036 struct gl_renderbuffer_attachment *att;
Brian Paulea4fe662006-03-26 05:22:17 +00002037 struct gl_texture_object *texObj = NULL;
2038 struct gl_framebuffer *fb;
Anuj Phogatcc5b0ff2012-03-12 10:39:48 -07002039 GLenum maxLevelsTarget;
Brian Paulddc82ee2005-02-05 19:56:45 +00002040
Brian Paulc6991432011-02-28 18:24:25 -07002041 fb = get_framebuffer_target(ctx, target);
2042 if (!fb) {
Brian Paulea4fe662006-03-26 05:22:17 +00002043 _mesa_error(ctx, GL_INVALID_ENUM,
Brian Paul5fec84a2009-01-29 15:01:09 -07002044 "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
Brian Paulddc82ee2005-02-05 19:56:45 +00002045 return;
Brian Paulea4fe662006-03-26 05:22:17 +00002046 }
Brian Paulddc82ee2005-02-05 19:56:45 +00002047
Brian Paulea4fe662006-03-26 05:22:17 +00002048 /* check framebuffer binding */
Brian Paul36ede892012-01-12 09:17:23 -07002049 if (_mesa_is_winsys_fbo(fb)) {
Brian Paulea4fe662006-03-26 05:22:17 +00002050 _mesa_error(ctx, GL_INVALID_OPERATION,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002051 "glFramebufferTexture%sEXT", caller);
Brian Paulea4fe662006-03-26 05:22:17 +00002052 return;
2053 }
2054
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002055 /* The textarget, level, and zoffset parameters are only validated if
2056 * texture is non-zero.
2057 */
2058 if (texture) {
2059 GLboolean err = GL_TRUE;
2060
2061 texObj = _mesa_lookup_texture(ctx, texture);
2062 if (texObj != NULL) {
Ian Romanickbb372f12007-05-16 15:34:22 -07002063 if (textarget == 0) {
Brian Paul534cbbe2012-03-12 11:03:59 -06002064 /* If textarget == 0 it means we're being called by
2065 * glFramebufferTextureLayer() and textarget is not used.
2066 * The only legal texture types for that function are 3D and
2067 * 1D/2D arrays textures.
2068 */
Ian Romanickbb372f12007-05-16 15:34:22 -07002069 err = (texObj->Target != GL_TEXTURE_3D) &&
2070 (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
Dave Airliee0e7e292012-11-03 20:41:08 +10002071 (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) &&
2072 (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY);
Ian Romanickbb372f12007-05-16 15:34:22 -07002073 }
2074 else {
Brian Paul534cbbe2012-03-12 11:03:59 -06002075 /* Make sure textarget is consistent with the texture's type */
Ian Romanickbb372f12007-05-16 15:34:22 -07002076 err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
Brian Paul2efa3d42011-11-18 17:39:00 -07002077 ? !_mesa_is_cube_face(textarget)
Ian Romanickbb372f12007-05-16 15:34:22 -07002078 : (texObj->Target != textarget);
2079 }
Brian Paulea4fe662006-03-26 05:22:17 +00002080 }
Brian Paul7a2e32d2010-03-10 10:54:24 -07002081 else {
2082 /* can't render to a non-existant texture */
2083 _mesa_error(ctx, GL_INVALID_OPERATION,
2084 "glFramebufferTexture%sEXT(non existant texture)",
2085 caller);
2086 return;
2087 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002088
2089 if (err) {
Brian Paulea4fe662006-03-26 05:22:17 +00002090 _mesa_error(ctx, GL_INVALID_OPERATION,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002091 "glFramebufferTexture%sEXT(texture target mismatch)",
2092 caller);
Brian Paulea4fe662006-03-26 05:22:17 +00002093 return;
2094 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002095
2096 if (texObj->Target == GL_TEXTURE_3D) {
Brian Paulea4fe662006-03-26 05:22:17 +00002097 const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
2098 if (zoffset < 0 || zoffset >= maxSize) {
2099 _mesa_error(ctx, GL_INVALID_VALUE,
Ian Romanickbb372f12007-05-16 15:34:22 -07002100 "glFramebufferTexture%sEXT(zoffset)", caller);
Brian Paulea4fe662006-03-26 05:22:17 +00002101 return;
2102 }
2103 }
Ian Romanickbb372f12007-05-16 15:34:22 -07002104 else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
Dave Airliee0e7e292012-11-03 20:41:08 +10002105 (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) ||
2106 (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY)) {
Brian Paul859c3872012-11-04 16:43:44 -07002107 if (zoffset < 0 ||
2108 zoffset >= (GLint) ctx->Const.MaxArrayTextureLayers) {
Ian Romanickbb372f12007-05-16 15:34:22 -07002109 _mesa_error(ctx, GL_INVALID_VALUE,
2110 "glFramebufferTexture%sEXT(layer)", caller);
2111 return;
2112 }
2113 }
2114
Anuj Phogatcc5b0ff2012-03-12 10:39:48 -07002115 maxLevelsTarget = textarget ? textarget : texObj->Target;
Brian Paul45bd5c42011-12-16 08:44:43 -07002116 if ((level < 0) ||
Anuj Phogatcc5b0ff2012-03-12 10:39:48 -07002117 (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002118 _mesa_error(ctx, GL_INVALID_VALUE,
2119 "glFramebufferTexture%sEXT(level)", caller);
2120 return;
2121 }
Brian Paulea4fe662006-03-26 05:22:17 +00002122 }
2123
2124 att = _mesa_get_attachment(ctx, fb, attachment);
Brian Paul3deaa012005-02-07 05:08:24 +00002125 if (att == NULL) {
2126 _mesa_error(ctx, GL_INVALID_ENUM,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002127 "glFramebufferTexture%sEXT(attachment)", caller);
Brian Paul3deaa012005-02-07 05:08:24 +00002128 return;
2129 }
2130
Brian Paul800e5532009-11-02 15:39:39 -07002131 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paul474f28e2005-10-08 14:41:17 +00002132
Brian Paulea4fe662006-03-26 05:22:17 +00002133 _glthread_LOCK_MUTEX(fb->Mutex);
2134 if (texObj) {
Chad Versacebf8ad172011-11-10 10:19:20 -08002135 if (attachment == GL_DEPTH_ATTACHMENT &&
Paul Berryb9819a02012-04-13 21:50:08 -07002136 texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
2137 level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
2138 _mesa_tex_target_to_face(textarget) ==
2139 fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
2140 zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
Chad Versacebf8ad172011-11-10 10:19:20 -08002141 /* The texture object is already attached to the stencil attachment
2142 * point. Don't create a new renderbuffer; just reuse the stencil
2143 * attachment's. This is required to prevent a GL error in
2144 * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
2145 */
2146 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
2147 BUFFER_STENCIL);
2148 } else if (attachment == GL_STENCIL_ATTACHMENT &&
Paul Berryb9819a02012-04-13 21:50:08 -07002149 texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
2150 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
2151 _mesa_tex_target_to_face(textarget) ==
2152 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
2153 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
2154 /* As above, but with depth and stencil transposed. */
Chad Versacebf8ad172011-11-10 10:19:20 -08002155 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
2156 BUFFER_DEPTH);
2157 } else {
2158 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
2159 level, zoffset);
2160 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2161 /* Above we created a new renderbuffer and attached it to the
2162 * depth attachment point. Now attach it to the stencil attachment
2163 * point too.
2164 */
2165 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2166 reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
2167 BUFFER_DEPTH);
2168 }
2169 }
2170
Brian Paul2897cee2009-01-29 09:20:18 -07002171 /* Set the render-to-texture flag. We'll check this flag in
2172 * glTexImage() and friends to determine if we need to revalidate
2173 * any FBOs that might be rendering into this texture.
2174 * This flag never gets cleared since it's non-trivial to determine
2175 * when all FBOs might be done rendering to this texture. That's OK
2176 * though since it's uncommon to render to a texture then repeatedly
2177 * call glTexImage() to change images in the texture.
2178 */
2179 texObj->_RenderToTexture = GL_TRUE;
Brian Paul3deaa012005-02-07 05:08:24 +00002180 }
2181 else {
Brian Paul519b23b2006-03-20 18:51:57 +00002182 _mesa_remove_attachment(ctx, att);
Chad Versacebf8ad172011-11-10 10:19:20 -08002183 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2184 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2185 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
2186 }
Brian Paul3deaa012005-02-07 05:08:24 +00002187 }
Brian Paul72966362009-01-21 16:28:38 -07002188
2189 invalidate_framebuffer(fb);
2190
Brian Paulea4fe662006-03-26 05:22:17 +00002191 _glthread_UNLOCK_MUTEX(fb->Mutex);
2192}
2193
2194
2195
2196void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002197_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
Brian Paulea4fe662006-03-26 05:22:17 +00002198 GLenum textarget, GLuint texture, GLint level)
2199{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002200 GET_CURRENT_CONTEXT(ctx);
2201
Brian Paul352cab42011-08-18 14:35:27 -06002202 if (texture != 0) {
2203 GLboolean error;
2204
2205 switch (textarget) {
2206 case GL_TEXTURE_1D:
2207 error = GL_FALSE;
2208 break;
Brian Paul3e9dc512011-08-18 15:59:33 -06002209 case GL_TEXTURE_1D_ARRAY:
2210 error = !ctx->Extensions.EXT_texture_array;
2211 break;
Brian Paul352cab42011-08-18 14:35:27 -06002212 default:
2213 error = GL_TRUE;
2214 }
2215
2216 if (error) {
2217 _mesa_error(ctx, GL_INVALID_OPERATION,
2218 "glFramebufferTexture1DEXT(textarget=%s)",
2219 _mesa_lookup_enum_by_nr(textarget));
2220 return;
2221 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002222 }
2223
2224 framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
2225 level, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00002226}
2227
2228
Brian Paul1864c7d2005-02-08 03:46:37 +00002229void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002230_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002231 GLenum textarget, GLuint texture, GLint level)
2232{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002233 GET_CURRENT_CONTEXT(ctx);
2234
Brian Paul352cab42011-08-18 14:35:27 -06002235 if (texture != 0) {
2236 GLboolean error;
2237
2238 switch (textarget) {
2239 case GL_TEXTURE_2D:
2240 error = GL_FALSE;
2241 break;
2242 case GL_TEXTURE_RECTANGLE:
Ian Romanick7f991d22012-07-27 07:22:41 -07002243 error = _mesa_is_gles(ctx)
2244 || !ctx->Extensions.NV_texture_rectangle;
Brian Paul352cab42011-08-18 14:35:27 -06002245 break;
2246 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2247 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2248 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2249 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2250 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2251 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2252 error = !ctx->Extensions.ARB_texture_cube_map;
2253 break;
Brian Paul3e9dc512011-08-18 15:59:33 -06002254 case GL_TEXTURE_2D_ARRAY:
Ian Romanick7f991d22012-07-27 07:22:41 -07002255 error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2256 || !ctx->Extensions.EXT_texture_array;
Brian Paul3e9dc512011-08-18 15:59:33 -06002257 break;
Brian Paul352cab42011-08-18 14:35:27 -06002258 default:
Chia-I Wud8ba30a2011-10-22 22:17:31 +08002259 error = GL_TRUE;
Brian Paul352cab42011-08-18 14:35:27 -06002260 }
2261
2262 if (error) {
2263 _mesa_error(ctx, GL_INVALID_OPERATION,
2264 "glFramebufferTexture2DEXT(textarget=%s)",
2265 _mesa_lookup_enum_by_nr(textarget));
2266 return;
2267 }
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002268 }
2269
2270 framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
2271 level, 0);
Brian Paulddc82ee2005-02-05 19:56:45 +00002272}
2273
2274
Brian Paul1864c7d2005-02-08 03:46:37 +00002275void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002276_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002277 GLenum textarget, GLuint texture,
2278 GLint level, GLint zoffset)
2279{
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002280 GET_CURRENT_CONTEXT(ctx);
2281
2282 if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
Brian Paulccecc082011-08-18 11:51:48 -06002283 _mesa_error(ctx, GL_INVALID_OPERATION,
Ian Romanickb0fe0d82007-05-15 13:42:25 -07002284 "glFramebufferTexture3DEXT(textarget)");
2285 return;
2286 }
2287
2288 framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
Brian Paulea4fe662006-03-26 05:22:17 +00002289 level, zoffset);
Brian Paulddc82ee2005-02-05 19:56:45 +00002290}
2291
2292
Brian Paul1864c7d2005-02-08 03:46:37 +00002293void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002294_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
Ian Romanickbb372f12007-05-16 15:34:22 -07002295 GLuint texture, GLint level, GLint layer)
2296{
2297 GET_CURRENT_CONTEXT(ctx);
2298
2299 framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2300 level, layer);
2301}
2302
2303
2304void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002305_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002306 GLenum renderbufferTarget,
2307 GLuint renderbuffer)
2308{
Brian Paul2c6f9112005-02-24 05:47:06 +00002309 struct gl_renderbuffer_attachment *att;
Brian Paul0bffb112005-11-08 14:45:48 +00002310 struct gl_framebuffer *fb;
Brian Paule4b23562005-05-04 20:11:35 +00002311 struct gl_renderbuffer *rb;
Brian Paulddc82ee2005-02-05 19:56:45 +00002312 GET_CURRENT_CONTEXT(ctx);
2313
Brian Paulc6991432011-02-28 18:24:25 -07002314 fb = get_framebuffer_target(ctx, target);
2315 if (!fb) {
2316 _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
Brian Paulddc82ee2005-02-05 19:56:45 +00002317 return;
2318 }
2319
Brian Paul3deaa012005-02-07 05:08:24 +00002320 if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
Brian Paule4b23562005-05-04 20:11:35 +00002321 _mesa_error(ctx, GL_INVALID_ENUM,
2322 "glFramebufferRenderbufferEXT(renderbufferTarget)");
Brian Paul3deaa012005-02-07 05:08:24 +00002323 return;
2324 }
2325
Brian Paul36ede892012-01-12 09:17:23 -07002326 if (_mesa_is_winsys_fbo(fb)) {
Brian Paulab8ef282005-09-07 23:21:59 +00002327 /* Can't attach new renderbuffers to a window system framebuffer */
Brian Paul3deaa012005-02-07 05:08:24 +00002328 _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
2329 return;
2330 }
2331
Brian Paul84716042005-11-16 04:05:54 +00002332 att = _mesa_get_attachment(ctx, fb, attachment);
Brian Paul3deaa012005-02-07 05:08:24 +00002333 if (att == NULL) {
Brian Paulddc82ee2005-02-05 19:56:45 +00002334 _mesa_error(ctx, GL_INVALID_ENUM,
Brian Paul9b50cea2009-10-23 11:34:14 -06002335 "glFramebufferRenderbufferEXT(invalid attachment %s)",
2336 _mesa_lookup_enum_by_nr(attachment));
Brian Paulddc82ee2005-02-05 19:56:45 +00002337 return;
2338 }
2339
Brian Paul1864c7d2005-02-08 03:46:37 +00002340 if (renderbuffer) {
Brian Paulea4fe662006-03-26 05:22:17 +00002341 rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00002342 if (!rb) {
Brian Paule4b23562005-05-04 20:11:35 +00002343 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paul9b50cea2009-10-23 11:34:14 -06002344 "glFramebufferRenderbufferEXT(non-existant"
2345 " renderbuffer %u)", renderbuffer);
Brian Paul1864c7d2005-02-08 03:46:37 +00002346 return;
2347 }
Brian Pauldd973cd2011-01-12 18:14:14 -07002348 else if (rb == &DummyRenderbuffer) {
2349 /* This is what NVIDIA does */
2350 _mesa_error(ctx, GL_INVALID_VALUE,
2351 "glFramebufferRenderbufferEXT(renderbuffer %u)",
2352 renderbuffer);
2353 return;
2354 }
Brian Paul1864c7d2005-02-08 03:46:37 +00002355 }
2356 else {
Brian Paule4b23562005-05-04 20:11:35 +00002357 /* remove renderbuffer attachment */
2358 rb = NULL;
Brian Paul1864c7d2005-02-08 03:46:37 +00002359 }
Brian Paule4b23562005-05-04 20:11:35 +00002360
Brian Paula504f232010-05-27 13:05:23 -06002361 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2362 rb && rb->Format != MESA_FORMAT_NONE) {
Brian Paul30590072009-01-21 11:06:11 -07002363 /* make sure the renderbuffer is a depth/stencil format */
Brian Paula504f232010-05-27 13:05:23 -06002364 const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
Brian Paul45e76d22009-10-08 20:27:27 -06002365 if (baseFormat != GL_DEPTH_STENCIL) {
Brian Paul30590072009-01-21 11:06:11 -07002366 _mesa_error(ctx, GL_INVALID_OPERATION,
2367 "glFramebufferRenderbufferEXT(renderbuffer"
2368 " is not DEPTH_STENCIL format)");
2369 return;
2370 }
2371 }
2372
2373
Brian Paul800e5532009-11-02 15:39:39 -07002374 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paul474f28e2005-10-08 14:41:17 +00002375
Brian Paule4b23562005-05-04 20:11:35 +00002376 assert(ctx->Driver.FramebufferRenderbuffer);
Brian Paul84716042005-11-16 04:05:54 +00002377 ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
Brian Paul2e019182006-03-07 01:43:52 +00002378
2379 /* Some subsequent GL commands may depend on the framebuffer's visual
2380 * after the binding is updated. Update visual info now.
2381 */
Eric Anholt059cca92011-01-02 17:58:07 -08002382 _mesa_update_framebuffer_visual(ctx, fb);
Brian Paulddc82ee2005-02-05 19:56:45 +00002383}
2384
2385
Brian Paul1864c7d2005-02-08 03:46:37 +00002386void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002387_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
Brian Paulddc82ee2005-02-05 19:56:45 +00002388 GLenum pname, GLint *params)
2389{
Brian Paul2c6f9112005-02-24 05:47:06 +00002390 const struct gl_renderbuffer_attachment *att;
Brian Paul0bffb112005-11-08 14:45:48 +00002391 struct gl_framebuffer *buffer;
Marek Olšák000896c2011-07-19 03:05:07 +02002392 GLenum err;
Brian Paulddc82ee2005-02-05 19:56:45 +00002393 GET_CURRENT_CONTEXT(ctx);
2394
Brian Pauldbe88512012-02-10 16:22:33 -07002395 /* The error differs in GL and GLES. */
Jordan Justen09714c02012-07-19 11:27:16 -07002396 err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
Marek Olšák000896c2011-07-19 03:05:07 +02002397
Brian Paulc6991432011-02-28 18:24:25 -07002398 buffer = get_framebuffer_target(ctx, target);
2399 if (!buffer) {
Brian Paulddc82ee2005-02-05 19:56:45 +00002400 _mesa_error(ctx, GL_INVALID_ENUM,
2401 "glGetFramebufferAttachmentParameterivEXT(target)");
2402 return;
2403 }
2404
Brian Paul36ede892012-01-12 09:17:23 -07002405 if (_mesa_is_winsys_fbo(buffer)) {
Ian Romanickda2e41c2011-10-03 12:04:09 -07002406 /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
2407 * says:
2408 *
2409 * "If the framebuffer currently bound to target is zero, then
2410 * INVALID_OPERATION is generated."
2411 *
2412 * The EXT_framebuffer_object spec has the same wording, and the
2413 * OES_framebuffer_object spec refers to the EXT_framebuffer_object
2414 * spec.
2415 */
Anuj Phogat2f2801f2012-12-11 20:08:13 -08002416 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2417 && !_mesa_is_gles3(ctx)) {
Ian Romanickda2e41c2011-10-03 12:04:09 -07002418 _mesa_error(ctx, GL_INVALID_OPERATION,
2419 "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
2420 return;
2421 }
Anuj Phogat2f2801f2012-12-11 20:08:13 -08002422
2423 if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
2424 attachment != GL_DEPTH && attachment != GL_STENCIL) {
2425 _mesa_error(ctx, GL_INVALID_OPERATION,
2426 "glGetFramebufferAttachmentParameteriv(attachment)");
2427 return;
2428 }
Brian Paul61ec2052010-06-22 08:37:44 -06002429 /* the default / window-system FBO */
2430 att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
2431 }
2432 else {
2433 /* user-created framebuffer FBO */
2434 att = _mesa_get_attachment(ctx, buffer, attachment);
2435 }
2436
Brian Paul3deaa012005-02-07 05:08:24 +00002437 if (att == NULL) {
Brian Paulddc82ee2005-02-05 19:56:45 +00002438 _mesa_error(ctx, GL_INVALID_ENUM,
2439 "glGetFramebufferAttachmentParameterivEXT(attachment)");
2440 return;
2441 }
2442
Brian Paul30590072009-01-21 11:06:11 -07002443 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2444 /* the depth and stencil attachments must point to the same buffer */
2445 const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
2446 depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
2447 stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
2448 if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
2449 _mesa_error(ctx, GL_INVALID_OPERATION,
2450 "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
2451 " attachments differ)");
2452 return;
2453 }
2454 }
2455
Brian Paul800e5532009-11-02 15:39:39 -07002456 /* No need to flush here */
Brian Paul474f28e2005-10-08 14:41:17 +00002457
Brian Paulddc82ee2005-02-05 19:56:45 +00002458 switch (pname) {
2459 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
Brian Paul36ede892012-01-12 09:17:23 -07002460 *params = _mesa_is_winsys_fbo(buffer)
2461 ? GL_FRAMEBUFFER_DEFAULT : att->Type;
Brian Paul3deaa012005-02-07 05:08:24 +00002462 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002463 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00002464 if (att->Type == GL_RENDERBUFFER_EXT) {
2465 *params = att->Renderbuffer->Name;
2466 }
2467 else if (att->Type == GL_TEXTURE) {
2468 *params = att->Texture->Name;
2469 }
2470 else {
Brian Paul20cf1852010-12-03 08:23:31 -07002471 assert(att->Type == GL_NONE);
Ian Romanick0cdaa472012-07-27 07:47:28 -07002472 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
Marek Olšák000896c2011-07-19 03:05:07 +02002473 *params = 0;
2474 } else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002475 goto invalid_pname_enum;
Marek Olšák000896c2011-07-19 03:05:07 +02002476 }
Brian Paul3deaa012005-02-07 05:08:24 +00002477 }
2478 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002479 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00002480 if (att->Type == GL_TEXTURE) {
2481 *params = att->TextureLevel;
2482 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002483 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002484 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002485 "glGetFramebufferAttachmentParameterivEXT(pname)");
2486 }
Brian Paul3deaa012005-02-07 05:08:24 +00002487 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002488 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00002489 }
2490 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002491 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
Brian Paul3deaa012005-02-07 05:08:24 +00002492 if (att->Type == GL_TEXTURE) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06002493 if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
2494 *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
2495 }
2496 else {
2497 *params = 0;
2498 }
Brian Paul3deaa012005-02-07 05:08:24 +00002499 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002500 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002501 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002502 "glGetFramebufferAttachmentParameterivEXT(pname)");
2503 }
Brian Paul3deaa012005-02-07 05:08:24 +00002504 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002505 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00002506 }
2507 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002508 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002509 if (ctx->API == API_OPENGLES) {
2510 goto invalid_pname_enum;
2511 } else if (att->Type == GL_NONE) {
2512 _mesa_error(ctx, err,
2513 "glGetFramebufferAttachmentParameterivEXT(pname)");
2514 } else if (att->Type == GL_TEXTURE) {
Brian Paulf1e4ca72008-08-06 08:39:54 -06002515 if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
2516 *params = att->Zoffset;
2517 }
2518 else {
2519 *params = 0;
2520 }
Brian Paul3deaa012005-02-07 05:08:24 +00002521 }
2522 else {
Ian Romanick0cdaa472012-07-27 07:47:28 -07002523 goto invalid_pname_enum;
Brian Paul3deaa012005-02-07 05:08:24 +00002524 }
2525 return;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002526 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002527 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2528 && !_mesa_is_gles3(ctx)) {
2529 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002530 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002531 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002532 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002533 "glGetFramebufferAttachmentParameterivEXT(pname)");
2534 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002535 else {
Marek Olšák69c8f462012-01-24 23:39:31 +01002536 if (ctx->Extensions.EXT_framebuffer_sRGB) {
Marek Olšák81ae8c62011-01-23 13:26:43 +01002537 *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
2538 }
2539 else {
2540 /* According to ARB_framebuffer_sRGB, we should return LINEAR
2541 * if the sRGB conversion is unsupported. */
2542 *params = GL_LINEAR;
2543 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002544 }
2545 return;
2546 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Paul Berrydbd61352012-11-27 12:26:51 -08002547 if ((ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_framebuffer_object)
Ian Romanick0cdaa472012-07-27 07:47:28 -07002548 && ctx->API != API_OPENGL_CORE
2549 && !_mesa_is_gles3(ctx)) {
2550 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002551 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002552 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002553 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002554 "glGetFramebufferAttachmentParameterivEXT(pname)");
2555 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002556 else {
Brian Paul45e76d22009-10-08 20:27:27 -06002557 gl_format format = att->Renderbuffer->Format;
Ian Romanickd7475c72013-01-18 17:25:57 -08002558
2559 /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
2560 * 3.0.1 spec says:
2561 *
2562 * "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
2563 * attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
2564 * generate an INVALID_OPERATION error.
2565 */
2566 if (_mesa_is_gles3(ctx) && attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2567 _mesa_error(ctx, GL_INVALID_OPERATION,
2568 "glGetFramebufferAttachmentParameteriv(cannot query "
2569 "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
2570 "GL_DEPTH_STENCIL_ATTACHMENT");
2571 return;
2572 }
2573
Ian Romanick55d232a2011-08-26 12:20:00 -07002574 if (format == MESA_FORMAT_S8) {
Brian Paul45e76d22009-10-08 20:27:27 -06002575 /* special cases */
2576 *params = GL_INDEX;
2577 }
Marek Olšák11652802011-06-01 15:48:51 +02002578 else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) {
2579 /* depends on the attachment parameter */
2580 if (attachment == GL_STENCIL_ATTACHMENT) {
2581 *params = GL_INDEX;
2582 }
2583 else {
2584 *params = GL_FLOAT;
2585 }
2586 }
Brian Paul45e76d22009-10-08 20:27:27 -06002587 else {
2588 *params = _mesa_get_format_datatype(format);
2589 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002590 }
2591 return;
2592 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002593 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002594 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002595 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002596 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Brian Paul1bc59bf2009-01-22 15:07:34 -07002597 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002598 if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2599 && !_mesa_is_gles3(ctx)) {
2600 goto invalid_pname_enum;
Brian Paul1bc59bf2009-01-22 15:07:34 -07002601 }
Marek Olšákb9e9df72011-05-31 20:36:07 +02002602 else if (att->Type == GL_NONE) {
Marek Olšák000896c2011-07-19 03:05:07 +02002603 _mesa_error(ctx, err,
Marek Olšákb9e9df72011-05-31 20:36:07 +02002604 "glGetFramebufferAttachmentParameterivEXT(pname)");
2605 }
Brian Paul45e76d22009-10-08 20:27:27 -06002606 else if (att->Texture) {
2607 const struct gl_texture_image *texImage =
2608 _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
2609 att->TextureLevel);
2610 if (texImage) {
2611 *params = get_component_bits(pname, texImage->_BaseFormat,
2612 texImage->TexFormat);
2613 }
2614 else {
2615 *params = 0;
2616 }
2617 }
2618 else if (att->Renderbuffer) {
2619 *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
2620 att->Renderbuffer->Format);
2621 }
Brian Paul1bc59bf2009-01-22 15:07:34 -07002622 else {
Marek Olšákb9e9df72011-05-31 20:36:07 +02002623 _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
2624 " invalid FBO attachment structure");
Brian Paul1bc59bf2009-01-22 15:07:34 -07002625 }
2626 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002627 default:
Ian Romanick0cdaa472012-07-27 07:47:28 -07002628 goto invalid_pname_enum;
Brian Paulddc82ee2005-02-05 19:56:45 +00002629 }
Ian Romanick0cdaa472012-07-27 07:47:28 -07002630
2631 return;
2632
2633invalid_pname_enum:
2634 _mesa_error(ctx, GL_INVALID_ENUM,
2635 "glGetFramebufferAttachmentParameteriv(pname)");
2636 return;
Brian Paulddc82ee2005-02-05 19:56:45 +00002637}
2638
2639
Brian Paul1864c7d2005-02-08 03:46:37 +00002640void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002641_mesa_GenerateMipmap(GLenum target)
Brian Paulddc82ee2005-02-05 19:56:45 +00002642{
Eric Anholtf80e1e72011-10-18 11:52:39 -07002643 struct gl_texture_image *srcImage;
Brian Paul463642c2005-02-08 02:06:00 +00002644 struct gl_texture_object *texObj;
Brian Paul3e9dc512011-08-18 15:59:33 -06002645 GLboolean error;
2646
Brian Paulddc82ee2005-02-05 19:56:45 +00002647 GET_CURRENT_CONTEXT(ctx);
2648
Brian Paul474f28e2005-10-08 14:41:17 +00002649 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
Brian Paulddc82ee2005-02-05 19:56:45 +00002650
2651 switch (target) {
2652 case GL_TEXTURE_1D:
Ian Romanick5b44a772012-07-27 07:24:37 -07002653 error = _mesa_is_gles(ctx);
2654 break;
Brian Paulddc82ee2005-02-05 19:56:45 +00002655 case GL_TEXTURE_2D:
Brian Paul3e9dc512011-08-18 15:59:33 -06002656 error = GL_FALSE;
2657 break;
Ian Romanick5b44a772012-07-27 07:24:37 -07002658 case GL_TEXTURE_3D:
2659 error = ctx->API == API_OPENGLES;
2660 break;
Brian Paul463642c2005-02-08 02:06:00 +00002661 case GL_TEXTURE_CUBE_MAP:
Brian Paul3e9dc512011-08-18 15:59:33 -06002662 error = !ctx->Extensions.ARB_texture_cube_map;
2663 break;
2664 case GL_TEXTURE_1D_ARRAY:
Ian Romanick5b44a772012-07-27 07:24:37 -07002665 error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array;
2666 break;
Brian Paul3e9dc512011-08-18 15:59:33 -06002667 case GL_TEXTURE_2D_ARRAY:
Ian Romanick5b44a772012-07-27 07:24:37 -07002668 error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2669 || !ctx->Extensions.EXT_texture_array;
Brian Paulddc82ee2005-02-05 19:56:45 +00002670 break;
2671 default:
Brian Paul3e9dc512011-08-18 15:59:33 -06002672 error = GL_TRUE;
2673 }
2674
2675 if (error) {
2676 _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)",
2677 _mesa_lookup_enum_by_nr(target));
Brian Paulddc82ee2005-02-05 19:56:45 +00002678 return;
2679 }
2680
Brian Paula7193952009-11-16 08:21:28 -07002681 texObj = _mesa_get_current_tex_object(ctx, target);
Brian Paul463642c2005-02-08 02:06:00 +00002682
Brian Paul652828e2009-11-16 08:25:17 -07002683 if (texObj->BaseLevel >= texObj->MaxLevel) {
2684 /* nothing to do */
2685 return;
2686 }
2687
Brian Paulecb7cc32010-12-06 15:11:41 -07002688 if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
2689 !_mesa_cube_complete(texObj)) {
2690 _mesa_error(ctx, GL_INVALID_OPERATION,
2691 "glGenerateMipmap(incomplete cube map)");
2692 return;
2693 }
2694
Keith Whitwell5ac93f82006-11-01 14:21:57 +00002695 _mesa_lock_texture(ctx, texObj);
Eric Anholtf80e1e72011-10-18 11:52:39 -07002696
2697 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
2698 if (!srcImage) {
2699 _mesa_unlock_texture(ctx, texObj);
Brian Paulf6b71572012-08-10 10:36:17 -06002700 _mesa_error(ctx, GL_INVALID_OPERATION,
2701 "glGenerateMipmap(zero size base image)");
Eric Anholtf80e1e72011-10-18 11:52:39 -07002702 return;
2703 }
2704
Anuj Phogatc0a78d72012-11-02 10:47:33 -07002705 if (_mesa_is_enum_format_integer(srcImage->InternalFormat) ||
2706 _mesa_is_depthstencil_format(srcImage->InternalFormat) ||
2707 _mesa_is_stencil_format(srcImage->InternalFormat)) {
2708 _mesa_unlock_texture(ctx, texObj);
2709 _mesa_error(ctx, GL_INVALID_OPERATION,
2710 "glGenerateMipmap(invalid internal format)");
2711 return;
2712 }
2713
Eric Anholtf849d362008-12-06 21:14:56 -08002714 if (target == GL_TEXTURE_CUBE_MAP) {
Brian Paulef6ee072009-09-15 18:09:03 -06002715 GLuint face;
Eric Anholtf849d362008-12-06 21:14:56 -08002716 for (face = 0; face < 6; face++)
2717 ctx->Driver.GenerateMipmap(ctx,
2718 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
2719 texObj);
Brian Paulef6ee072009-09-15 18:09:03 -06002720 }
2721 else {
Eric Anholtf849d362008-12-06 21:14:56 -08002722 ctx->Driver.GenerateMipmap(ctx, target, texObj);
2723 }
Keith Whitwell5ac93f82006-11-01 14:21:57 +00002724 _mesa_unlock_texture(ctx, texObj);
Brian Paulddc82ee2005-02-05 19:56:45 +00002725}
Brian Paul0bffb112005-11-08 14:45:48 +00002726
2727
Brian Paul21f8d312009-10-27 16:59:23 -06002728static const struct gl_renderbuffer_attachment *
Brian Paulb3cfcdf2011-01-28 20:25:26 -07002729find_attachment(const struct gl_framebuffer *fb,
2730 const struct gl_renderbuffer *rb)
Brian Paul21f8d312009-10-27 16:59:23 -06002731{
2732 GLuint i;
2733 for (i = 0; i < Elements(fb->Attachment); i++) {
2734 if (fb->Attachment[i].Renderbuffer == rb)
2735 return &fb->Attachment[i];
2736 }
2737 return NULL;
2738}
2739
2740
Brian Paul9b111702012-01-09 12:38:49 -07002741/**
2742 * Helper function for checking if the datatypes of color buffers are
2743 * compatible for glBlitFramebuffer. From the 3.1 spec, page 198:
2744 *
2745 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
2746 * and any of the following conditions hold:
2747 * - The read buffer contains fixed-point or floating-point values and any
2748 * draw buffer contains neither fixed-point nor floating-point values.
2749 * - The read buffer contains unsigned integer values and any draw buffer
2750 * does not contain unsigned integer values.
2751 * - The read buffer contains signed integer values and any draw buffer
2752 * does not contain signed integer values."
2753 */
2754static GLboolean
2755compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat)
2756{
2757 GLenum srcType = _mesa_get_format_datatype(srcFormat);
2758 GLenum dstType = _mesa_get_format_datatype(dstFormat);
2759
2760 if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
2761 assert(srcType == GL_UNSIGNED_NORMALIZED ||
2762 srcType == GL_SIGNED_NORMALIZED ||
2763 srcType == GL_FLOAT);
2764 /* Boil any of those types down to GL_FLOAT */
2765 srcType = GL_FLOAT;
2766 }
2767
2768 if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
2769 assert(dstType == GL_UNSIGNED_NORMALIZED ||
2770 dstType == GL_SIGNED_NORMALIZED ||
2771 dstType == GL_FLOAT);
2772 /* Boil any of those types down to GL_FLOAT */
2773 dstType = GL_FLOAT;
2774 }
2775
2776 return srcType == dstType;
2777}
2778
Brian Paul21f8d312009-10-27 16:59:23 -06002779
Marek Olšák59272272012-07-21 15:16:15 +02002780static GLboolean
Marek Olšák135fe902012-11-28 19:07:18 +01002781compatible_resolve_formats(const struct gl_renderbuffer *readRb,
2782 const struct gl_renderbuffer *drawRb)
Marek Olšák59272272012-07-21 15:16:15 +02002783{
Marek Olšák91ca0532012-11-23 03:02:44 +01002784 GLenum readFormat, drawFormat;
2785
2786 /* The simple case where we know the backing Mesa formats are the same.
Marek Olšák59272272012-07-21 15:16:15 +02002787 */
Marek Olšák135fe902012-11-28 19:07:18 +01002788 if (_mesa_get_srgb_format_linear(readRb->Format) ==
2789 _mesa_get_srgb_format_linear(drawRb->Format)) {
Marek Olšák59272272012-07-21 15:16:15 +02002790 return GL_TRUE;
2791 }
2792
2793 /* The Mesa formats are different, so we must check whether the internal
2794 * formats are compatible.
2795 *
2796 * Under some circumstances, the user may request e.g. two GL_RGBA8
2797 * textures and get two entirely different Mesa formats like RGBA8888 and
2798 * ARGB8888. Drivers behaving like that should be able to cope with
2799 * non-matching formats by themselves, because it's not the user's fault.
Marek Olšák91ca0532012-11-23 03:02:44 +01002800 *
2801 * Blits between linear and sRGB formats are also allowed.
Marek Olšák59272272012-07-21 15:16:15 +02002802 */
Marek Olšák135fe902012-11-28 19:07:18 +01002803 readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
2804 drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
2805 readFormat = _mesa_get_linear_internalformat(readFormat);
2806 drawFormat = _mesa_get_linear_internalformat(drawFormat);
Marek Olšák91ca0532012-11-23 03:02:44 +01002807
2808 if (readFormat == drawFormat) {
Marek Olšák59272272012-07-21 15:16:15 +02002809 return GL_TRUE;
2810 }
2811
2812 return GL_FALSE;
2813}
2814
2815
2816/**
Brian Paul722d9762009-01-20 16:58:49 -07002817 * Blit rectangular region, optionally from one framebuffer to another.
2818 *
2819 * Note, if the src buffer is multisampled and the dest is not, this is
2820 * when the samples must be resolved to a single color.
2821 */
Brian Paul0bffb112005-11-08 14:45:48 +00002822void GLAPIENTRY
Paul Berry1a1db172012-11-06 08:57:59 -08002823_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Brian Paul0bffb112005-11-08 14:45:48 +00002824 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
2825 GLbitfield mask, GLenum filter)
2826{
Brian Paul722d9762009-01-20 16:58:49 -07002827 const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
2828 GL_DEPTH_BUFFER_BIT |
2829 GL_STENCIL_BUFFER_BIT);
2830 const struct gl_framebuffer *readFb, *drawFb;
Brian Paul0bffb112005-11-08 14:45:48 +00002831 GET_CURRENT_CONTEXT(ctx);
2832
Brian Paul0bffb112005-11-08 14:45:48 +00002833 FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2834
Brian Paul6364d752011-02-18 09:53:29 -07002835 if (MESA_VERBOSE & VERBOSE_API)
2836 _mesa_debug(ctx,
2837 "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n",
2838 srcX0, srcY0, srcX1, srcY1,
2839 dstX0, dstY0, dstX1, dstY1,
2840 mask, _mesa_lookup_enum_by_nr(filter));
2841
Brian Paul99745402006-03-01 02:02:43 +00002842 if (ctx->NewState) {
2843 _mesa_update_state(ctx);
2844 }
2845
Brian Paul722d9762009-01-20 16:58:49 -07002846 readFb = ctx->ReadBuffer;
2847 drawFb = ctx->DrawBuffer;
2848
2849 if (!readFb || !drawFb) {
2850 /* This will normally never happen but someday we may want to
2851 * support MakeCurrent() with no drawables.
2852 */
2853 return;
Brian Paul99745402006-03-01 02:02:43 +00002854 }
2855
Brian Paul0bffb112005-11-08 14:45:48 +00002856 /* check for complete framebuffers */
Brian Paul722d9762009-01-20 16:58:49 -07002857 if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
2858 readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
Brian Paul0bffb112005-11-08 14:45:48 +00002859 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
2860 "glBlitFramebufferEXT(incomplete draw/read buffers)");
2861 return;
2862 }
2863
Brian Paul99745402006-03-01 02:02:43 +00002864 if (filter != GL_NEAREST && filter != GL_LINEAR) {
2865 _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)");
2866 return;
2867 }
2868
Brian Paul722d9762009-01-20 16:58:49 -07002869 if (mask & ~legalMaskBits) {
Brian Paul99745402006-03-01 02:02:43 +00002870 _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
2871 return;
2872 }
2873
Brian Paul0bffb112005-11-08 14:45:48 +00002874 /* depth/stencil must be blitted with nearest filtering */
2875 if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
2876 && filter != GL_NEAREST) {
2877 _mesa_error(ctx, GL_INVALID_OPERATION,
Vinson Lee4f94e0b2011-03-28 20:32:01 -07002878 "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
Brian Paul0bffb112005-11-08 14:45:48 +00002879 return;
2880 }
2881
Brian Paul722d9762009-01-20 16:58:49 -07002882 /* get color read/draw renderbuffers */
2883 if (mask & GL_COLOR_BUFFER_BIT) {
Anuj Phogatab36ca02012-12-11 20:17:47 -08002884 const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
2885 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
2886 const struct gl_renderbuffer *colorDrawRb = NULL;
2887 GLuint i;
Ian Romanickbb475862011-06-07 12:38:39 -07002888
2889 /* From the EXT_framebuffer_object spec:
2890 *
2891 * "If a buffer is specified in <mask> and does not exist in both
2892 * the read and draw framebuffers, the corresponding bit is silently
2893 * ignored."
2894 */
Anuj Phogatab36ca02012-12-11 20:17:47 -08002895 if (!colorReadRb || numColorDrawBuffers == 0) {
2896 mask &= ~GL_COLOR_BUFFER_BIT;
Ian Romanickbb475862011-06-07 12:38:39 -07002897 }
Anuj Phogatab36ca02012-12-11 20:17:47 -08002898 else {
2899 for (i = 0; i < numColorDrawBuffers; i++) {
2900 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
2901 if (!colorDrawRb)
2902 continue;
2903
Ian Romanick9cb64a42013-01-17 13:37:53 -08002904 /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
2905 * ES 3.0.1 spec says:
2906 *
2907 * "If the source and destination buffers are identical, an
2908 * INVALID_OPERATION error is generated. Different mipmap
2909 * levels of a texture, different layers of a three-
2910 * dimensional texture or two-dimensional array texture, and
2911 * different faces of a cube map texture do not constitute
2912 * identical buffers."
2913 */
2914 if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
2915 _mesa_error(ctx, GL_INVALID_OPERATION,
2916 "glBlitFramebuffer(source and destination color "
2917 "buffer cannot be the same)");
2918 return;
2919 }
2920
Anuj Phogatab36ca02012-12-11 20:17:47 -08002921 if (!compatible_color_datatypes(colorReadRb->Format,
2922 colorDrawRb->Format)) {
2923 _mesa_error(ctx, GL_INVALID_OPERATION,
2924 "glBlitFramebufferEXT(color buffer datatypes mismatch)");
2925 return;
2926 }
2927 /* extra checks for multisample copies... */
2928 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
2929 /* color formats must match */
2930 if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
2931 _mesa_error(ctx, GL_INVALID_OPERATION,
2932 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
2933 return;
2934 }
2935 }
2936 }
2937 if (filter == GL_LINEAR) {
2938 /* 3.1 spec, page 199:
2939 * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
2940 * if filter is LINEAR and read buffer contains integer data."
2941 */
2942 GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
2943 if (type == GL_INT || type == GL_UNSIGNED_INT) {
2944 _mesa_error(ctx, GL_INVALID_OPERATION,
2945 "glBlitFramebufferEXT(integer color type)");
2946 return;
2947 }
2948 }
Brian Paul9b111702012-01-09 12:38:49 -07002949 }
Brian Paul722d9762009-01-20 16:58:49 -07002950 }
Brian Paul722d9762009-01-20 16:58:49 -07002951
Brian Paul99745402006-03-01 02:02:43 +00002952 if (mask & GL_STENCIL_BUFFER_BIT) {
Brian Pauld1240922011-12-10 11:44:43 -07002953 struct gl_renderbuffer *readRb =
2954 readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
2955 struct gl_renderbuffer *drawRb =
2956 drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
Ian Romanickbb475862011-06-07 12:38:39 -07002957
2958 /* From the EXT_framebuffer_object spec:
2959 *
2960 * "If a buffer is specified in <mask> and does not exist in both
2961 * the read and draw framebuffers, the corresponding bit is silently
2962 * ignored."
2963 */
2964 if ((readRb == NULL) || (drawRb == NULL)) {
Ian Romanickbb475862011-06-07 12:38:39 -07002965 mask &= ~GL_STENCIL_BUFFER_BIT;
2966 }
Anuj Phogat252573a2013-01-07 15:55:31 -08002967 else {
Brian Paul7ecbbc32013-01-15 17:02:30 -07002968 int read_z_bits, draw_z_bits;
2969
Ian Romanick9cb64a42013-01-17 13:37:53 -08002970 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
2971 _mesa_error(ctx, GL_INVALID_OPERATION,
2972 "glBlitFramebuffer(source and destination stencil "
2973 "buffer cannot be the same)");
2974 return;
2975 }
2976
Anuj Phogat252573a2013-01-07 15:55:31 -08002977 if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
2978 _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
2979 /* There is no need to check the stencil datatype here, because
2980 * there is only one: GL_UNSIGNED_INT.
2981 */
2982 _mesa_error(ctx, GL_INVALID_OPERATION,
2983 "glBlitFramebuffer(stencil attachment format mismatch)");
2984 return;
2985 }
2986
Brian Paul7ecbbc32013-01-15 17:02:30 -07002987 read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
2988 draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
Anuj Phogat252573a2013-01-07 15:55:31 -08002989
2990 /* If both buffers also have depth data, the depth formats must match
2991 * as well. If one doesn't have depth, it's not blitted, so we should
2992 * ignore the depth format check.
2993 */
2994 if (read_z_bits > 0 && draw_z_bits > 0 &&
2995 (read_z_bits != draw_z_bits ||
2996 _mesa_get_format_datatype(readRb->Format) !=
2997 _mesa_get_format_datatype(drawRb->Format))) {
2998
2999 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3000 "(stencil attachment depth format mismatch)");
3001 return;
3002 }
Brian Paul99745402006-03-01 02:02:43 +00003003 }
3004 }
3005
3006 if (mask & GL_DEPTH_BUFFER_BIT) {
Brian Pauld1240922011-12-10 11:44:43 -07003007 struct gl_renderbuffer *readRb =
3008 readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
3009 struct gl_renderbuffer *drawRb =
3010 drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
Ian Romanickbb475862011-06-07 12:38:39 -07003011
3012 /* From the EXT_framebuffer_object spec:
3013 *
3014 * "If a buffer is specified in <mask> and does not exist in both
3015 * the read and draw framebuffers, the corresponding bit is silently
3016 * ignored."
3017 */
3018 if ((readRb == NULL) || (drawRb == NULL)) {
Ian Romanickbb475862011-06-07 12:38:39 -07003019 mask &= ~GL_DEPTH_BUFFER_BIT;
3020 }
Anuj Phogat252573a2013-01-07 15:55:31 -08003021 else {
Brian Paul7ecbbc32013-01-15 17:02:30 -07003022 int read_s_bit, draw_s_bit;
3023
Ian Romanick9cb64a42013-01-17 13:37:53 -08003024 if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
3025 _mesa_error(ctx, GL_INVALID_OPERATION,
3026 "glBlitFramebuffer(source and destination depth "
3027 "buffer cannot be the same)");
3028 return;
3029 }
3030
Anuj Phogat252573a2013-01-07 15:55:31 -08003031 if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
3032 _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
3033 (_mesa_get_format_datatype(readRb->Format) !=
3034 _mesa_get_format_datatype(drawRb->Format))) {
3035 _mesa_error(ctx, GL_INVALID_OPERATION,
3036 "glBlitFramebuffer(depth attachment format mismatch)");
3037 return;
3038 }
3039
Brian Paul7ecbbc32013-01-15 17:02:30 -07003040 read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
3041 draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
Anuj Phogat252573a2013-01-07 15:55:31 -08003042
3043 /* If both buffers also have stencil data, the stencil formats must
3044 * match as well. If one doesn't have stencil, it's not blitted, so
3045 * we should ignore the stencil format check.
3046 */
3047 if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
3048 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3049 "(depth attachment stencil bits mismatch)");
3050 return;
3051 }
Brian Paul99745402006-03-01 02:02:43 +00003052 }
Brian Paul0bffb112005-11-08 14:45:48 +00003053 }
3054
Brian Paul722d9762009-01-20 16:58:49 -07003055 if (readFb->Visual.samples > 0 &&
3056 drawFb->Visual.samples > 0 &&
3057 readFb->Visual.samples != drawFb->Visual.samples) {
3058 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paulb87b8572012-01-09 08:11:33 -07003059 "glBlitFramebufferEXT(mismatched samples)");
Brian Paul722d9762009-01-20 16:58:49 -07003060 return;
3061 }
3062
3063 /* extra checks for multisample copies... */
3064 if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
3065 /* src and dest region sizes must be the same */
Paul Berry5d5f0f32012-09-05 16:07:16 -07003066 if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
3067 abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
Brian Paul722d9762009-01-20 16:58:49 -07003068 _mesa_error(ctx, GL_INVALID_OPERATION,
Vinson Lee4f94e0b2011-03-28 20:32:01 -07003069 "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
Brian Paul722d9762009-01-20 16:58:49 -07003070 return;
3071 }
Brian Paul84c38c72012-01-09 08:11:33 -07003072 }
3073
Brian Paul0bffb112005-11-08 14:45:48 +00003074 if (!ctx->Extensions.EXT_framebuffer_blit) {
3075 _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
3076 return;
3077 }
3078
Brian Paul21f8d312009-10-27 16:59:23 -06003079 /* Debug code */
3080 if (DEBUG_BLIT) {
Anuj Phogatab36ca02012-12-11 20:17:47 -08003081 const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
3082 const struct gl_renderbuffer *colorDrawRb = NULL;
3083 GLuint i = 0;
3084
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003085 printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d,"
3086 " 0x%x, 0x%x)\n",
3087 srcX0, srcY0, srcX1, srcY1,
3088 dstX0, dstY0, dstX1, dstY1,
3089 mask, filter);
Brian Paul21f8d312009-10-27 16:59:23 -06003090 if (colorReadRb) {
3091 const struct gl_renderbuffer_attachment *att;
3092
3093 att = find_attachment(readFb, colorReadRb);
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003094 printf(" Src FBO %u RB %u (%dx%d) ",
3095 readFb->Name, colorReadRb->Name,
3096 colorReadRb->Width, colorReadRb->Height);
Brian Paul21f8d312009-10-27 16:59:23 -06003097 if (att && att->Texture) {
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003098 printf("Tex %u tgt 0x%x level %u face %u",
3099 att->Texture->Name,
3100 att->Texture->Target,
3101 att->TextureLevel,
3102 att->CubeMapFace);
Brian Paul21f8d312009-10-27 16:59:23 -06003103 }
Kristian Høgsberg298be2b2010-02-19 12:32:24 -05003104 printf("\n");
Brian Paul21f8d312009-10-27 16:59:23 -06003105
Anuj Phogatab36ca02012-12-11 20:17:47 -08003106 /* Print all active color render buffers */
3107 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
3108 colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
3109 if (!colorDrawRb)
3110 continue;
3111
3112 att = find_attachment(drawFb, colorDrawRb);
3113 printf(" Dst FBO %u RB %u (%dx%d) ",
3114 drawFb->Name, colorDrawRb->Name,
3115 colorDrawRb->Width, colorDrawRb->Height);
3116 if (att && att->Texture) {
3117 printf("Tex %u tgt 0x%x level %u face %u",
3118 att->Texture->Name,
3119 att->Texture->Target,
3120 att->TextureLevel,
3121 att->CubeMapFace);
3122 }
3123 printf("\n");
Brian Paul21f8d312009-10-27 16:59:23 -06003124 }
Brian Paul21f8d312009-10-27 16:59:23 -06003125 }
3126 }
3127
Marek Olšák83478e52011-07-10 20:01:33 +02003128 if (!mask) {
3129 return;
3130 }
3131
Brian Paul0bffb112005-11-08 14:45:48 +00003132 ASSERT(ctx->Driver.BlitFramebuffer);
3133 ctx->Driver.BlitFramebuffer(ctx,
3134 srcX0, srcY0, srcX1, srcY1,
3135 dstX0, dstY0, dstX1, dstY1,
3136 mask, filter);
3137}
Zack Rusinda7bd6a2010-06-28 17:31:21 -04003138
Brian Paul45bd5c42011-12-16 08:44:43 -07003139
Ian Romanick342be8a2012-08-13 09:27:00 -07003140static void
3141invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
3142 const GLenum *attachments, GLint x, GLint y,
3143 GLsizei width, GLsizei height, const char *name)
3144{
3145 int i;
3146 struct gl_framebuffer *fb;
3147 GET_CURRENT_CONTEXT(ctx);
3148
Ian Romanick342be8a2012-08-13 09:27:00 -07003149 fb = get_framebuffer_target(ctx, target);
3150 if (!fb) {
3151 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
3152 return;
3153 }
3154
3155 if (numAttachments < 0) {
3156 _mesa_error(ctx, GL_INVALID_VALUE,
3157 "%s(numAttachments < 0)", name);
3158 return;
3159 }
3160
3161 /* The GL_ARB_invalidate_subdata spec says:
3162 *
3163 * "If an attachment is specified that does not exist in the
3164 * framebuffer bound to <target>, it is ignored."
3165 *
3166 * It also says:
3167 *
3168 * "If <attachments> contains COLOR_ATTACHMENTm and m is greater than
3169 * or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
3170 * INVALID_OPERATION is generated."
3171 *
3172 * No mention is made of GL_AUXi being out of range. Therefore, we allow
3173 * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
3174 * set of retrictions).
3175 */
3176 for (i = 0; i < numAttachments; i++) {
3177 if (_mesa_is_winsys_fbo(fb)) {
3178 switch (attachments[i]) {
3179 case GL_ACCUM:
3180 case GL_AUX0:
3181 case GL_AUX1:
3182 case GL_AUX2:
3183 case GL_AUX3:
3184 /* Accumulation buffers and auxilary buffers were removed in
3185 * OpenGL 3.1, and they never existed in OpenGL ES.
3186 */
Paul Berrydbd61352012-11-27 12:26:51 -08003187 if (ctx->API != API_OPENGL_COMPAT)
Ian Romanick342be8a2012-08-13 09:27:00 -07003188 goto invalid_enum;
3189 break;
3190 case GL_COLOR:
3191 case GL_DEPTH:
3192 case GL_STENCIL:
3193 break;
3194 case GL_BACK_LEFT:
3195 case GL_BACK_RIGHT:
3196 case GL_FRONT_LEFT:
3197 case GL_FRONT_RIGHT:
3198 if (!_mesa_is_desktop_gl(ctx))
3199 goto invalid_enum;
3200 break;
3201 default:
3202 goto invalid_enum;
3203 }
3204 } else {
3205 switch (attachments[i]) {
3206 case GL_DEPTH_ATTACHMENT:
3207 case GL_STENCIL_ATTACHMENT:
3208 break;
3209 case GL_COLOR_ATTACHMENT0:
3210 case GL_COLOR_ATTACHMENT1:
3211 case GL_COLOR_ATTACHMENT2:
3212 case GL_COLOR_ATTACHMENT3:
3213 case GL_COLOR_ATTACHMENT4:
3214 case GL_COLOR_ATTACHMENT5:
3215 case GL_COLOR_ATTACHMENT6:
3216 case GL_COLOR_ATTACHMENT7:
3217 case GL_COLOR_ATTACHMENT8:
3218 case GL_COLOR_ATTACHMENT9:
3219 case GL_COLOR_ATTACHMENT10:
3220 case GL_COLOR_ATTACHMENT11:
3221 case GL_COLOR_ATTACHMENT12:
3222 case GL_COLOR_ATTACHMENT13:
3223 case GL_COLOR_ATTACHMENT14:
3224 case GL_COLOR_ATTACHMENT15: {
Brian Paul859c3872012-11-04 16:43:44 -07003225 unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
Ian Romanick342be8a2012-08-13 09:27:00 -07003226 if (k >= ctx->Const.MaxColorAttachments) {
3227 _mesa_error(ctx, GL_INVALID_OPERATION,
3228 "%s(attachment >= max. color attachments)", name);
3229 return;
3230 }
3231 }
3232 default:
3233 goto invalid_enum;
3234 }
3235 }
3236 }
3237
3238 /* We don't actually do anything for this yet. Just return after
3239 * validating the parameters and generating the required errors.
3240 */
3241 return;
3242
3243invalid_enum:
3244 _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
3245 return;
3246}
3247
3248void GLAPIENTRY
3249_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
3250 const GLenum *attachments, GLint x, GLint y,
3251 GLsizei width, GLsizei height)
3252{
3253 invalidate_framebuffer_storage(target, numAttachments, attachments,
3254 x, y, width, height,
3255 "glInvalidateSubFramebuffer");
3256}
3257
3258void GLAPIENTRY
3259_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
3260 const GLenum *attachments)
3261{
3262 /* The GL_ARB_invalidate_subdata spec says:
3263 *
3264 * "The command
3265 *
3266 * void InvalidateFramebuffer(enum target,
3267 * sizei numAttachments,
3268 * const enum *attachments);
3269 *
3270 * is equivalent to the command InvalidateSubFramebuffer with <x>, <y>,
3271 * <width>, <height> equal to 0, 0, <MAX_VIEWPORT_DIMS[0]>,
3272 * <MAX_VIEWPORT_DIMS[1]> respectively."
3273 */
3274 invalidate_framebuffer_storage(target, numAttachments, attachments,
3275 0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
3276 "glInvalidateFramebuffer");
3277}