#include "context.h"
#include "fbobject.h"
#include "texformat.h"
#include "texrender.h"
#include "renderbuffer.h"
struct texture_renderbuffer
{
struct gl_renderbuffer Base;
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)
{
const struct texture_renderbuffer *trb
= (const struct texture_renderbuffer *) rb;
const GLint z = trb->Zoffset;
GLuint 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) {
GLuint *zValues = (GLuint *) values;
for (i = 0; i < count; i++) {
GLfloat flt;
trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
#if 0
zValues[i] = (GLuint) (flt * scale);
#else
zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
#endif
}
}
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)
{
const struct texture_renderbuffer *trb
= (const struct texture_renderbuffer *) rb;
const GLint z = trb->Zoffset;
GLuint 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) {
GLuint *zValues = (GLuint *) values;
for (i = 0; i < count; i++) {
GLfloat flt;
trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i], z, &flt);
#if 0
zValues[i] = (GLuint) (flt * 0xffffffff);
#else
zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
#endif
}
}
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");
}
}
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;
GLuint i;
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) {
const GLuint *zValues = (const GLuint *) values;
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
trb->Store(trb->TexImage, x + i, y, z, zValues + i);
}
}
}
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);
}
}
}
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)
{
const struct texture_renderbuffer *trb
= (const struct texture_renderbuffer *) rb;
const GLint z = trb->Zoffset;
GLuint i;
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) {
const GLuint zValue = *((const GLuint *) value);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
trb->Store(trb->TexImage, x + i, y, z, &zValue);
}
}
}
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,
const GLubyte *mask)
{
const struct texture_renderbuffer *trb
= (const struct texture_renderbuffer *) rb;
const GLint z = trb->Zoffset;
GLuint i;
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) {
const GLuint *zValues = (const GLuint *) values;
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
trb->Store(trb->TexImage, x[i], y[i], z, zValues + i);
}
}
}
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);
}
}
}
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[],
const void *value, const GLubyte *mask)
{
const struct texture_renderbuffer *trb
= (const struct texture_renderbuffer *) rb;
const GLint z = trb->Zoffset;
GLuint i;
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) {
const GLuint zValue = *((const GLuint *) value);
for (i = 0; i < count; i++) {
if (!mask || mask[i]) {
trb->Store(trb->TexImage, x[i], y[i], z, &zValue);
}
}
}
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");
}
}
static void
delete_texture_wrapper(struct gl_renderbuffer *rb)
{
ASSERT(rb->RefCount == 0);
_mesa_free(rb);
}
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);
trb = CALLOC_STRUCT(texture_renderbuffer);
if (!trb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
return;
}
_mesa_init_renderbuffer(&trb->Base, name);
trb->Base.Delete = delete_texture_wrapper;
trb->Base.AllocStorage = NULL;
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;
_mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base));
}
static void
update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
{
struct texture_renderbuffer *trb
= (struct texture_renderbuffer *) att->Renderbuffer;
(void) ctx;
ASSERT(trb);
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->InternalFormat;
if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z24_S8) {
trb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
}
else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z16) {
trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
trb->Base.DataType = GL_UNSIGNED_SHORT;
}
else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z32) {
trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
trb->Base.DataType = GL_UNSIGNED_INT;
}
else {
trb->Base._ActualFormat = trb->TexImage->InternalFormat;
trb->Base.DataType = CHAN_TYPE;
}
trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat;
#if 0
ASSERT(trb->Base._BaseFormat == GL_RGB ||
trb->Base._BaseFormat == GL_RGBA ||
trb->Base._BaseFormat == GL_DEPTH_COMPONENT);
#endif
trb->Base.Data = trb->TexImage->Data;
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;
}
void
_mesa_render_texture(GLcontext *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
(void) fb;
if (!att->Renderbuffer) {
wrap_texture(ctx, att);
}
update_wrapper(ctx, att);
}
void
_mesa_finish_render_texture(GLcontext *ctx,
struct gl_renderbuffer_attachment *att)
{
(void) ctx;
(void) att;
}