fix GL_ALPHA render-to-texture problem (Jon Smirl)
[mesa.git] / src / mesa / main / texrender.c
1
2 #include "context.h"
3 #include "fbobject.h"
4 #include "texrender.h"
5 #include "renderbuffer.h"
6
7
8 /*
9 * Render-to-texture code for GL_EXT_framebuffer_object
10 */
11
12
13 /**
14 * Derived from gl_renderbuffer class
15 */
16 struct texture_renderbuffer
17 {
18 struct gl_renderbuffer Base; /* Base class object */
19 struct gl_texture_image *TexImage;
20 StoreTexelFunc Store;
21 GLint Zoffset;
22 };
23
24
25
26 static void
27 texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
28 GLint x, GLint y, void *values)
29 {
30 /* XXX unfinished */
31 }
32
33 static void
34 texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
35 const GLint x[], const GLint y[], void *values)
36 {
37 /* XXX unfinished */
38 }
39
40 static void
41 texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
42 GLint x, GLint y, const void *values, const GLubyte *mask)
43 {
44 const struct texture_renderbuffer *trb
45 = (const struct texture_renderbuffer *) rb;
46 const GLint z = trb->Zoffset;
47 const GLchan *rgba = (const GLchan *) values;
48 GLuint i;
49 for (i = 0; i < count; i++) {
50 if (!mask || mask[i]) {
51 trb->Store(trb->TexImage, x + i, y, z, rgba);
52 }
53 rgba += 4;
54 }
55 }
56
57 static void
58 texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
59 GLint x, GLint y, const void *value, const GLubyte *mask)
60 {
61 const struct texture_renderbuffer *trb
62 = (const struct texture_renderbuffer *) rb;
63 const GLint z = trb->Zoffset;
64 const GLchan *rgba = (const GLchan *) value;
65 GLuint i;
66 for (i = 0; i < count; i++) {
67 if (!mask || mask[i]) {
68 trb->Store(trb->TexImage, x + i, y, z, rgba);
69 }
70 }
71 }
72
73 static void
74 texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
75 const GLint x[], const GLint y[], const void *values,
76 const GLubyte *mask)
77 {
78 const struct texture_renderbuffer *trb
79 = (const struct texture_renderbuffer *) rb;
80 const GLint z = trb->Zoffset;
81 const GLchan *rgba = (const GLchan *) values;
82 GLuint i;
83 for (i = 0; i < count; i++) {
84 if (!mask || mask[i]) {
85 trb->Store(trb->TexImage, x[i], y[i], z, rgba);
86 }
87 rgba += 4;
88 }
89 }
90
91 static void
92 texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb,
93 GLuint count, const GLint x[], const GLint y[],
94 const void *value, const GLubyte *mask)
95 {
96 const struct texture_renderbuffer *trb
97 = (const struct texture_renderbuffer *) rb;
98 const GLint z = trb->Zoffset;
99 const GLchan *rgba = (const GLchan *) value;
100 GLuint i;
101 for (i = 0; i < count; i++) {
102 if (!mask || mask[i]) {
103 trb->Store(trb->TexImage, x[i], y[i], z, rgba);
104 }
105 }
106 }
107
108
109 static void
110 delete_texture_wrapper(struct gl_renderbuffer *rb)
111 {
112 _mesa_free(rb);
113 }
114
115
116 /**
117 * If a render buffer attachment specifies a texture image, we'll use
118 * this function to make a gl_renderbuffer wrapper around the texture image.
119 * This allows other parts of Mesa to access the texture image as if it
120 * was a renderbuffer.
121 */
122 static void
123 wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
124 {
125 struct texture_renderbuffer *trb;
126 const GLuint name = 0;
127
128 ASSERT(att->Type == GL_TEXTURE);
129 ASSERT(att->Renderbuffer == NULL);
130 /*
131 ASSERT(att->Complete);
132 */
133
134 trb = CALLOC_STRUCT(texture_renderbuffer);
135 if (!trb) {
136 _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
137 return;
138 }
139
140 _mesa_init_renderbuffer(&trb->Base, name);
141
142 trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
143 assert(trb->TexImage);
144
145 trb->Store = trb->TexImage->TexFormat->StoreTexel;
146 assert(trb->Store);
147
148 trb->Zoffset = att->Zoffset;
149
150 trb->Base.Width = trb->TexImage->Width;
151 trb->Base.Height = trb->TexImage->Height;
152 trb->Base.InternalFormat = trb->TexImage->IntFormat; /* XXX fix? */
153 trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat;
154 #if 0
155 /* fix/avoid this assertion someday */
156 assert(trb->Base._BaseFormat == GL_RGB ||
157 trb->Base._BaseFormat == GL_RGBA ||
158 trb->Base._BaseFormat == GL_DEPTH_COMPONENT);
159 #endif
160 trb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix! */
161 trb->Base.Data = trb->TexImage->Data;
162
163 trb->Base.GetRow = texture_get_row;
164 trb->Base.GetValues = texture_get_values;
165 trb->Base.PutRow = texture_put_row;
166 trb->Base.PutMonoRow = texture_put_mono_row;
167 trb->Base.PutValues = texture_put_values;
168 trb->Base.PutMonoValues = texture_put_mono_values;
169
170 trb->Base.Delete = delete_texture_wrapper;
171 trb->Base.AllocStorage = NULL; /* illegal! */
172
173 att->Renderbuffer = &(trb->Base);
174 }
175
176
177
178 /**
179 * Software fallback for ctx->Driver.RenderbufferTexture.
180 * This is called via the glRenderbufferTexture1D/2D/3D() functions.
181 * If we're unbinding a texture, texObj will be NULL.
182 * The framebuffer of interest is ctx->DrawBuffer.
183 * \sa _mesa_framebuffer_renderbuffer
184 */
185 void
186 _mesa_renderbuffer_texture(GLcontext *ctx,
187 struct gl_renderbuffer_attachment *att,
188 struct gl_texture_object *texObj,
189 GLenum texTarget, GLuint level, GLuint zoffset)
190 {
191 if (texObj) {
192 _mesa_set_texture_attachment(ctx, att, texObj,
193 texTarget, level, zoffset);
194
195 wrap_texture(ctx, att);
196 }
197 else {
198 _mesa_remove_attachment(ctx, att);
199 }
200 }