diff options
Diffstat (limited to 'src/mesa/main/fbobject.c')
-rw-r--r-- | src/mesa/main/fbobject.c | 608 |
1 files changed, 395 insertions, 213 deletions
diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 99023759531..f5ddb37d349 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -28,80 +28,16 @@ #include "hash.h" -/* XXX these are temporary here! */ -#define GL_FRAMEBUFFER_EXT 0x8D40 -#define GL_RENDERBUFFER_EXT 0x8D41 -#define GL_STENCIL_INDEX_EXT 0x8D45 -#define GL_STENCIL_INDEX1_EXT 0x8D46 -#define GL_STENCIL_INDEX4_EXT 0x8D47 -#define GL_STENCIL_INDEX8_EXT 0x8D48 -#define GL_STENCIL_INDEX16_EXT 0x8D49 -#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 -#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 -#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 -#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 -#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 -#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 -#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 -#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 -#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 -#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 -#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 -#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 -#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA -#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB -#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC -#define GL_COLOR_ATTACHMENT13_EXT 0x8CED -#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE -#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF -#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 -#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 -#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 -#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC -#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD -#define GL_FRAMEBUFFER_STATUS_ERROR_EXT 0x8CDE -#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 -#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 -#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF -#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 -#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 - - -struct gl_render_buffer_object -{ - GLint RefCount; - GLuint Name; - - GLuint width, height; -}; - - -struct gl_frame_buffer_object -{ - GLint RefCount; - GLuint Name; - -}; - +#define IS_CUBE_FACE(TARGET) \ + ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \ + (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) /** * Helper routine for getting a gl_render_buffer_object. */ static struct gl_render_buffer_object * -LookupRenderbuffer(GLcontext *ctx, GLuint id) +lookup_renderbuffer(GLcontext *ctx, GLuint id) { struct gl_render_buffer_object *rb; @@ -118,7 +54,7 @@ LookupRenderbuffer(GLcontext *ctx, GLuint id) * Helper routine for getting a gl_frame_buffer_object. */ static struct gl_frame_buffer_object * -LookupFramebuffer(GLcontext *ctx, GLuint id) +lookup_framebuffer(GLcontext *ctx, GLuint id) { struct gl_frame_buffer_object *rb; @@ -136,12 +72,13 @@ LookupFramebuffer(GLcontext *ctx, GLuint id) * XXX make this a device driver function. */ static struct gl_render_buffer_object * -NewRenderBuffer(GLcontext *ctx, GLuint name) +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; } @@ -152,7 +89,7 @@ NewRenderBuffer(GLcontext *ctx, GLuint name) * XXX make this a device driver function. */ static struct gl_frame_buffer_object * -NewFrameBuffer(GLcontext *ctx, GLuint name) +new_framebuffer(GLcontext *ctx, GLuint name) { struct gl_frame_buffer_object *fb = CALLOC_STRUCT(gl_frame_buffer_object); if (fb) { @@ -163,6 +100,100 @@ NewFrameBuffer(GLcontext *ctx, GLuint name) } +static struct gl_render_buffer_attachment * +get_attachment(GLcontext *ctx, GLenum attachment) +{ + GLuint i; + + switch (attachment) { + case GL_COLOR_ATTACHMENT0_EXT: + case GL_COLOR_ATTACHMENT1_EXT: + case GL_COLOR_ATTACHMENT2_EXT: + case GL_COLOR_ATTACHMENT3_EXT: + case GL_COLOR_ATTACHMENT4_EXT: + case GL_COLOR_ATTACHMENT5_EXT: + case GL_COLOR_ATTACHMENT6_EXT: + case GL_COLOR_ATTACHMENT7_EXT: + case GL_COLOR_ATTACHMENT8_EXT: + case GL_COLOR_ATTACHMENT9_EXT: + case GL_COLOR_ATTACHMENT10_EXT: + case GL_COLOR_ATTACHMENT11_EXT: + case GL_COLOR_ATTACHMENT12_EXT: + case GL_COLOR_ATTACHMENT13_EXT: + case GL_COLOR_ATTACHMENT14_EXT: + case GL_COLOR_ATTACHMENT15_EXT: + i = attachment - GL_COLOR_ATTACHMENT0_EXT; + if (i >= ctx->Const.MaxColorAttachments) { + return NULL; + } + return &ctx->CurrentFramebuffer->ColorAttachment[i]; + case GL_DEPTH_ATTACHMENT_EXT: + return &ctx->CurrentFramebuffer->DepthAttachment; + case GL_STENCIL_ATTACHMENT_EXT: + return &ctx->CurrentFramebuffer->StencilAttachment; + default: + return NULL; + } +} + + +static void +remove_attachment(GLcontext *ctx, struct gl_render_buffer_attachment *att) +{ + if (att->Type == GL_TEXTURE) { + ASSERT(att->Texture); + ASSERT(!att->Renderbuffer); + att->Texture->RefCount--; + if (att->Texture->RefCount == 0) { + ctx->Driver.DeleteTexture(ctx, att->Texture); + } + att->Texture = NULL; + } + else if (att->Type == GL_RENDERBUFFER_EXT) { + ASSERT(att->Renderbuffer); + ASSERT(!att->Texture); + att->Renderbuffer->RefCount--; + if (att->Renderbuffer->RefCount == 0) { + _mesa_free(att->Renderbuffer); /* XXX driver free */ + } + att->Renderbuffer = NULL; + } + att->Type = GL_NONE; +} + + +static void +set_texture_attachment(GLcontext *ctx, + struct gl_render_buffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset) +{ + remove_attachment(ctx, att); + att->Type = GL_TEXTURE; + att->Texture = texObj; + att->TextureLevel = level; + if (IS_CUBE_FACE(texTarget)) { + att->CubeMapFace = texTarget - GL_TEXTURE_CUBE_MAP_POSITIVE_X; + } + else { + att->CubeMapFace = 0; + } + att->Zoffset = zoffset; + texObj->RefCount++; +} + + +static void +set_renderbuffer_attachment(GLcontext *ctx, + struct gl_render_buffer_attachment *att, + struct gl_render_buffer_object *rb) +{ + remove_attachment(ctx, att); + att->Type = GL_RENDERBUFFER_EXT; + att->Renderbuffer = rb; + rb->RefCount++; +} + GLboolean _mesa_IsRenderbufferEXT(GLuint renderbuffer) @@ -172,7 +203,7 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer) ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - rb = LookupRenderbuffer(ctx, renderbuffer); + rb = lookup_renderbuffer(ctx, renderbuffer); return rb ? GL_TRUE : GL_FALSE; } @@ -180,28 +211,39 @@ _mesa_IsRenderbufferEXT(GLuint renderbuffer) void _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) { - struct gl_render_buffer_object *rb; + struct gl_render_buffer_object *newRb, *oldRb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - switch (target) { - case GL_RENDERBUFFER_EXT: - break; - case GL_FRAMEBUFFER_EXT: - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)"); + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glBindRenderbufferEXT(target)"); return; } - rb = LookupRenderbuffer(ctx, renderbuffer); - if (!rb) { - _mesa_error(ctx, GL_INVALID_VALUE, "glIsRenderbufferEXT(renderbuffer)"); - return; + if (renderbuffer) { + newRb = lookup_renderbuffer(ctx, renderbuffer); + if (!newRb) { + /* create new renderbuffer object */ + newRb = new_renderbuffer(ctx, renderbuffer); + if (!newRb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); + return; + } + } + newRb->RefCount++; } + oldRb = ctx->CurrentRenderbuffer; + if (oldRb) { + oldRb->RefCount--; + if (oldRb->RefCount == 0) { + _mesa_free(oldRb); /* XXX device driver function */ + } + } + ctx->CurrentRenderbuffer = newRb; } @@ -214,19 +256,21 @@ _mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) ASSERT_OUTSIDE_BEGIN_END(ctx); for (i = 0; i < n; i++) { - struct gl_render_buffer_object *rb; - rb = LookupRenderbuffer(ctx, renderbuffers[i]); - if (rb) { - /* remove from hash table immediately, to free the ID */ - _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); - - /* But the object will not be freed until it's no longer bound in - * any context. - */ - rb->RefCount--; - if (rb->RefCount == 0) { - _mesa_free(rb); /* XXX call device driver function */ - } + if (renderbuffers[i]) { + struct gl_render_buffer_object *rb; + rb = lookup_renderbuffer(ctx, renderbuffers[i]); + if (rb) { + /* remove from hash table immediately, to free the ID */ + _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); + + /* But the object will not be freed until it's no longer bound in + * any context. + */ + rb->RefCount--; + if (rb->RefCount == 0) { + _mesa_free(rb); /* XXX call device driver function */ + } + } } } } @@ -254,7 +298,7 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) for (i = 0; i < n; i++) { struct gl_render_buffer_object *rb; GLuint name = first + i; - rb = NewRenderBuffer(ctx, name); + rb = new_renderbuffer(ctx, name); if (!rb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenRenderbuffersEXT"); return; @@ -270,7 +314,6 @@ _mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) } - void _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) @@ -300,7 +343,6 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, return; } - if (width > 0 /*value of MAX_RENDERBUFFER_SIZE_EXT*/) { _mesa_error(ctx, GL_INVALID_VALUE, "glRenderbufferStorageEXT(width)"); return; @@ -311,12 +353,9 @@ _mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, return; } - - } - void _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) { @@ -354,7 +393,6 @@ _mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) } - GLboolean _mesa_IsFramebufferEXT(GLuint framebuffer) { @@ -363,7 +401,7 @@ _mesa_IsFramebufferEXT(GLuint framebuffer) ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - fb = LookupFramebuffer(ctx, framebuffer); + fb = lookup_framebuffer(ctx, framebuffer); return fb ? GL_TRUE : GL_FALSE; } @@ -371,20 +409,39 @@ _mesa_IsFramebufferEXT(GLuint framebuffer) void _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) { + struct gl_frame_buffer_object *newFb, *oldFb; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - switch (target) { - case GL_FRAMEBUFFER_EXT: - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, + if (target != GL_FRAMEBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); return; } + if (framebuffer) { + newFb = lookup_framebuffer(ctx, framebuffer); + if (!newFb) { + /* create new framebuffer object */ + newFb = new_framebuffer(ctx, framebuffer); + if (!newFb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); + return; + } + } + newFb->RefCount++; + } + + oldFb = ctx->CurrentFramebuffer; + if (oldFb) { + oldFb->RefCount--; + if (oldFb->RefCount == 0) { + _mesa_free(oldFb); /* XXX device driver function */ + } + } + ctx->CurrentFramebuffer = newFb; } @@ -397,19 +454,21 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) ASSERT_OUTSIDE_BEGIN_END(ctx); for (i = 0; i < n; i++) { - struct gl_frame_buffer_object *fb; - fb = LookupFramebuffer(ctx, framebuffers[i]); - if (fb) { - /* remove from hash table immediately, to free the ID */ - _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); - - /* But the object will not be freed until it's no longer bound in - * any context. - */ - fb->RefCount--; - if (fb->RefCount == 0) { - _mesa_free(fb); /* XXX call device driver function */ - } + if (framebuffers[i]) { + struct gl_frame_buffer_object *fb; + fb = lookup_framebuffer(ctx, framebuffers[i]); + if (fb) { + /* remove from hash table immediately, to free the ID */ + _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); + + /* But the object will not be freed until it's no longer bound in + * any context. + */ + fb->RefCount--; + if (fb->RefCount == 0) { + _mesa_free(fb); /* XXX call device driver function */ + } + } } } } @@ -437,7 +496,7 @@ _mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) for (i = 0; i < n; i++) { struct gl_frame_buffer_object *fb; GLuint name = first + i; - fb = NewFrameBuffer(ctx, name); + fb = new_framebuffer(ctx, name); if (!fb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenFramebuffersEXT"); return; @@ -492,52 +551,51 @@ _mesa_CheckFramebufferStatusEXT(GLenum target) * \return GL_TRUE if any error, GL_FALSE otherwise */ static GLboolean -error_check_framebuffer_texture(GLcontext *ctx, - GLuint dims, GLenum target, GLenum attachment, - GLint level) +error_check_framebuffer_texture(GLcontext *ctx, GLuint dims, + GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) { + ASSERT(dims >= 1 && dims <= 3); + if (target != GL_FRAMEBUFFER_EXT) { _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferTexture%dDEXT(target)", dims); return GL_TRUE; } - switch (attachment) { - case GL_COLOR_ATTACHMENT0_EXT: - case GL_COLOR_ATTACHMENT1_EXT: - case GL_COLOR_ATTACHMENT2_EXT: - case GL_COLOR_ATTACHMENT3_EXT: - case GL_COLOR_ATTACHMENT4_EXT: - case GL_COLOR_ATTACHMENT5_EXT: - case GL_COLOR_ATTACHMENT6_EXT: - case GL_COLOR_ATTACHMENT7_EXT: - case GL_COLOR_ATTACHMENT8_EXT: - case GL_COLOR_ATTACHMENT9_EXT: - case GL_COLOR_ATTACHMENT10_EXT: - case GL_COLOR_ATTACHMENT11_EXT: - case GL_COLOR_ATTACHMENT12_EXT: - case GL_COLOR_ATTACHMENT13_EXT: - case GL_COLOR_ATTACHMENT14_EXT: - case GL_COLOR_ATTACHMENT15_EXT: - case GL_DEPTH_ATTACHMENT_EXT: - case GL_STENCIL_ATTACHMENT_EXT: - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture%dDEXT(level)", dims); + if (ctx->CurrentFramebuffer == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture%dDEXT", dims); return GL_TRUE; } - if (level < 0 /* || level too large */) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%dDEXT(level)", dims); - return GL_TRUE; - } + /* 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) || + (dims == 2 && textarget != GL_TEXTURE_2D && + textarget != GL_TEXTURE_RECTANGLE_ARB && + !IS_CUBE_FACE(textarget))) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%dDEXT(textarget)", dims); + return GL_TRUE; + } - if (target == GL_TEXTURE_RECTANGLE_ARB && level != 0) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%dDEXT(level)", dims); - return GL_TRUE; + if ((level < 0) + || (textarget == GL_TEXTURE_1D + && level >= ctx->Const.MaxTextureLevels) + || (textarget == GL_TEXTURE_2D + && level >= ctx->Const.MaxTextureLevels) + || (textarget == GL_TEXTURE_3D + && level >= ctx->Const.Max3DTextureLevels) + || (textarget == GL_TEXTURE_RECTANGLE_ARB + && level != 0) + || (IS_CUBE_FACE(textarget) + && level >= ctx->Const.MaxCubeTextureLevels)) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%dDEXT(level)", dims); + return GL_TRUE; + } } return GL_FALSE; @@ -548,13 +606,44 @@ void _mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + struct gl_render_buffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (error_check_framebuffer_texture(ctx, 1, target, attachment, level)) + if (error_check_framebuffer_texture(ctx, 1, target, attachment, + textarget, texture, level)) return; + ASSERT(textarget == GL_TEXTURE_1D); + + att = get_attachment(ctx, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture1DEXT(attachment)"); + return; + } + + if (texture) { + 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)"); + return; + } + if (texObj->Target != textarget) { + _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ + "glFramebufferTexture1DEXT(texture target)"); + return; + } + set_texture_attachment(ctx, att, texObj, textarget, level, 0); + } + else { + remove_attachment(ctx, att); + } + + /* XXX call a driver function to signal new attachment? */ } @@ -562,12 +651,49 @@ void _mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + struct gl_render_buffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (error_check_framebuffer_texture(ctx, 1, target, attachment, level)) + if (error_check_framebuffer_texture(ctx, 2, target, attachment, + textarget, texture, level)) + return; + + ASSERT(textarget == GL_TEXTURE_2D || + textarget == GL_TEXTURE_RECTANGLE_ARB || + IS_CUBE_FACE(textarget)); + + att = get_attachment(ctx, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture2DEXT(attachment)"); return; + } + + if (texture) { + 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)"); + return; + } + if ((texObj->Target == GL_TEXTURE_2D && textarget != GL_TEXTURE_2D) || + (texObj->Target == GL_TEXTURE_RECTANGLE_ARB + && textarget != GL_TEXTURE_RECTANGLE_ARB) || + (texObj->Target == GL_TEXTURE_CUBE_MAP + && !IS_CUBE_FACE(textarget))) { + _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ + "glFramebufferTexture2DEXT(texture target)"); + return; + } + set_texture_attachment(ctx, att, texObj, textarget, level, 0); + } + else { + remove_attachment(ctx, att); + } + } @@ -576,14 +702,47 @@ _mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) { + struct gl_render_buffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); - if (error_check_framebuffer_texture(ctx, 1, target, attachment, level)) + if (error_check_framebuffer_texture(ctx, 3, target, attachment, + textarget, texture, level)) return; - /* check that zoffset isn't too large */ + ASSERT(textarget == GL_TEXTURE_3D); + + att = get_attachment(ctx, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture1DEXT(attachment)"); + return; + } + + if (texture) { + struct gl_texture_object *texObj = (struct gl_texture_object *) + _mesa_HashLookup(ctx->Shared->TexObjects, texture); + if (!texObj) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture3DEXT(texture)"); + return; + } + if (texObj->Target != textarget) { + _mesa_error(ctx, GL_INVALID_OPERATION, /* XXX correct error? */ + "glFramebufferTexture3DEXT(texture target)"); + return; + } + if (zoffset >= texObj->Image[0][level]->Depth) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture3DEXT(zoffset)"); + return; + } + set_texture_attachment(ctx, att, texObj, textarget, level, zoffset); + } + else { + remove_attachment(ctx, att); + } } @@ -593,6 +752,8 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbufferTarget, GLuint renderbuffer) { + struct gl_render_buffer_object *rb; + struct gl_render_buffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -603,39 +764,38 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, return; } - switch (attachment) { - case GL_COLOR_ATTACHMENT0_EXT: - case GL_COLOR_ATTACHMENT1_EXT: - case GL_COLOR_ATTACHMENT2_EXT: - case GL_COLOR_ATTACHMENT3_EXT: - case GL_COLOR_ATTACHMENT4_EXT: - case GL_COLOR_ATTACHMENT5_EXT: - case GL_COLOR_ATTACHMENT6_EXT: - case GL_COLOR_ATTACHMENT7_EXT: - case GL_COLOR_ATTACHMENT8_EXT: - case GL_COLOR_ATTACHMENT9_EXT: - case GL_COLOR_ATTACHMENT10_EXT: - case GL_COLOR_ATTACHMENT11_EXT: - case GL_COLOR_ATTACHMENT12_EXT: - case GL_COLOR_ATTACHMENT13_EXT: - case GL_COLOR_ATTACHMENT14_EXT: - case GL_COLOR_ATTACHMENT15_EXT: - case GL_DEPTH_ATTACHMENT_EXT: - case GL_STENCIL_ATTACHMENT_EXT: - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbufferEXT(attachment)"); + if (renderbufferTarget != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(renderbufferTarget)"); return; } - if (renderbufferTarget != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbufferEXT(renderbufferTarget)"); + if (ctx->CurrentFramebuffer == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); return; } + if (renderbuffer) { + rb = lookup_renderbuffer(ctx, renderbuffer); + if (!rb) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferRenderbufferEXT(renderbuffer)"); + return; + } + } + else { + rb = NULL; /* default renderbuffer */ + } + + att = get_attachment(ctx, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(attachment)"); + return; + } + remove_attachment(ctx, att); + set_renderbuffer_attachment(ctx, att, rb); } @@ -644,6 +804,7 @@ void _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) { + const struct gl_render_buffer_attachment *att; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -654,27 +815,14 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, return; } - switch (attachment) { - case GL_COLOR_ATTACHMENT0_EXT: - case GL_COLOR_ATTACHMENT1_EXT: - case GL_COLOR_ATTACHMENT2_EXT: - case GL_COLOR_ATTACHMENT3_EXT: - case GL_COLOR_ATTACHMENT4_EXT: - case GL_COLOR_ATTACHMENT5_EXT: - case GL_COLOR_ATTACHMENT6_EXT: - case GL_COLOR_ATTACHMENT7_EXT: - case GL_COLOR_ATTACHMENT8_EXT: - case GL_COLOR_ATTACHMENT9_EXT: - case GL_COLOR_ATTACHMENT10_EXT: - case GL_COLOR_ATTACHMENT11_EXT: - case GL_COLOR_ATTACHMENT12_EXT: - case GL_COLOR_ATTACHMENT13_EXT: - case GL_COLOR_ATTACHMENT14_EXT: - case GL_COLOR_ATTACHMENT15_EXT: - case GL_DEPTH_ATTACHMENT_EXT: - case GL_STENCIL_ATTACHMENT_EXT: - break; - default: + if (ctx->CurrentFramebuffer == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferAttachmentParameterivEXT"); + return; + } + + att = get_attachment(ctx, attachment); + if (att == NULL) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferAttachmentParameterivEXT(attachment)"); return; @@ -682,18 +830,52 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, switch (pname) { case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: + *params = att->Type; + return; case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: + if (att->Type == GL_RENDERBUFFER_EXT) { + *params = att->Renderbuffer->Name; + } + else if (att->Type == GL_TEXTURE) { + *params = att->Texture->Name; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: + if (att->Type == GL_TEXTURE) { + *params = att->TextureLevel; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: + if (att->Type == GL_TEXTURE) { + *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: - break; + if (att->Type == GL_TEXTURE) { + *params = att->Zoffset; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetFramebufferAttachmentParameterivEXT(pname)"); return; } - - *params = 0; } |