additional work on GL_EXT_framebuffer_object

This commit is contained in:
Brian Paul
2005-02-07 05:08:24 +00:00
parent 1e42244e82
commit 3deaa01c2b
9 changed files with 615 additions and 263 deletions

View File

@@ -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]);
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 */
}
/* 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]);
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 */
}
/* 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:
if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(renderbufferTarget)");
return;
}
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;
}
if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glFramebufferRenderbufferEXT(renderbufferTarget)");
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;
}