From 2c6f911e10761c0946261d494bf149b19072821d Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 24 Feb 2005 05:47:06 +0000 Subject: [PATCH] More GL_EXT_framebuffer_object: rename some things, added device driver hooks. --- src/mesa/drivers/common/driverfuncs.c | 12 +- src/mesa/main/dd.h | 13 +- src/mesa/main/fbobject.c | 248 ++++++++++++++++++++++------------ src/mesa/main/fbobject.h | 112 +++++++++++++-- src/mesa/main/mtypes.h | 7 +- 5 files changed, 290 insertions(+), 102 deletions(-) diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c index 11b4e28..7ab5f48 100644 --- a/src/mesa/drivers/common/driverfuncs.c +++ b/src/mesa/drivers/common/driverfuncs.c @@ -2,7 +2,7 @@ * Mesa 3-D graphics library * Version: 6.3 * - * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -33,7 +33,12 @@ #include "teximage.h" #include "texobj.h" #include "texstore.h" +#if FEATURE_ARB_vertex_buffer_object #include "bufferobj.h" +#endif +#if FEATURE_EXT_framebuffer_object +#include "fbobject.h" +#endif #include "driverfuncs.h" #include "swrast/swrast.h" @@ -192,6 +197,11 @@ _mesa_init_driver_functions(struct dd_function_table *driver) driver->UnmapBuffer = _mesa_buffer_unmap; #endif +#if FEATURE_EXT_framebuffer_object + driver->NewFramebuffer = _mesa_new_framebuffer; + driver->NewRenderbuffer = _mesa_new_renderbuffer; +#endif + /* T&L stuff */ driver->NeedValidate = GL_FALSE; driver->ValidateTnlModule = NULL; diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index def5501..312631a 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -751,7 +751,7 @@ struct dd_function_table { /** - * \name Vertex buffer object functions + * \name Vertex/pixel buffer object functions */ #if FEATURE_ARB_vertex_buffer_object /*@{*/ @@ -784,6 +784,17 @@ struct dd_function_table { #endif /** + * \name Functions for GL_EXT_framebuffer_object + */ +#if FEATURE_EXT_framebuffer_object + /*@{*/ + struct gl_framebuffer * (*NewFramebuffer)(GLcontext *ctx, GLuint name); + struct gl_renderbuffer * (*NewRenderbuffer)(GLcontext *ctx, GLuint name); + /*@}*/ +#endif + + + /** * \name Support for multiple T&L engines */ /*@{*/ diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 45d578d..05ad155 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -51,8 +51,8 @@ * 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) \ @@ -61,50 +61,115 @@ static struct gl_render_buffer_object DummyRenderbuffer; /** - * 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. + * Allocate a new gl_framebuffer. + * This is the default function for ctx->Driver.NewFramebuffer(). */ -static struct gl_render_buffer_object * -new_renderbuffer(GLcontext *ctx, GLuint name) +struct gl_framebuffer * +_mesa_new_framebuffer(GLcontext *ctx, GLuint name) { - struct gl_render_buffer_object *rb = CALLOC_STRUCT(gl_render_buffer_object); + struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); + if (fb) { + fb->Name = name; + fb->RefCount = 1; + fb->Delete = _mesa_delete_framebuffer; + } + return fb; +} + + +/** + * Delete a gl_framebuffer. + * This is the default function for framebuffer->Delete(). + */ +void +_mesa_delete_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) +{ + (void) ctx; + _mesa_free(fb); +} + + +/** + * Allocate the actual storage for a renderbuffer with the given format + * and dimensions. + * This is the default function for gl_renderbuffer->AllocStorage(). + * All incoming parameters will have already been checked for errors. + * If memory allocate fails, the function must call + * _mesa_error(GL_OUT_OF_MEMORY) and then return. + * \return GL_TRUE for success, GL_FALSE for failure. + */ +static GLboolean +alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + /* First, free any existing storage */ + if (rb->Data) { + _mesa_free(rb->Data); + } + + /* Now, allocate new storage */ + rb->Data = _mesa_malloc(width * height * 4); /* XXX fix size! */ + if (rb->Data == NULL) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glRenderbufferStorageEXT"); + return GL_FALSE; + } + + /* We set these fields now if the allocation worked */ + rb->Width = width; + rb->Height = height; + rb->InternalFormat = internalFormat; + + return GL_TRUE; +} + + +/** + * Allocate a new gl_renderbuffer. + * This is the default function for ctx->Driver.NewRenderbuffer(). + */ +struct gl_renderbuffer * +_mesa_new_renderbuffer(GLcontext *ctx, GLuint name) +{ + struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); if (rb) { rb->Name = name; rb->RefCount = 1; + rb->Delete = _mesa_delete_renderbuffer; + rb->AllocStorage = alloc_renderbuffer_storage; /* other fields are zero */ } return rb; @@ -112,27 +177,26 @@ new_renderbuffer(GLcontext *ctx, GLuint name) /** - * Allocate a new gl_frame_buffer_object. - * XXX make this a device driver function. + * Delete a gl_framebuffer. + * This is the default function for framebuffer->Delete(). */ -static struct gl_frame_buffer_object * -new_framebuffer(GLcontext *ctx, GLuint name) +void +_mesa_delete_renderbuffer(GLcontext *ctx, struct gl_renderbuffer *rb) { - struct gl_frame_buffer_object *fb = CALLOC_STRUCT(gl_frame_buffer_object); - if (fb) { - fb->Name = name; - fb->RefCount = 1; + (void) ctx; + if (rb->Data) { + _mesa_free(rb->Data); } - return fb; + _mesa_free(rb); } /** * 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; @@ -157,11 +221,11 @@ get_attachment(GLcontext *ctx, GLenum attachment) if (i >= ctx->Const.MaxColorAttachments) { return NULL; } - return &ctx->CurrentFramebuffer->ColorAttachment[i]; + return &fb->ColorAttachment[i]; case GL_DEPTH_ATTACHMENT_EXT: - return &ctx->CurrentFramebuffer->DepthAttachment; + return &fb->DepthAttachment; case GL_STENCIL_ATTACHMENT_EXT: - return &ctx->CurrentFramebuffer->StencilAttachment; + return &fb->StencilAttachment; default: return NULL; } @@ -173,7 +237,7 @@ get_attachment(GLcontext *ctx, GLenum attachment) * point. Update reference counts, etc. */ static void -remove_attachment(GLcontext *ctx, struct gl_render_buffer_attachment *att) +remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att) { if (att->Type == GL_TEXTURE) { ASSERT(att->Texture); @@ -189,7 +253,7 @@ remove_attachment(GLcontext *ctx, struct gl_render_buffer_attachment *att) ASSERT(!att->Texture); att->Renderbuffer->RefCount--; if (att->Renderbuffer->RefCount == 0) { - _mesa_free(att->Renderbuffer); /* XXX driver free */ + att->Renderbuffer->Delete(ctx, att->Renderbuffer); } att->Renderbuffer = NULL; } @@ -204,7 +268,7 @@ remove_attachment(GLcontext *ctx, struct gl_render_buffer_attachment *att) */ static void set_texture_attachment(GLcontext *ctx, - struct gl_render_buffer_attachment *att, + struct gl_renderbuffer_attachment *att, struct gl_texture_object *texObj, GLenum texTarget, GLuint level, GLuint zoffset) { @@ -221,6 +285,11 @@ set_texture_attachment(GLcontext *ctx, 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. + */ } @@ -230,12 +299,13 @@ set_texture_attachment(GLcontext *ctx, */ static void set_renderbuffer_attachment(GLcontext *ctx, - struct gl_render_buffer_attachment *att, - struct gl_render_buffer_object *rb) + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb) { 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++; } @@ -249,7 +319,7 @@ set_renderbuffer_attachment(GLcontext *ctx, */ 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); @@ -335,7 +405,7 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format, */ static void test_framebuffer_completeness(GLcontext *ctx, - struct gl_frame_buffer_object *fb) + struct gl_framebuffer *fb) { GLint i; GLuint numImages, width, height; @@ -348,7 +418,7 @@ test_framebuffer_completeness(GLcontext *ctx, /* 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; + struct gl_renderbuffer_attachment *att; GLuint w, h; GLenum f; @@ -418,8 +488,8 @@ test_framebuffer_completeness(GLcontext *ctx, /* 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]); + struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->DrawBuffer[i]); if (att->Type == GL_NONE) { fb->Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; return; @@ -429,8 +499,8 @@ test_framebuffer_completeness(GLcontext *ctx, /* Check that the ReadBuffer is present */ if (fb->ReadBuffer != GL_NONE) { - struct gl_render_buffer_attachment *att - = get_attachment(ctx, fb->ReadBuffer); + struct gl_renderbuffer_attachment *att + = get_attachment(ctx, fb, fb->ReadBuffer); if (att->Type == GL_NONE) { fb->Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; return; @@ -448,7 +518,7 @@ test_framebuffer_completeness(GLcontext *ctx, GLboolean GLAPIENTRY _mesa_IsRenderbufferEXT(GLuint renderbuffer) { - const struct gl_render_buffer_object *rb; + const struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); @@ -461,7 +531,7 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer) 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); @@ -480,11 +550,12 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) } 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++; @@ -497,7 +568,7 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) if (oldRb) { oldRb->RefCount--; if (oldRb->RefCount == 0) { - _mesa_free(oldRb); /* XXX device driver function */ + oldRb->Delete(ctx, oldRb); } } @@ -516,8 +587,8 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) 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 */ @@ -529,7 +600,7 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) */ rb->RefCount--; if (rb->RefCount == 0) { - _mesa_free(rb); /* XXX call device driver function */ + rb->Delete(ctx, rb); } } } @@ -603,9 +674,9 @@ base_internal_format(GLcontext *ctx, GLenum internalFormat) 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: @@ -618,6 +689,7 @@ void GLAPIENTRY _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) { + struct gl_renderbuffer *rb; GLenum baseFormat; GET_CURRENT_CONTEXT(ctx); @@ -645,27 +717,33 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, 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; + + /* XXX if this renderbuffer is attached anywhere, invalidate attachment + * points??? + */ } @@ -709,7 +787,7 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) GLboolean GLAPIENTRY _mesa_IsFramebufferEXT(GLuint framebuffer) { - const struct gl_frame_buffer_object *fb; + const struct gl_framebuffer *fb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); @@ -722,7 +800,7 @@ _mesa_IsFramebufferEXT(GLuint framebuffer) void GLAPIENTRY _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) { - struct gl_frame_buffer_object *newFb, *oldFb; + struct gl_framebuffer *newFb, *oldFb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -741,7 +819,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) } 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; @@ -758,7 +836,7 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) if (oldFb) { oldFb->RefCount--; if (oldFb->RefCount == 0) { - _mesa_free(oldFb); /* XXX device driver function */ + oldFb->Delete(ctx, oldFb); } } @@ -777,8 +855,8 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) 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) { /* remove from hash table immediately, to free the ID */ @@ -790,7 +868,7 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) */ fb->RefCount--; if (fb->RefCount == 0) { - _mesa_free(fb); /* XXX call device driver function */ + fb->Delete(ctx, fb); } } } @@ -903,7 +981,7 @@ void GLAPIENTRY _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - struct gl_render_buffer_attachment *att; + struct gl_renderbuffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -914,7 +992,7 @@ _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, ASSERT(textarget == GL_TEXTURE_1D); - att = get_attachment(ctx, attachment); + att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture1DEXT(attachment)"); @@ -948,7 +1026,7 @@ void GLAPIENTRY _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - struct gl_render_buffer_attachment *att; + struct gl_renderbuffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -961,7 +1039,7 @@ _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, textarget == GL_TEXTURE_RECTANGLE_ARB || IS_CUBE_FACE(textarget)); - att = get_attachment(ctx, attachment); + att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture2DEXT(attachment)"); @@ -999,7 +1077,7 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) { - struct gl_render_buffer_attachment *att; + struct gl_renderbuffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -1010,7 +1088,7 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, ASSERT(textarget == GL_TEXTURE_3D); - att = get_attachment(ctx, attachment); + att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture1DEXT(attachment)"); @@ -1049,7 +1127,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbufferTarget, GLuint renderbuffer) { - struct gl_render_buffer_attachment *att; + struct gl_renderbuffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -1071,7 +1149,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, return; } - att = get_attachment(ctx, attachment); + att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(attachment)"); @@ -1079,7 +1157,7 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, } if (renderbuffer) { - struct gl_render_buffer_object *rb; + struct gl_renderbuffer *rb; rb = lookup_renderbuffer(ctx, renderbuffer); if (!rb) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1098,7 +1176,7 @@ void GLAPIENTRY _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); @@ -1115,7 +1193,7 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, return; } - att = get_attachment(ctx, attachment); + att = get_attachment(ctx, ctx->CurrentFramebuffer, attachment); if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferAttachmentParameterivEXT(attachment)"); diff --git a/src/mesa/main/fbobject.h b/src/mesa/main/fbobject.h index 3619d0a..0241da2 100644 --- a/src/mesa/main/fbobject.h +++ b/src/mesa/main/fbobject.h @@ -27,51 +27,138 @@ #define FBOBJECT_H -struct gl_render_buffer_object +/** + * A renderbuffer stores colors or depth values or stencil values. + * A framebuffer object will have a collection of these. + * Data are read/written to the buffer with a handful of Get/Put functions. + * + * Instances of this object are allocated with the Driver's NewRenderbuffer + * hook. Drivers will likely wrap this class inside a driver-specific + * class to simulate inheritance. + */ +struct gl_renderbuffer { - GLint RefCount; GLuint Name; + GLint RefCount; GLuint Width, Height; GLenum InternalFormat; GLenum _BaseFormat; /* Either GL_RGB, GL_RGBA, GL_DEPTH_COMPONENT or */ /* GL_STENCIL_INDEX. */ + + GLenum DataType; /* GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, etc */ GLvoid *Data; + + /* Delete this renderbuffer */ + void (*Delete)(GLcontext *ctx, struct gl_renderbuffer *rb); + + /* Allocate new storage for this renderbuffer */ + GLboolean (*AllocStorage)(GLcontext *ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height); + + /* Return a pointer to the element/pixel at (x,y). + * Should return NULL if the buffer memory can't be directly addressed. + */ + void *(*GetPointer)(struct gl_renderbuffer *rb, GLint x, GLint y); + + /* Get/Read a row of values. + * The values will be of format _BaseFormat and type DataType. + */ + void (*GetRow)(struct gl_renderbuffer *rb, + GLint x, GLint y, GLuint count, void *values); + + /* Get/Read values at arbitrary locations + * The values will be of format _BaseFormat and type DataType. + */ + void (*GetValues)(struct gl_renderbuffer *rb, + const GLint x[], const GLint y[], + GLuint count, void *values); + + /* Put/Write a row of values + * The values will be of format _BaseFormat and type DataType. + */ + void (*PutRow)(struct gl_renderbuffer *rb, + GLint x, GLint y, GLuint count, + const void *values, const GLubyte *maek); + + /* Put/Write values at arbitrary locations + * The values will be of format _BaseFormat and type DataType. + */ + void (*PutValues)(struct gl_renderbuffer *rb, + const GLint x[], const GLint y[], GLuint count, + const void *values, const GLubyte *mask); }; -struct gl_render_buffer_attachment +/** + * A renderbuffer attachment point points to either a texture object + * (and specifies a mipmap level, cube face or 3D texture slice) or + * points to a renderbuffer. + */ +struct gl_renderbuffer_attachment { GLenum Type; /* GL_NONE or GL_TEXTURE or GL_RENDERBUFFER_EXT */ + GLboolean Complete; + /* IF Type == GL_RENDERBUFFER_EXT: */ - struct gl_render_buffer_object *Renderbuffer; + struct gl_renderbuffer *Renderbuffer; + /* IF Type == GL_TEXTURE: */ struct gl_texture_object *Texture; GLuint TextureLevel; GLuint CubeMapFace; /* 0 .. 5, for cube map textures */ GLuint Zoffset; /* for 3D textures */ - GLboolean Complete; }; -struct gl_frame_buffer_object +/** + * A framebuffer object is basically a collection of rendering buffers. + * (Though, a rendering buffer might actually be a texture image.) + * All the renderbuffers/textures which we reference must have the same + * width and height (and meet a few other requirements) in order for the + * framebufffer object to be "complete". + * + * Instances of this object are allocated with the Driver's Newframebuffer + * hook. Drivers will likely wrap this class inside a driver-specific + * class to simulate inheritance. + */ +struct gl_framebuffer { - GLint RefCount; GLuint Name; + GLint RefCount; - GLenum Status; + GLenum Status; /* One of the GL_FRAMEBUFFER_(IN)COMPLETE_* tokens */ - struct gl_render_buffer_attachment ColorAttachment[MAX_COLOR_ATTACHMENTS]; - struct gl_render_buffer_attachment DepthAttachment; - struct gl_render_buffer_attachment StencilAttachment; + struct gl_renderbuffer_attachment ColorAttachment[MAX_COLOR_ATTACHMENTS]; + struct gl_renderbuffer_attachment DepthAttachment; + struct gl_renderbuffer_attachment StencilAttachment; /* In unextended OpenGL, these vars are part of the GL_COLOR_BUFFER * attribute group and GL_PIXEL attribute group, respectively. */ GLenum DrawBuffer[MAX_DRAW_BUFFERS]; GLenum ReadBuffer; + + GLuint _Width, _Height; + + /** Delete this framebuffer */ + void (*Delete)(GLcontext *ctx, struct gl_framebuffer *fb); }; +extern struct gl_framebuffer * +_mesa_new_framebuffer(GLcontext *ctx, GLuint name); + +extern void +_mesa_delete_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb); + +extern struct gl_renderbuffer * +_mesa_new_renderbuffer(GLcontext *ctx, GLuint name); + +extern void +_mesa_delete_renderbuffer(GLcontext *ctx, struct gl_renderbuffer *rb); + + extern GLboolean GLAPIENTRY _mesa_IsRenderbufferEXT(GLuint renderbuffer); @@ -89,7 +176,8 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); extern void GLAPIENTRY -_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params); +_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, + GLint *params); extern GLboolean GLAPIENTRY _mesa_IsFramebufferEXT(GLuint framebuffer); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 0292419..999fda7 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -94,7 +94,8 @@ /** - * Depth buffer data type. + * Used for storing intermediate depth buffer values. + * The actual depth/Z buffer might use 16 or 32-bit values. * * \note Must be 32-bits! */ @@ -2631,8 +2632,8 @@ struct __GLcontextRec /*@}*/ #if FEATURE_EXT_framebuffer_object - struct gl_frame_buffer_object *CurrentFramebuffer; - struct gl_render_buffer_object *CurrentRenderbuffer; + struct gl_framebuffer *CurrentFramebuffer; + struct gl_renderbuffer *CurrentRenderbuffer; #endif GLenum ErrorValue; /**< Last error code */ -- 2.7.4