#include "texstore.h"
+/* XXX temporarily here */
+#define GL_READ_FRAMEBUFFER_EXT 0x90
+#define GL_DRAW_FRAMEBUFFER_EXT 0x9a
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_FRAMEBUFFER_BINDING_EXT
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x9b
+
+
/**
* Notes:
*
* Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
* gl_renderbuffer_attachment object.
*/
-static struct gl_renderbuffer_attachment *
-get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment)
+struct gl_renderbuffer_attachment *
+_mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLenum attachment)
{
GLuint i;
{
if (att->Type == GL_TEXTURE) {
ASSERT(att->Texture);
- if (att->Renderbuffer) {
- /* delete/remove the 'wrapper' renderbuffer */
- /* XXX do we really want to do this??? */
- att->Renderbuffer->Delete(att->Renderbuffer);
- att->Renderbuffer = NULL;
- }
att->Texture->RefCount--;
if (att->Texture->RefCount == 0) {
ctx->Driver.DeleteTexture(ctx, att->Texture);
}
+ else {
+ /* tell driver that we're done rendering to this texture. */
+ if (ctx->Driver.FinishRenderTexture) {
+ ctx->Driver.FinishRenderTexture(ctx, att->Texture,
+ att->CubeMapFace,
+ att->TextureLevel);
+ }
+ }
att->Texture = NULL;
}
- else if (att->Type == GL_RENDERBUFFER_EXT) {
+ if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
ASSERT(att->Renderbuffer);
ASSERT(!att->Texture);
att->Renderbuffer->RefCount--;
struct gl_texture_object *texObj,
GLenum texTarget, GLuint level, GLuint zoffset)
{
- _mesa_remove_attachment(ctx, att);
- att->Type = GL_TEXTURE;
- att->Texture = texObj;
+ if (att->Texture == texObj) {
+ /* re-attaching same texture */
+ ASSERT(att->Type == GL_TEXTURE);
+ }
+ else {
+ /* new attachment */
+ _mesa_remove_attachment(ctx, att);
+ att->Type = GL_TEXTURE;
+ att->Texture = texObj;
+ texObj->RefCount++;
+ }
+
+ /* always update these fields */
att->TextureLevel = level;
if (IS_CUBE_FACE(texTarget)) {
att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
}
att->Zoffset = zoffset;
att->Complete = GL_FALSE;
-
- texObj->RefCount++;
-
- /* XXX when we attach to a texture, we should probably set the
- * att->Renderbuffer pointer to a "wrapper renderbuffer" which
- * makes the texture image look like renderbuffer.
- */
}
/**
* Fallback for ctx->Driver.FramebufferRenderbuffer()
- * Sets a framebuffer attachment to a particular renderbuffer.
- * The framebuffer in question is ctx->DrawBuffer.
- * \sa _mesa_renderbuffer_texture
+ * Attach a renderbuffer object to a framebuffer object.
*/
void
-_mesa_framebuffer_renderbuffer(GLcontext *ctx,
- struct gl_renderbuffer_attachment *att,
- struct gl_renderbuffer *rb)
+_mesa_framebuffer_renderbuffer(GLcontext *ctx, struct gl_framebuffer *fb,
+ GLenum attachment, struct gl_renderbuffer *rb)
{
+ struct gl_renderbuffer_attachment *att;
+
+ att = _mesa_get_attachment(ctx, fb, attachment);
+ ASSERT(att);
+
if (rb) {
_mesa_set_renderbuffer_attachment(ctx, att, rb);
}
}
if (att->Type == GL_TEXTURE) {
- w = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Width;
- h = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Height;
- f = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Format;
+ const struct gl_texture_image *texImg
+ = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ w = texImg->Width;
+ h = texImg->Height;
+ f = texImg->_BaseFormat;
numImages++;
if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT) {
/* XXX need GL_DEPTH_STENCIL_EXT test? */
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
if (fb->ColorDrawBuffer[i] != GL_NONE) {
const struct gl_renderbuffer_attachment *att
- = get_attachment(ctx, fb, fb->ColorDrawBuffer[i]);
+ = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[i]);
assert(att);
if (att->Type == GL_NONE) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
/* Check that the ReadBuffer is present */
if (fb->ColorReadBuffer != GL_NONE) {
const struct gl_renderbuffer_attachment *att
- = get_attachment(ctx, fb, fb->ColorReadBuffer);
+ = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
assert(att);
if (att->Type == GL_NONE) {
fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (target != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
if (renderbuffer) {
newRb = lookup_renderbuffer(ctx, renderbuffer);
if (newRb == &DummyRenderbuffer) {
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
for (i = 0; i < n; i++) {
if (renderbuffers[i] > 0) {
struct gl_renderbuffer *rb;
rb = lookup_renderbuffer(ctx, renderbuffers[i]);
if (rb) {
+ /* check if deleting currently bound renderbuffer object */
+ if (rb == ctx->CurrentRenderbuffer) {
+ /* bind default */
+ ASSERT(rb->RefCount >= 2);
+ _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+ }
+
/* remove from hash table immediately, to free the ID */
_mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (target != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM, "glRenderbufferStorageEXT(target)");
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ if (rb->InternalFormat == internalFormat &&
+ rb->Width == width &&
+ rb->Height == height) {
+ /* no change in allocation needed */
+ return;
+ }
+
/* Now allocate the storage */
ASSERT(rb->AllocStorage);
if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
assert(rb->Width == width);
assert(rb->Height == height);
assert(rb->InternalFormat);
+ assert(rb->RedBits || rb->GreenBits || rb->BlueBits || rb->AlphaBits ||
+ rb->DepthBits || rb->StencilBits || rb->IndexBits);
rb->_BaseFormat = baseFormat;
}
else {
rb->Height = 0;
rb->InternalFormat = GL_NONE;
rb->_BaseFormat = GL_NONE;
+ rb->RedBits =
+ rb->GreenBits =
+ rb->BlueBits =
+ rb->AlphaBits =
+ rb->IndexBits =
+ rb->DepthBits =
+ rb->StencilBits = 0;
}
/*
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
switch (pname) {
case GL_RENDERBUFFER_WIDTH_EXT:
*params = ctx->CurrentRenderbuffer->Width;
*params = ctx->CurrentRenderbuffer->InternalFormat;
return;
case GL_RENDERBUFFER_RED_SIZE_EXT:
- if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
- ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
- *params = ctx->CurrentRenderbuffer->RedBits;
- }
- else {
- *params = 0;
- }
+ *params = ctx->CurrentRenderbuffer->RedBits;
break;
case GL_RENDERBUFFER_GREEN_SIZE_EXT:
- if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
- ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
- *params = ctx->CurrentRenderbuffer->GreenBits;
- }
- else {
- *params = 0;
- }
+ *params = ctx->CurrentRenderbuffer->GreenBits;
break;
case GL_RENDERBUFFER_BLUE_SIZE_EXT:
- if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
- ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
- *params = ctx->CurrentRenderbuffer->BlueBits;
- }
- else {
- *params = 0;
- }
+ *params = ctx->CurrentRenderbuffer->BlueBits;
break;
case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
- if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
- ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
- *params = ctx->CurrentRenderbuffer->AlphaBits;
- }
- else {
- *params = 0;
- }
+ *params = ctx->CurrentRenderbuffer->AlphaBits;
break;
case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
- if (ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_COMPONENT ||
- ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
- *params = ctx->CurrentRenderbuffer->DepthBits;
- }
- else {
- *params = 0;
- }
+ *params = ctx->CurrentRenderbuffer->DepthBits;
break;
case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
- if (ctx->CurrentRenderbuffer->_BaseFormat == GL_STENCIL_INDEX ||
- ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
- *params = ctx->CurrentRenderbuffer->StencilBits;
- }
- else {
- *params = 0;
- }
+ *params = ctx->CurrentRenderbuffer->StencilBits;
break;
-
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetRenderbufferParameterivEXT(target)");
}
+/**
+ * Examine all the framebuffer's attachments to see if any are textures.
+ * If so, call ctx->Driver.FinishRenderTexture() for each texture to
+ * notify the device driver that the texture image may have changed.
+ */
+static void
+check_texture_render(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ if (ctx->Driver.FinishRenderTexture) {
+ GLuint i;
+ for (i = 0; i < BUFFER_COUNT; i++) {
+ struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+ struct gl_texture_object *texObj = att->Texture;
+ if (texObj) {
+ ctx->Driver.FinishRenderTexture(ctx, texObj, att->CubeMapFace,
+ att->TextureLevel);
+ }
+ }
+ }
+}
+
+
void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
{
- struct gl_framebuffer *newFb, *newReadFb, *oldFb;
+ struct gl_framebuffer *newFb, *oldFb;
+ GLboolean bindReadBuf, bindDrawBuf;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
- if (target != GL_FRAMEBUFFER_EXT) {
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+ bindDrawBuf = GL_TRUE;
+ bindReadBuf = GL_FALSE;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
+ return;
+ }
+ bindDrawBuf = GL_FALSE;
+ bindReadBuf = GL_TRUE;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ bindDrawBuf = GL_TRUE;
+ bindReadBuf = GL_TRUE;
+ break;
+ default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
if (framebuffer) {
/* Binding a user-created framebuffer object */
newFb = lookup_framebuffer(ctx, framebuffer);
}
_mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
}
- newFb->RefCount++;
- newReadFb = newFb;
+ if (bindReadBuf)
+ newFb->RefCount++;
+ if (bindDrawBuf)
+ newFb->RefCount++;
}
else {
/* Binding the window system framebuffer (which was originally set
* with MakeCurrent).
*/
newFb = ctx->WinSysDrawBuffer;
- newReadFb = ctx->WinSysReadBuffer;
}
- oldFb = ctx->DrawBuffer;
- if (oldFb) { /* AND oldFb->Name != 0 */
- oldFb->RefCount--;
- if (oldFb->RefCount == 0) {
- oldFb->Delete(oldFb);
+ ASSERT(newFb != &DummyFramebuffer);
+
+ if (bindReadBuf) {
+ oldFb = ctx->ReadBuffer;
+ if (oldFb && oldFb->Name != 0) {
+ oldFb->RefCount--;
+ if (oldFb->RefCount == 0) {
+ oldFb->Delete(oldFb);
+ }
}
+ ctx->ReadBuffer = newFb;
}
- ASSERT(newFb != &DummyFramebuffer);
-
- /* Note, we set both the GL_DRAW_BUFFER and GL_READ_BUFFER state: */
- ctx->DrawBuffer = newFb;
- ctx->ReadBuffer = newReadFb;
+ if (bindDrawBuf) {
+ oldFb = ctx->DrawBuffer;
+ if (oldFb && oldFb->Name != 0) {
+ /* check if old FB had any texture attachments */
+ if (ctx->Driver.FinishRenderTexture) {
+ check_texture_render(ctx, oldFb);
+ }
+ /* check if time to delete this framebuffer */
+ oldFb->RefCount--;
+ if (oldFb->RefCount == 0) {
+ oldFb->Delete(oldFb);
+ }
+ }
+ ctx->DrawBuffer = newFb;
+ }
}
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
for (i = 0; i < n; i++) {
if (framebuffers[i] > 0) {
fb = lookup_framebuffer(ctx, framebuffers[i]);
if (fb) {
ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
+
+ /* check if deleting currently bound framebuffer object */
+ if (fb == ctx->DrawBuffer) {
+ /* bind default */
+ ASSERT(fb->RefCount >= 2);
+ _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+
/* remove from hash table immediately, to free the ID */
_mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
GLenum GLAPIENTRY
_mesa_CheckFramebufferStatusEXT(GLenum target)
{
+ struct gl_framebuffer *buffer;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
- if (target != GL_FRAMEBUFFER_EXT) {
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+ return 0;
+ }
+ buffer = ctx->DrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
+ return 0;
+ }
+ buffer = ctx->ReadBuffer;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ buffer = ctx->DrawBuffer;
+ break;
+ default:
_mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
}
- if (ctx->DrawBuffer->Name == 0) {
+ if (buffer->Name == 0) {
/* The window system / default framebuffer is always complete */
return GL_FRAMEBUFFER_COMPLETE_EXT;
}
- _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
- return ctx->DrawBuffer->_Status;
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ _mesa_test_framebuffer_completeness(ctx, buffer);
+ return buffer->_Status;
}
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* XXX check */
if (error_check_framebuffer_texture(ctx, 1, target, attachment,
textarget, texture, level))
ASSERT(textarget == GL_TEXTURE_1D);
- att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+ /* XXX read blit */
+ att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(attachment)");
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
if (texture) {
texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
texObj = NULL;
}
ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0);
-
- _mesa_update_framebuffer_visual(ctx->DrawBuffer);
}
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* XXX check */
if (error_check_framebuffer_texture(ctx, 2, target, attachment,
textarget, texture, level))
textarget == GL_TEXTURE_RECTANGLE_ARB ||
IS_CUBE_FACE(textarget));
- att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+ att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture2DEXT(attachment)");
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
if (texture) {
texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
texObj = NULL;
}
ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0);
- _mesa_update_framebuffer_visual(ctx->DrawBuffer);
}
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* XXX check */
if (error_check_framebuffer_texture(ctx, 3, target, attachment,
textarget, texture, level))
ASSERT(textarget == GL_TEXTURE_3D);
- att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+ att = _mesa_get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(attachment)");
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
if (texture) {
const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
texObj = (struct gl_texture_object *)
}
ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget,
level, zoffset);
- _mesa_update_framebuffer_visual(ctx->DrawBuffer);
}
GLuint renderbuffer)
{
struct gl_renderbuffer_attachment *att;
+ struct gl_framebuffer *fb;
struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- FLUSH_VERTICES(ctx, _NEW_BUFFERS);
- if (target != GL_FRAMEBUFFER_EXT) {
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(target)");
+ return;
+ }
+ fb = ctx->DrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(target)");
+ return;
+ }
+ fb = ctx->ReadBuffer;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ fb = ctx->DrawBuffer;
+ break;
+ default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(target)");
return;
return;
}
- if (ctx->DrawBuffer->Name == 0) {
+ if (fb->Name == 0) {
/* Can't attach new renderbuffers to a window system framebuffer */
_mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
return;
}
- att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+ att = _mesa_get_attachment(ctx, fb, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(attachment)");
rb = NULL;
}
- assert(ctx->Driver.FramebufferRenderbuffer);
- ctx->Driver.FramebufferRenderbuffer(ctx, att, rb);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
- _mesa_update_framebuffer_visual(ctx->DrawBuffer);
+ assert(ctx->Driver.FramebufferRenderbuffer);
+ ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
}
GLenum pname, GLint *params)
{
const struct gl_renderbuffer_attachment *att;
+ struct gl_framebuffer *buffer;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- if (target != GL_FRAMEBUFFER_EXT) {
+ switch (target) {
+#if FEATURE_EXT_framebuffer_blit
+ case GL_DRAW_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(target)");
+ return;
+ }
+ buffer = ctx->DrawBuffer;
+ break;
+ case GL_READ_FRAMEBUFFER_EXT:
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetFramebufferAttachmentParameterivEXT(target)");
+ return;
+ }
+ buffer = ctx->ReadBuffer;
+ break;
+#endif
+ case GL_FRAMEBUFFER_EXT:
+ buffer = ctx->DrawBuffer;
+ break;
+ default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(target)");
return;
}
- if (ctx->DrawBuffer->Name == 0) {
+ if (buffer->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetFramebufferAttachmentParameterivEXT");
return;
}
- att = get_attachment(ctx, ctx->DrawBuffer, attachment);
+ att = _mesa_get_attachment(ctx, buffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(attachment)");
return;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
switch (pname) {
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
*params = att->Type;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
switch (target) {
case GL_TEXTURE_1D:
/* XXX this might not handle cube maps correctly */
_mesa_generate_mipmap(ctx, target, texUnit, texObj);
}
+
+
+#if FEATURE_EXT_framebuffer_blit
+void GLAPIENTRY
+_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+
+ /* check for complete framebuffers */
+ if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+ ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glBlitFramebufferEXT(incomplete draw/read buffers)");
+ return;
+ }
+
+ /* depth/stencil must be blitted with nearest filtering */
+ if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+ && filter != GL_NEAREST) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter");
+ return;
+ }
+
+ if (mask & ~(GL_COLOR_BUFFER_BIT |
+ GL_DEPTH_BUFFER_BIT |
+ GL_STENCIL_BUFFER_BIT)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
+ return;
+ }
+
+ if (!ctx->Extensions.EXT_framebuffer_blit) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
+ return;
+ }
+
+ ASSERT(ctx->Driver.BlitFramebuffer);
+ ctx->Driver.BlitFramebuffer(ctx,
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+}
+#endif /* FEATURE_EXT_framebuffer_blit */