diff options
Diffstat (limited to 'src/mesa/main')
-rw-r--r-- | src/mesa/main/texrender.c | 246 |
1 files changed, 178 insertions, 68 deletions
diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c index 85565bfb1d4..db720cef6e0 100644 --- a/src/mesa/main/texrender.c +++ b/src/mesa/main/texrender.c @@ -22,7 +22,9 @@ struct texture_renderbuffer }; - +/** + * Get row of values from the renderbuffer that wraps a texture image. + */ static void texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, void *values) @@ -30,13 +32,31 @@ texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const struct texture_renderbuffer *trb = (const struct texture_renderbuffer *) rb; const GLint z = trb->Zoffset; - GLchan *rgbaOut = (GLchan *) values; GLuint i; - for (i = 0; i < count; i++) { - trb->TexImage->FetchTexelc(trb->TexImage, x + i, y, z, rgbaOut + 4 * i); + + ASSERT(trb->TexImage->Width == rb->Width); + ASSERT(trb->TexImage->Height == rb->Height); + + if (rb->DataType == CHAN_TYPE) { + GLchan *rgbaOut = (GLchan *) values; + for (i = 0; i < count; i++) { + trb->TexImage->FetchTexelc(trb->TexImage, x + i, y, z, rgbaOut + 4 * i); + } + } + else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { + GLuint *zValues = (GLuint *) values; + for (i = 0; i < count; i++) { + GLfloat flt; + trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt); + zValues[i] = ((GLuint) (flt * 0xffffff)) << 8; + } + } + else { + _mesa_problem(ctx, "invalid rb->DataType in texture_get_row"); } } + static void texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], void *values) @@ -44,14 +64,32 @@ texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const struct texture_renderbuffer *trb = (const struct texture_renderbuffer *) rb; const GLint z = trb->Zoffset; - GLchan *rgbaOut = (GLchan *) values; GLuint i; - for (i = 0; i < count; i++) { - trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i], z, - rgbaOut + 4 * i); + + if (rb->DataType == CHAN_TYPE) { + GLchan *rgbaOut = (GLchan *) values; + for (i = 0; i < count; i++) { + trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i], z, + rgbaOut + 4 * i); + } + } + else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { + GLuint *zValues = (GLuint *) values; + for (i = 0; i < count; i++) { + GLfloat flt; + trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i], z, &flt); + zValues[i] = ((GLuint) (flt * 0xffffff)) << 8; + } + } + else { + _mesa_problem(ctx, "invalid rb->DataType in texture_get_values"); } } + +/** + * Put row of values into a renderbuffer that wraps a texture image. + */ static void texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, const void *values, const GLubyte *mask) @@ -59,16 +97,32 @@ texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, 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); + + if (rb->DataType == CHAN_TYPE) { + const GLchan *rgba = (const GLchan *) values; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x + i, y, z, rgba); + } + rgba += 4; + } + } + else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { + const GLuint *zValues = (const GLuint *) values; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLfloat flt = (zValues[i] >> 8) * (1.0 / 0xffffff); + trb->Store(trb->TexImage, x + i, y, z, &flt); + } } - rgba += 4; + } + else { + _mesa_problem(ctx, "invalid rb->DataType in texture_put_row"); } } + static void texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, GLint x, GLint y, const void *value, const GLubyte *mask) @@ -76,15 +130,31 @@ texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, 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); + + if (rb->DataType == CHAN_TYPE) { + const GLchan *rgba = (const GLchan *) value; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x + i, y, z, rgba); + } + } + } + else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { + const GLuint zValue = *((const GLuint *) value); + const GLfloat flt = (zValue >> 8) * (1.0 / 0xffffff); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x + i, y, z, &flt); + } } } + else { + _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row"); + } } + static void texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], const void *values, @@ -93,16 +163,32 @@ texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, 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); + + if (rb->DataType == CHAN_TYPE) { + const GLchan *rgba = (const GLchan *) values; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x[i], y[i], z, rgba); + } + rgba += 4; + } + } + else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { + const GLuint *zValues = (const GLuint *) values; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLfloat flt = (zValues[i] >> 8) * (1.0 / 0xffffff); + trb->Store(trb->TexImage, x[i], y[i], z, &flt); + } } - rgba += 4; + } + else { + _mesa_problem(ctx, "invalid rb->DataType in texture_put_values"); } } + static void texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count, const GLint x[], const GLint y[], @@ -111,13 +197,28 @@ texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb, 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); + + if (rb->DataType == CHAN_TYPE) { + const GLchan *rgba = (const GLchan *) value; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x[i], y[i], z, rgba); + } + } + } + else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { + const GLuint zValue = *((const GLuint *) value); + const GLfloat flt = (zValue >> 8) * (1.0 / 0xffffff); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + trb->Store(trb->TexImage, x[i], y[i], z, &flt); + } } } + else { + _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values"); + } } @@ -130,10 +231,9 @@ delete_texture_wrapper(struct gl_renderbuffer *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. + * This function creates a renderbuffer object which wraps a texture image. + * The new renderbuffer is plugged into the given attachment point. + * This allows rendering into the texture as if it were a renderbuffer. */ static void wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) @@ -143,9 +243,6 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) ASSERT(att->Type == GL_TEXTURE); ASSERT(att->Renderbuffer == NULL); - /* - ASSERT(att->Complete); - */ trb = CALLOC_STRUCT(texture_renderbuffer); if (!trb) { @@ -153,48 +250,75 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) return; } + /* init base gl_renderbuffer fields */ _mesa_init_renderbuffer(&trb->Base, name); + /* plug in our texture_renderbuffer-specific functions */ + trb->Base.Delete = delete_texture_wrapper; + trb->Base.AllocStorage = NULL; /* illegal! */ + 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; + + /* update attachment point */ + att->Renderbuffer = &(trb->Base); +} + + + +/** + * Update the renderbuffer wrapper for rendering to a texture. + * For example, update the width, height of the RB based on the texture size, + * update the internal format info, etc. + */ +static void +update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att) +{ + struct texture_renderbuffer *trb + = (struct texture_renderbuffer *) att->Renderbuffer; + + ASSERT(trb); trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; - assert(trb->TexImage); + ASSERT(trb->TexImage); trb->Store = trb->TexImage->TexFormat->StoreTexel; - assert(trb->Store); + ASSERT(trb->Store); trb->Zoffset = att->Zoffset; trb->Base.Width = trb->TexImage->Width; trb->Base.Height = trb->TexImage->Height; - trb->Base.InternalFormat = trb->TexImage->InternalFormat; /* XXX fix? */ + trb->Base.InternalFormat = trb->TexImage->InternalFormat; + /* XXX may need more special cases here */ + if (trb->TexImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) { + trb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; + trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; + } + else if (trb->TexImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) { + trb->Base._ActualFormat = GL_DEPTH_COMPONENT; + trb->Base.DataType = GL_FLOAT; + } + else { + trb->Base._ActualFormat = trb->TexImage->InternalFormat; + trb->Base.DataType = CHAN_TYPE; + } trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat; #if 0 /* fix/avoid this assertion someday */ - assert(trb->Base._BaseFormat == GL_RGB || + ASSERT(trb->Base._BaseFormat == GL_RGB || trb->Base._BaseFormat == GL_RGBA || trb->Base._BaseFormat == GL_DEPTH_COMPONENT); #endif - 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! */ - - /* XXX fix these */ trb->Base.RedBits = trb->TexImage->TexFormat->RedBits; trb->Base.GreenBits = trb->TexImage->TexFormat->GreenBits; trb->Base.BlueBits = trb->TexImage->TexFormat->BlueBits; trb->Base.AlphaBits = trb->TexImage->TexFormat->AlphaBits; trb->Base.DepthBits = trb->TexImage->TexFormat->DepthBits; - - att->Renderbuffer = &(trb->Base); - trb->Base.RefCount++; } @@ -221,24 +345,10 @@ _mesa_render_texture(GLcontext *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { - struct gl_texture_image *newImage - = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; - struct texture_renderbuffer *trb - = (struct texture_renderbuffer *) att->Renderbuffer; - struct gl_texture_image *oldImage = trb ? trb->TexImage : NULL; - - (void) fb; - - ASSERT(newImage); - - if (oldImage != newImage) { - if (trb) { - /* get rid of old wrapper */ - /* XXX also if Zoffset changes? */ - trb->Base.Delete(&trb->Base); - } + if (!att->Renderbuffer) { wrap_texture(ctx, att); } + update_wrapper(ctx, att); } |