summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/texrender.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/texrender.c')
-rw-r--r--src/mesa/main/texrender.c197
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);
+ }
+}