diff options
Diffstat (limited to 'src/mesa/main/texrender.c')
-rw-r--r-- | src/mesa/main/texrender.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c new file mode 100644 index 00000000000..12afa93d01f --- /dev/null +++ b/src/mesa/main/texrender.c @@ -0,0 +1,197 @@ + +#include "context.h" +#include "fbobject.h" +#include "texrender.h" +#include "renderbuffer.h" + + +/* + * Render-to-texture code for GL_EXT_framebuffer_object + */ + + +/** + * Derived from gl_renderbuffer class + */ +struct texture_renderbuffer +{ + struct gl_renderbuffer Base; /* Base class object */ + struct gl_texture_image *TexImage; + StoreTexelFunc Store; + GLint Zoffset; +}; + + + +static void +texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, void *values) +{ + /* XXX unfinished */ +} + +static void +texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + /* XXX unfinished */ +} + +static void +texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) values; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x + i, y, z, rgba); + } + rgba += 4; + } +} + +static void +texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) value; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x + i, y, z, rgba); + } + } +} + +static void +texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, + const GLint x[], const GLint y[], const void *values, + const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) values; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x[i], y[i], z, rgba); + } + rgba += 4; + } +} + +static void +texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + const struct texture_renderbuffer *trb + = (const struct texture_renderbuffer *) rb; + const GLint z = trb->Zoffset; + const GLchan *rgba = (const GLchan *) value; + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x[i], y[i], z, rgba); + } + } +} + + +static void +delete_texture_wrapper(struct gl_renderbuffer *rb) +{ + _mesa_free(rb); +} + + +/** + * If a render buffer attachment specifies a texture image, we'll use + * this function to make a gl_renderbuffer wrapper around the texture image. + * This allows other parts of Mesa to access the texture image as if it + * was a renderbuffer. + */ +static void +wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) +{ + struct texture_renderbuffer *trb; + const GLuint name = 0; + + ASSERT(att->Type == GL_TEXTURE); + ASSERT(att->Renderbuffer == NULL); + /* + ASSERT(att->Complete); + */ + + trb = CALLOC_STRUCT(texture_renderbuffer); + if (!trb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture"); + return; + } + + _mesa_init_renderbuffer(&trb->Base, name); + + trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; + assert(trb->TexImage); + + trb->Store = trb->TexImage->TexFormat->StoreTexel; + assert(trb->Store); + + trb->Zoffset = att->Zoffset; + + trb->Base.Width = trb->TexImage->Width; + trb->Base.Height = trb->TexImage->Height; + trb->Base.InternalFormat = trb->TexImage->IntFormat; /* XXX fix? */ + trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat; + assert(trb->Base._BaseFormat == GL_RGB || + trb->Base._BaseFormat == GL_RGBA || + trb->Base._BaseFormat == GL_DEPTH_COMPONENT); + trb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix! */ + trb->Base.Data = trb->TexImage->Data; + + trb->Base.GetRow = texture_get_row; + trb->Base.GetValues = texture_get_values; + trb->Base.PutRow = texture_put_row; + trb->Base.PutMonoRow = texture_put_mono_row; + trb->Base.PutValues = texture_put_values; + trb->Base.PutMonoValues = texture_put_mono_values; + + trb->Base.Delete = delete_texture_wrapper; + trb->Base.AllocStorage = NULL; /* illegal! */ + + att->Renderbuffer = &(trb->Base); +} + + + +/** + * Software fallback for ctx->Driver.RenderbufferTexture. + * This is called via the glRenderbufferTexture1D/2D/3D() functions. + * If we're unbinding a texture, texObj will be NULL. + * The framebuffer of interest is ctx->DrawBuffer. + * \sa _mesa_framebuffer_renderbuffer + */ +void +_mesa_renderbuffer_texture(GLcontext *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset) +{ + if (texObj) { + _mesa_set_texture_attachment(ctx, att, texObj, + texTarget, level, zoffset); + + wrap_texture(ctx, att); + } + else { + _mesa_remove_attachment(ctx, att); + } +} |