#include "context.h"
#include "fbobject.h"
+#include "framebuffer.h"
#include "hash.h"
+#include "renderbuffer.h"
#include "teximage.h"
#include "texstore.h"
* Later, when the object ID is first bound, we replace the placeholder
* with the real frame/renderbuffer.
*/
-static struct gl_frame_buffer_object DummyFramebuffer;
-static struct gl_render_buffer_object DummyRenderbuffer;
+static struct gl_framebuffer DummyFramebuffer;
+static struct gl_renderbuffer DummyRenderbuffer;
#define IS_CUBE_FACE(TARGET) \
/**
- * Helper routine for getting a gl_render_buffer_object.
+ * Helper routine for getting a gl_renderbuffer.
*/
-static struct gl_render_buffer_object *
+static struct gl_renderbuffer *
lookup_renderbuffer(GLcontext *ctx, GLuint id)
{
- struct gl_render_buffer_object *rb;
+ struct gl_renderbuffer *rb;
if (id == 0)
return NULL;
- rb = (struct gl_render_buffer_object *)
+ rb = (struct gl_renderbuffer *)
_mesa_HashLookup(ctx->Shared->RenderBuffers, id);
return rb;
}
/**
- * Helper routine for getting a gl_frame_buffer_object.
+ * Helper routine for getting a gl_framebuffer.
*/
-static struct gl_frame_buffer_object *
+static struct gl_framebuffer *
lookup_framebuffer(GLcontext *ctx, GLuint id)
{
- struct gl_frame_buffer_object *fb;
+ struct gl_framebuffer *fb;
if (id == 0)
return NULL;
- fb = (struct gl_frame_buffer_object *)
+ fb = (struct gl_framebuffer *)
_mesa_HashLookup(ctx->Shared->FrameBuffers, id);
return fb;
}
-/**
- * Allocate a new gl_render_buffer_object.
- * XXX make this a device driver function.
- */
-static struct gl_render_buffer_object *
-new_renderbuffer(GLcontext *ctx, GLuint name)
-{
- struct gl_render_buffer_object *rb = CALLOC_STRUCT(gl_render_buffer_object);
- if (rb) {
- rb->Name = name;
- rb->RefCount = 1;
- /* other fields are zero */
- }
- return rb;
-}
-
-
-/**
- * Allocate a new gl_frame_buffer_object.
- * XXX make this a device driver function.
- */
-static struct gl_frame_buffer_object *
-new_framebuffer(GLcontext *ctx, GLuint name)
-{
- struct gl_frame_buffer_object *fb = CALLOC_STRUCT(gl_frame_buffer_object);
- if (fb) {
- fb->Name = name;
- fb->RefCount = 1;
- }
- return fb;
-}
-
-
/**
* Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
- * gl_render_buffer_attachment object.
+ * gl_renderbuffer_attachment object.
*/
-static struct gl_render_buffer_attachment *
-get_attachment(GLcontext *ctx, GLenum attachment)
+static struct gl_renderbuffer_attachment *
+get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, GLenum attachment)
{
GLuint i;
if (i >= ctx->Const.MaxColorAttachments) {
return NULL;
}
- return &ctx->CurrentFramebuffer->ColorAttachment[i];
+ return &fb->Attachment[BUFFER_COLOR0 + i];
case GL_DEPTH_ATTACHMENT_EXT:
- return &ctx->CurrentFramebuffer->DepthAttachment;
+ return &fb->Attachment[BUFFER_DEPTH];
case GL_STENCIL_ATTACHMENT_EXT:
- return &ctx->CurrentFramebuffer->StencilAttachment;
+ return &fb->Attachment[BUFFER_STENCIL];
default:
return NULL;
}
* Remove any texture or renderbuffer attached to the given attachment
* point. Update reference counts, etc.
*/
-static void
-remove_attachment(GLcontext *ctx, struct gl_render_buffer_attachment *att)
+void
+_mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
{
if (att->Type == GL_TEXTURE) {
ASSERT(att->Texture);
- ASSERT(!att->Renderbuffer);
+ 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);
ASSERT(!att->Texture);
att->Renderbuffer->RefCount--;
if (att->Renderbuffer->RefCount == 0) {
- _mesa_free(att->Renderbuffer); /* XXX driver free */
+ att->Renderbuffer->Delete(att->Renderbuffer);
}
att->Renderbuffer = NULL;
}
* Bind a texture object to an attachment point.
* The previous binding, if any, will be removed first.
*/
-static void
-set_texture_attachment(GLcontext *ctx,
- struct gl_render_buffer_attachment *att,
- struct gl_texture_object *texObj,
- GLenum texTarget, GLuint level, GLuint zoffset)
+void
+_mesa_set_texture_attachment(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_texture_object *texObj,
+ GLenum texTarget, GLuint level, GLuint zoffset)
{
- remove_attachment(ctx, att);
+ _mesa_remove_attachment(ctx, att);
att->Type = GL_TEXTURE;
att->Texture = texObj;
att->TextureLevel = level;
}
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.
+ */
}
* Bind a renderbuffer to an attachment point.
* The previous binding, if any, will be removed first.
*/
-static void
-set_renderbuffer_attachment(GLcontext *ctx,
- struct gl_render_buffer_attachment *att,
- struct gl_render_buffer_object *rb)
+void
+_mesa_set_renderbuffer_attachment(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_renderbuffer *rb)
{
- remove_attachment(ctx, att);
+ _mesa_remove_attachment(ctx, att);
att->Type = GL_RENDERBUFFER_EXT;
att->Renderbuffer = rb;
+ att->Texture = NULL; /* just to be safe */
att->Complete = GL_FALSE;
rb->RefCount++;
}
+/**
+ * Fallback for ctx->Driver.FramebufferRenderbuffer()
+ * Sets a framebuffer attachment to a particular renderbuffer.
+ * The framebuffer in question is ctx->DrawBuffer.
+ * \sa _mesa_renderbuffer_texture
+ */
+void
+_mesa_framebuffer_renderbuffer(GLcontext *ctx,
+ struct gl_renderbuffer_attachment *att,
+ struct gl_renderbuffer *rb)
+{
+ if (rb) {
+ _mesa_set_renderbuffer_attachment(ctx, att, rb);
+ }
+ else {
+ _mesa_remove_attachment(ctx, att);
+ }
+}
+
+
/**
* Test if an attachment point is complete and update its Complete field.
* \param format if GL_COLOR, this is a color attachment point,
*/
static void
test_attachment_completeness(const GLcontext *ctx, GLenum format,
- struct gl_render_buffer_attachment *att)
+ struct gl_renderbuffer_attachment *att)
{
assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
/* assume complete */
att->Complete = GL_TRUE;
- if (att->Type == GL_NONE)
- return; /* complete */
-
/* Look for reasons why the attachment might be incomplete */
if (att->Type == GL_TEXTURE) {
- struct gl_texture_object *texObj = att->Texture;
+ const struct gl_texture_object *texObj = att->Texture;
struct gl_texture_image *texImage;
- assert(texObj);
+ if (!texObj) {
+ att->Complete = GL_FALSE;
+ return;
+ }
texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
if (!texImage) {
}
if (format == GL_COLOR) {
- if (texImage->Format != GL_RGB && texImage->Format != GL_RGBA) {
+ if (texImage->TexFormat->BaseFormat != GL_RGB &&
+ texImage->TexFormat->BaseFormat != GL_RGBA) {
att->Complete = GL_FALSE;
return;
}
}
else if (format == GL_DEPTH) {
- if (texImage->Format != GL_DEPTH_COMPONENT) {
+ if (texImage->TexFormat->BaseFormat != GL_DEPTH_COMPONENT) {
att->Complete = GL_FALSE;
return;
}
return;
}
}
- else {
- assert(att->Type == GL_RENDERBUFFER_EXT);
-
+ else if (att->Type == GL_RENDERBUFFER_EXT) {
if (att->Renderbuffer->Width < 1 || att->Renderbuffer->Height < 1) {
att->Complete = GL_FALSE;
return;
}
}
}
+ else {
+ ASSERT(att->Type == GL_NONE);
+ /* complete */
+ return;
+ }
}
/**
* Test if the given framebuffer object is complete and update its
* Status field with the results.
+ * Also update the framebuffer's Width and Height fields if the
+ * framebuffer is complete.
*/
-static void
-test_framebuffer_completeness(GLcontext *ctx,
- struct gl_frame_buffer_object *fb)
+void
+_mesa_test_framebuffer_completeness(GLcontext *ctx, struct gl_framebuffer *fb)
{
+ GLuint numImages, width = 0, height = 0;
+ GLenum intFormat = GL_NONE;
+ GLuint w = 0, h = 0;
GLint i;
- GLuint numImages, width, height;
- GLenum intFormat;
- /* Set to COMPLETE status, then try to find reasons for being incomplete */
- fb->Status = GL_FRAMEBUFFER_COMPLETE_EXT;
+ assert(fb->Name != 0);
numImages = 0;
+ fb->Width = 0;
+ fb->Height = 0;
/* Start at -2 to more easily loop over all attachment points */
- for (i = -2; i < ctx->Const.MaxColorAttachments; i++) {
- struct gl_render_buffer_attachment *att;
- GLuint w, h;
+ for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
+ struct gl_renderbuffer_attachment *att;
GLenum f;
if (i == -2) {
- att = &fb->DepthAttachment;
+ att = &fb->Attachment[BUFFER_DEPTH];
test_attachment_completeness(ctx, GL_DEPTH, att);
if (!att->Complete) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
return;
}
}
else if (i == -1) {
- att = &fb->StencilAttachment;
+ att = &fb->Attachment[BUFFER_STENCIL];
test_attachment_completeness(ctx, GL_STENCIL, att);
if (!att->Complete) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
return;
}
}
else {
- att = &fb->ColorAttachment[i];
+ att = &fb->Attachment[BUFFER_COLOR0 + i];
test_attachment_completeness(ctx, GL_COLOR, att);
if (!att->Complete) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
return;
}
}
h = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Height;
f = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->Format;
numImages++;
+ if (f != GL_RGB && f != GL_RGBA && f != GL_DEPTH_COMPONENT) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+ return;
+ }
}
else if (att->Type == GL_RENDERBUFFER_EXT) {
w = att->Renderbuffer->Width;
else {
/* check that width, height, format are same */
if (w != width || h != height) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
return;
}
- if (i >= 0 && f != intFormat) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
+ if (intFormat != GL_NONE && f != intFormat) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
return;
}
-
}
}
/* Check that all DrawBuffers are present */
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- if (fb->DrawBuffer[i] != GL_NONE) {
- struct gl_render_buffer_attachment *att
- = get_attachment(ctx, fb->DrawBuffer[i]);
+ if (fb->ColorDrawBuffer[i] != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = get_attachment(ctx, fb, fb->ColorDrawBuffer[i]);
+ assert(att);
if (att->Type == GL_NONE) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
return;
}
}
}
/* Check that the ReadBuffer is present */
- if (fb->ReadBuffer != GL_NONE) {
- struct gl_render_buffer_attachment *att
- = get_attachment(ctx, fb->ReadBuffer);
+ if (fb->ColorReadBuffer != GL_NONE) {
+ const struct gl_renderbuffer_attachment *att
+ = get_attachment(ctx, fb, fb->ColorReadBuffer);
+ assert(att);
if (att->Type == GL_NONE) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
return;
}
}
+ /* Check if any renderbuffer is attached more than once */
+ for (i = 0; i < BUFFER_COUNT - 1; i++) {
+ struct gl_renderbuffer *rb_i = fb->Attachment[i].Renderbuffer;
+ if (rb_i) {
+ GLint j;
+ for (j = i + 1; j < BUFFER_COUNT; j++) {
+ struct gl_renderbuffer *rb_j = fb->Attachment[j].Renderbuffer;
+ if (rb_i == rb_j) {
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT;
+ return;
+ }
+ }
+ }
+ }
+
+
if (numImages == 0) {
- fb->Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
+ fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
return;
}
-}
+ /*
+ * If we get here, the framebuffer is complete!
+ */
+ fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
+ fb->Width = w;
+ fb->Height = h;
+}
GLboolean GLAPIENTRY
_mesa_IsRenderbufferEXT(GLuint renderbuffer)
{
- const struct gl_render_buffer_object *rb;
GET_CURRENT_CONTEXT(ctx);
-
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
- rb = lookup_renderbuffer(ctx, renderbuffer);
- return rb ? GL_TRUE : GL_FALSE;
+ if (renderbuffer && lookup_renderbuffer(ctx, renderbuffer))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
}
void GLAPIENTRY
_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
{
- struct gl_render_buffer_object *newRb, *oldRb;
+ struct gl_renderbuffer *newRb, *oldRb;
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,
}
if (!newRb) {
/* create new renderbuffer object */
- newRb = new_renderbuffer(ctx, renderbuffer);
+ newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
if (!newRb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
return;
}
+ ASSERT(newRb->AllocStorage);
_mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
}
newRb->RefCount++;
if (oldRb) {
oldRb->RefCount--;
if (oldRb->RefCount == 0) {
- _mesa_free(oldRb); /* XXX device driver function */
+ oldRb->Delete(oldRb);
}
}
ASSERT_OUTSIDE_BEGIN_END(ctx);
for (i = 0; i < n; i++) {
- if (renderbuffers[i]) {
- struct gl_render_buffer_object *rb;
+ if (renderbuffers[i] > 0) {
+ struct gl_renderbuffer *rb;
rb = lookup_renderbuffer(ctx, renderbuffers[i]);
if (rb) {
/* remove from hash table immediately, to free the ID */
*/
rb->RefCount--;
if (rb->RefCount == 0) {
- _mesa_free(rb); /* XXX call device driver function */
+ rb->Delete(rb);
}
}
}
case GL_STENCIL_INDEX16_EXT:
return GL_STENCIL_INDEX;
case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16_SGIX:
- case GL_DEPTH_COMPONENT24_SGIX:
- case GL_DEPTH_COMPONENT32_SGIX:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32:
return GL_DEPTH_COMPONENT;
/* XXX add floating point formats eventually */
default:
_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
GLsizei width, GLsizei height)
{
+ struct gl_renderbuffer *rb;
GLenum baseFormat;
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;
}
- /* XXX this check isn't in the spec, but seems necessary */
- if (!ctx->CurrentRenderbuffer) {
+ rb = ctx->CurrentRenderbuffer;
+
+ if (!rb) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferStorageEXT");
return;
}
- if (ctx->CurrentRenderbuffer->Data) {
- /* XXX device driver free */
- _mesa_free(ctx->CurrentRenderbuffer->Data);
+ /* Now allocate the storage */
+ ASSERT(rb->AllocStorage);
+ if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
+ /* No error - check/set fields now */
+ assert(rb->Width == width);
+ assert(rb->Height == height);
+ assert(rb->InternalFormat);
+ rb->_BaseFormat = baseFormat;
}
-
- /* XXX device driver allocate, fix size */
- ctx->CurrentRenderbuffer->Data = _mesa_malloc(width * height * 4);
- if (ctx->CurrentRenderbuffer->Data == NULL) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRenderbufferStorageEXT");
- return;
+ else {
+ /* Probably ran out of memory - clear the fields */
+ rb->Width = 0;
+ rb->Height = 0;
+ rb->InternalFormat = GL_NONE;
+ rb->_BaseFormat = GL_NONE;
}
- ctx->CurrentRenderbuffer->InternalFormat = internalFormat;
- ctx->CurrentRenderbuffer->Width = width;
- ctx->CurrentRenderbuffer->Height = height;
- ctx->CurrentRenderbuffer->_BaseFormat = baseFormat;
+
+ /*
+ test_framebuffer_completeness(ctx, fb);
+ */
+ /* XXX if this renderbuffer is attached anywhere, invalidate attachment
+ * points???
+ */
}
case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
*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->ComponentSizes[0];
+ }
+ else {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_GREEN_SIZE_EXT:
+ if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
+ ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
+ *params = ctx->CurrentRenderbuffer->ComponentSizes[1];
+ }
+ else {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_BLUE_SIZE_EXT:
+ if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
+ ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
+ *params = ctx->CurrentRenderbuffer->ComponentSizes[2];
+ }
+ else {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
+ if (ctx->CurrentRenderbuffer->_BaseFormat == GL_RGB ||
+ ctx->CurrentRenderbuffer->_BaseFormat == GL_RGBA) {
+ *params = ctx->CurrentRenderbuffer->ComponentSizes[3];
+ }
+ else {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
+ if (ctx->CurrentRenderbuffer->_BaseFormat == GL_DEPTH_COMPONENT) {
+ *params = ctx->CurrentRenderbuffer->ComponentSizes[0];
+ }
+ else {
+ *params = 0;
+ }
+ break;
+ case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
+ if (ctx->CurrentRenderbuffer->_BaseFormat == GL_STENCIL_INDEX) {
+ *params = ctx->CurrentRenderbuffer->ComponentSizes[0];
+ }
+ else {
+ *params = 0;
+ }
+ break;
+
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetRenderbufferParameterivEXT(target)");
GLboolean GLAPIENTRY
_mesa_IsFramebufferEXT(GLuint framebuffer)
{
- const struct gl_frame_buffer_object *fb;
GET_CURRENT_CONTEXT(ctx);
-
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
-
- fb = lookup_framebuffer(ctx, framebuffer);
- return fb ? GL_TRUE : GL_FALSE;
+ if (framebuffer && lookup_framebuffer(ctx, framebuffer))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
}
void GLAPIENTRY
_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
{
- struct gl_frame_buffer_object *newFb, *oldFb;
+ struct gl_framebuffer *newFb, *newReadFb, *oldFb;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
}
if (framebuffer) {
+ /* Binding a user-created framebuffer object */
newFb = lookup_framebuffer(ctx, framebuffer);
if (newFb == &DummyFramebuffer) {
/* ID was reserved, but no real framebuffer object made yet */
}
if (!newFb) {
/* create new framebuffer object */
- newFb = new_framebuffer(ctx, framebuffer);
+ newFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
if (!newFb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
return;
_mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newFb);
}
newFb->RefCount++;
+ newReadFb = newFb;
}
else {
- newFb = NULL;
+ /* Binding the window system framebuffer (which was originally set
+ * with MakeCurrent).
+ */
+ newFb = ctx->WinSysDrawBuffer;
+ newReadFb = ctx->WinSysReadBuffer;
}
- oldFb = ctx->CurrentFramebuffer;
- if (oldFb) {
+ oldFb = ctx->DrawBuffer;
+ if (oldFb) { /* AND oldFb->Name != 0 */
oldFb->RefCount--;
if (oldFb->RefCount == 0) {
- _mesa_free(oldFb); /* XXX device driver function */
+ oldFb->Delete(oldFb);
}
}
ASSERT(newFb != &DummyFramebuffer);
- ctx->CurrentFramebuffer = newFb;
+ /* Note, we set both the GL_DRAW_BUFFER and GL_READ_BUFFER state: */
+ ctx->DrawBuffer = newFb;
+ ctx->ReadBuffer = newReadFb;
}
ASSERT_OUTSIDE_BEGIN_END(ctx);
for (i = 0; i < n; i++) {
- if (framebuffers[i]) {
- struct gl_frame_buffer_object *fb;
+ if (framebuffers[i] > 0) {
+ struct gl_framebuffer *fb;
fb = lookup_framebuffer(ctx, framebuffers[i]);
if (fb) {
+ ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
/* remove from hash table immediately, to free the ID */
_mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
*/
fb->RefCount--;
if (fb->RefCount == 0) {
- _mesa_free(fb); /* XXX call device driver function */
+ fb->Delete(fb);
}
}
}
{
GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FRAMEBUFFER_STATUS_ERROR_EXT);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
- return GL_FRAMEBUFFER_STATUS_ERROR_EXT;
+ return 0; /* formerly GL_FRAMEBUFFER_STATUS_ERROR_EXT */
}
- if (!ctx->CurrentFramebuffer) {
+ if (ctx->DrawBuffer->Name == 0) {
/* The window system / default framebuffer is always complete */
return GL_FRAMEBUFFER_COMPLETE_EXT;
}
- test_framebuffer_completeness(ctx, ctx->CurrentFramebuffer);
- return ctx->CurrentFramebuffer->Status;
+ _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer);
+ return ctx->DrawBuffer->_Status;
}
return GL_TRUE;
}
- if (ctx->CurrentFramebuffer == NULL) {
+ /* check framebuffer binding */
+ if (ctx->DrawBuffer->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferTexture%dDEXT", dims);
return GL_TRUE;
}
- /* only check textarget, level if texture ID is non-zero*/
+ /* only check textarget, level if texture ID is non-zero */
if (texture) {
if ((dims == 1 && textarget != GL_TEXTURE_1D) ||
(dims == 3 && textarget != GL_TEXTURE_3D) ||
_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
- struct gl_render_buffer_attachment *att;
+ struct gl_renderbuffer_attachment *att;
+ struct gl_texture_object *texObj;
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, attachment);
+ att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(attachment)");
}
if (texture) {
- struct gl_texture_object *texObj = (struct gl_texture_object *)
+ texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
if (!texObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture1DEXT(texture target)");
return;
}
- set_texture_attachment(ctx, att, texObj, textarget, level, 0);
}
else {
- remove_attachment(ctx, att);
+ /* remove texture attachment */
+ texObj = NULL;
}
-
- /* XXX call a driver function to signal new attachment? */
+ ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0);
}
_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment,
GLenum textarget, GLuint texture, GLint level)
{
- struct gl_render_buffer_attachment *att;
+ struct gl_renderbuffer_attachment *att;
+ struct gl_texture_object *texObj;
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, attachment);
+ att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture2DEXT(attachment)");
}
if (texture) {
- struct gl_texture_object *texObj = (struct gl_texture_object *)
+ texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
if (!texObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture2DEXT(texture target)");
return;
}
- set_texture_attachment(ctx, att, texObj, textarget, level, 0);
}
else {
- remove_attachment(ctx, att);
+ /* remove texture attachment */
+ texObj = NULL;
}
-
+ ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget, level, 0);
}
GLenum textarget, GLuint texture,
GLint level, GLint zoffset)
{
- struct gl_render_buffer_attachment *att;
+ struct gl_renderbuffer_attachment *att;
+ struct gl_texture_object *texObj;
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, attachment);
+ att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferTexture1DEXT(attachment)");
if (texture) {
const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
- struct gl_texture_object *texObj = (struct gl_texture_object *)
+ texObj = (struct gl_texture_object *)
_mesa_HashLookup(ctx->Shared->TexObjects, texture);
if (!texObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glFramebufferTexture3DEXT(zoffset)");
return;
}
- set_texture_attachment(ctx, att, texObj, textarget, level, zoffset);
}
else {
- remove_attachment(ctx, att);
+ /* remove texture attachment */
+ texObj = NULL;
}
+ ctx->Driver.RenderbufferTexture(ctx, att, texObj, textarget,
+ level, zoffset);
}
GLenum renderbufferTarget,
GLuint renderbuffer)
{
- struct gl_render_buffer_attachment *att;
+ struct gl_renderbuffer_attachment *att;
+ struct gl_renderbuffer *rb;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
if (target != GL_FRAMEBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
}
if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glFramebufferRenderbufferEXT(renderbufferTarget)");
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glFramebufferRenderbufferEXT(renderbufferTarget)");
return;
}
- if (ctx->CurrentFramebuffer == NULL) {
+ if (ctx->DrawBuffer->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
return;
}
- att = get_attachment(ctx, attachment);
+ att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(attachment)");
}
if (renderbuffer) {
- struct gl_render_buffer_object *rb;
rb = lookup_renderbuffer(ctx, renderbuffer);
if (!rb) {
- _mesa_error(ctx, GL_INVALID_VALUE,
+ _mesa_error(ctx, GL_INVALID_OPERATION,
"glFramebufferRenderbufferEXT(renderbuffer)");
return;
}
- set_renderbuffer_attachment(ctx, att, rb);
}
else {
- remove_attachment(ctx, att);
+ /* remove renderbuffer attachment */
+ rb = NULL;
}
+
+ assert(ctx->Driver.FramebufferRenderbuffer);
+ ctx->Driver.FramebufferRenderbuffer(ctx, att, rb);
+
+ _mesa_update_framebuffer_visual(ctx->DrawBuffer);
}
_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
GLenum pname, GLint *params)
{
- const struct gl_render_buffer_attachment *att;
+ const struct gl_renderbuffer_attachment *att;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
return;
}
- if (ctx->CurrentFramebuffer == NULL) {
+ if (ctx->DrawBuffer->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetFramebufferAttachmentParameterivEXT");
return;
}
- att = get_attachment(ctx, attachment);
+ att = get_attachment(ctx, ctx->DrawBuffer, attachment);
if (att == NULL) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glGetFramebufferAttachmentParameterivEXT(attachment)");
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP:
+ /* OK, legal value */
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)");