blob: 12afa93d01f432c4b093febae4df7d267b043724 [file] [log] [blame]
#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);
}
}