Replace MESA_FORMAT_DEPTH_COMPONENT_FLOAT32 with 32-bit integer format.
[mesa.git] / src / mesa / main / texrender.c
1
2 #include "context.h"
3 #include "fbobject.h"
4 #include "texformat.h"
5 #include "texrender.h"
6 #include "renderbuffer.h"
7
8
9 /*
10 * Render-to-texture code for GL_EXT_framebuffer_object
11 */
12
13
14 /**
15 * Derived from gl_renderbuffer class
16 */
17 struct texture_renderbuffer
18 {
19 struct gl_renderbuffer Base; /* Base class object */
20 struct gl_texture_image *TexImage;
21 StoreTexelFunc Store;
22 GLint Zoffset;
23 };
24
25
26 /**
27 * Get row of values from the renderbuffer that wraps a texture image.
28 */
29 static void
30 texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
31 GLint x, GLint y, void *values)
32 {
33 const struct texture_renderbuffer *trb
34 = (const struct texture_renderbuffer *) rb;
35 const GLint z = trb->Zoffset;
36 GLuint i;
37
38 ASSERT(trb->TexImage->Width == rb->Width);
39 ASSERT(trb->TexImage->Height == rb->Height);
40
41 if (rb->DataType == CHAN_TYPE) {
42 GLchan *rgbaOut = (GLchan *) values;
43 for (i = 0; i < count; i++) {
44 trb->TexImage->FetchTexelc(trb->TexImage, x + i, y, z, rgbaOut + 4 * i);
45 }
46 }
47 else if (rb->DataType == GL_UNSIGNED_INT) {
48 GLuint *zValues = (GLuint *) values;
49 /*
50 const GLdouble scale = (GLdouble) 0xffffffff;
51 */
52 for (i = 0; i < count; i++) {
53 GLfloat flt;
54 trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
55 #if 0
56 /* this should work, but doesn't (overflow due to low precision) */
57 zValues[i] = (GLuint) (flt * scale);
58 #else
59 /* temporary hack */
60 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
61 #endif
62 }
63 }
64 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
65 GLuint *zValues = (GLuint *) values;
66 for (i = 0; i < count; i++) {
67 GLfloat flt;
68 trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
69 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
70 }
71 }
72 else {
73 _mesa_problem(ctx, "invalid rb->DataType in texture_get_row");
74 }
75 }
76
77
78 static void
79 texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
80 const GLint x[], const GLint y[], void *values)
81 {
82 const struct texture_renderbuffer *trb
83 = (const struct texture_renderbuffer *) rb;
84 const GLint z = trb->Zoffset;
85 GLuint i;
86
87 if (rb->DataType == CHAN_TYPE) {
88 GLchan *rgbaOut = (GLchan *) values;
89 for (i = 0; i < count; i++) {
90 trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i], z,
91 rgbaOut + 4 * i);
92 }
93 }
94 else if (rb->DataType == GL_UNSIGNED_INT) {
95 GLuint *zValues = (GLuint *) values;
96 for (i = 0; i < count; i++) {
97 GLfloat flt;
98 trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i], z, &flt);
99 #if 0
100 zValues[i] = (GLuint) (flt * 0xffffffff);
101 #else
102 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
103 #endif
104 }
105 }
106 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
107 GLuint *zValues = (GLuint *) values;
108 for (i = 0; i < count; i++) {
109 GLfloat flt;
110 trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i], z, &flt);
111 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
112 }
113 }
114 else {
115 _mesa_problem(ctx, "invalid rb->DataType in texture_get_values");
116 }
117 }
118
119
120 /**
121 * Put row of values into a renderbuffer that wraps a texture image.
122 */
123 static void
124 texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
125 GLint x, GLint y, const void *values, const GLubyte *mask)
126 {
127 const struct texture_renderbuffer *trb
128 = (const struct texture_renderbuffer *) rb;
129 const GLint z = trb->Zoffset;
130 GLuint i;
131
132 if (rb->DataType == CHAN_TYPE) {
133 const GLchan *rgba = (const GLchan *) values;
134 for (i = 0; i < count; i++) {
135 if (!mask || mask[i]) {
136 trb->Store(trb->TexImage, x + i, y, z, rgba);
137 }
138 rgba += 4;
139 }
140 }
141 else if (rb->DataType == GL_UNSIGNED_INT) {
142 const GLuint *zValues = (const GLuint *) values;
143 for (i = 0; i < count; i++) {
144 if (!mask || mask[i]) {
145 trb->Store(trb->TexImage, x + i, y, z, zValues + i);
146 }
147 }
148 }
149 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
150 const GLuint *zValues = (const GLuint *) values;
151 for (i = 0; i < count; i++) {
152 if (!mask || mask[i]) {
153 GLfloat flt = (zValues[i] >> 8) * (1.0 / 0xffffff);
154 trb->Store(trb->TexImage, x + i, y, z, &flt);
155 }
156 }
157 }
158 else {
159 _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
160 }
161 }
162
163
164 static void
165 texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
166 GLint x, GLint y, const void *value, const GLubyte *mask)
167 {
168 const struct texture_renderbuffer *trb
169 = (const struct texture_renderbuffer *) rb;
170 const GLint z = trb->Zoffset;
171 GLuint i;
172
173 if (rb->DataType == CHAN_TYPE) {
174 const GLchan *rgba = (const GLchan *) value;
175 for (i = 0; i < count; i++) {
176 if (!mask || mask[i]) {
177 trb->Store(trb->TexImage, x + i, y, z, rgba);
178 }
179 }
180 }
181 else if (rb->DataType == GL_UNSIGNED_INT) {
182 const GLuint zValue = *((const GLuint *) value);
183 for (i = 0; i < count; i++) {
184 if (!mask || mask[i]) {
185 trb->Store(trb->TexImage, x + i, y, z, &zValue);
186 }
187 }
188 }
189 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
190 const GLuint zValue = *((const GLuint *) value);
191 const GLfloat flt = (zValue >> 8) * (1.0 / 0xffffff);
192 for (i = 0; i < count; i++) {
193 if (!mask || mask[i]) {
194 trb->Store(trb->TexImage, x + i, y, z, &flt);
195 }
196 }
197 }
198 else {
199 _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row");
200 }
201 }
202
203
204 static void
205 texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
206 const GLint x[], const GLint y[], const void *values,
207 const GLubyte *mask)
208 {
209 const struct texture_renderbuffer *trb
210 = (const struct texture_renderbuffer *) rb;
211 const GLint z = trb->Zoffset;
212 GLuint i;
213
214 if (rb->DataType == CHAN_TYPE) {
215 const GLchan *rgba = (const GLchan *) values;
216 for (i = 0; i < count; i++) {
217 if (!mask || mask[i]) {
218 trb->Store(trb->TexImage, x[i], y[i], z, rgba);
219 }
220 rgba += 4;
221 }
222 }
223 else if (rb->DataType == GL_UNSIGNED_INT) {
224 const GLuint *zValues = (const GLuint *) values;
225 for (i = 0; i < count; i++) {
226 if (!mask || mask[i]) {
227 trb->Store(trb->TexImage, x[i], y[i], z, zValues + i);
228 }
229 }
230 }
231 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
232 const GLuint *zValues = (const GLuint *) values;
233 for (i = 0; i < count; i++) {
234 if (!mask || mask[i]) {
235 GLfloat flt = (zValues[i] >> 8) * (1.0 / 0xffffff);
236 trb->Store(trb->TexImage, x[i], y[i], z, &flt);
237 }
238 }
239 }
240 else {
241 _mesa_problem(ctx, "invalid rb->DataType in texture_put_values");
242 }
243 }
244
245
246 static void
247 texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb,
248 GLuint count, const GLint x[], const GLint y[],
249 const void *value, const GLubyte *mask)
250 {
251 const struct texture_renderbuffer *trb
252 = (const struct texture_renderbuffer *) rb;
253 const GLint z = trb->Zoffset;
254 GLuint i;
255
256 if (rb->DataType == CHAN_TYPE) {
257 const GLchan *rgba = (const GLchan *) value;
258 for (i = 0; i < count; i++) {
259 if (!mask || mask[i]) {
260 trb->Store(trb->TexImage, x[i], y[i], z, rgba);
261 }
262 }
263 }
264 else if (rb->DataType == GL_UNSIGNED_INT) {
265 const GLuint zValue = *((const GLuint *) value);
266 for (i = 0; i < count; i++) {
267 if (!mask || mask[i]) {
268 trb->Store(trb->TexImage, x[i], y[i], z, &zValue);
269 }
270 }
271 }
272 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
273 const GLuint zValue = *((const GLuint *) value);
274 const GLfloat flt = (zValue >> 8) * (1.0 / 0xffffff);
275 for (i = 0; i < count; i++) {
276 if (!mask || mask[i]) {
277 trb->Store(trb->TexImage, x[i], y[i], z, &flt);
278 }
279 }
280 }
281 else {
282 _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values");
283 }
284 }
285
286
287 static void
288 delete_texture_wrapper(struct gl_renderbuffer *rb)
289 {
290 ASSERT(rb->RefCount == 0);
291 _mesa_free(rb);
292 }
293
294
295 /**
296 * This function creates a renderbuffer object which wraps a texture image.
297 * The new renderbuffer is plugged into the given attachment point.
298 * This allows rendering into the texture as if it were a renderbuffer.
299 */
300 static void
301 wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
302 {
303 struct texture_renderbuffer *trb;
304 const GLuint name = 0;
305
306 ASSERT(att->Type == GL_TEXTURE);
307 ASSERT(att->Renderbuffer == NULL);
308
309 trb = CALLOC_STRUCT(texture_renderbuffer);
310 if (!trb) {
311 _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
312 return;
313 }
314
315 /* init base gl_renderbuffer fields */
316 _mesa_init_renderbuffer(&trb->Base, name);
317 /* plug in our texture_renderbuffer-specific functions */
318 trb->Base.Delete = delete_texture_wrapper;
319 trb->Base.AllocStorage = NULL; /* illegal! */
320 trb->Base.GetRow = texture_get_row;
321 trb->Base.GetValues = texture_get_values;
322 trb->Base.PutRow = texture_put_row;
323 trb->Base.PutMonoRow = texture_put_mono_row;
324 trb->Base.PutValues = texture_put_values;
325 trb->Base.PutMonoValues = texture_put_mono_values;
326
327 /* update attachment point */
328 att->Renderbuffer = &(trb->Base);
329 }
330
331
332
333 /**
334 * Update the renderbuffer wrapper for rendering to a texture.
335 * For example, update the width, height of the RB based on the texture size,
336 * update the internal format info, etc.
337 */
338 static void
339 update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
340 {
341 struct texture_renderbuffer *trb
342 = (struct texture_renderbuffer *) att->Renderbuffer;
343
344 (void) ctx;
345 ASSERT(trb);
346
347 trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
348 ASSERT(trb->TexImage);
349
350 trb->Store = trb->TexImage->TexFormat->StoreTexel;
351 ASSERT(trb->Store);
352
353 trb->Zoffset = att->Zoffset;
354
355 trb->Base.Width = trb->TexImage->Width;
356 trb->Base.Height = trb->TexImage->Height;
357 trb->Base.InternalFormat = trb->TexImage->InternalFormat;
358 /* XXX may need more special cases here */
359 if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z24_S8) {
360 trb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
361 trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
362 }
363 else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z16) {
364 trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
365 trb->Base.DataType = GL_UNSIGNED_SHORT;
366 }
367 else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z32) {
368 trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
369 trb->Base.DataType = GL_UNSIGNED_INT;
370 }
371 else {
372 trb->Base._ActualFormat = trb->TexImage->InternalFormat;
373 trb->Base.DataType = CHAN_TYPE;
374 }
375 trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat;
376 #if 0
377 /* fix/avoid this assertion someday */
378 ASSERT(trb->Base._BaseFormat == GL_RGB ||
379 trb->Base._BaseFormat == GL_RGBA ||
380 trb->Base._BaseFormat == GL_DEPTH_COMPONENT);
381 #endif
382 trb->Base.Data = trb->TexImage->Data;
383
384 trb->Base.RedBits = trb->TexImage->TexFormat->RedBits;
385 trb->Base.GreenBits = trb->TexImage->TexFormat->GreenBits;
386 trb->Base.BlueBits = trb->TexImage->TexFormat->BlueBits;
387 trb->Base.AlphaBits = trb->TexImage->TexFormat->AlphaBits;
388 trb->Base.DepthBits = trb->TexImage->TexFormat->DepthBits;
389 }
390
391
392
393 /**
394 * Called when rendering to a texture image begins, or when changing
395 * the dest mipmap level, cube face, etc.
396 * This is a fallback routine for software render-to-texture.
397 *
398 * Called via the glRenderbufferTexture1D/2D/3D() functions
399 * and elsewhere (such as glTexImage2D).
400 *
401 * The image we're rendering into is
402 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
403 * It'll never be NULL.
404 *
405 * \param fb the framebuffer object the texture is being bound to
406 * \param att the fb attachment point of the texture
407 *
408 * \sa _mesa_framebuffer_renderbuffer
409 */
410 void
411 _mesa_render_texture(GLcontext *ctx,
412 struct gl_framebuffer *fb,
413 struct gl_renderbuffer_attachment *att)
414 {
415 (void) fb;
416
417 if (!att->Renderbuffer) {
418 wrap_texture(ctx, att);
419 }
420 update_wrapper(ctx, att);
421 }
422
423
424 void
425 _mesa_finish_render_texture(GLcontext *ctx,
426 struct gl_renderbuffer_attachment *att)
427 {
428 /* do nothing */
429 /* The renderbuffer texture wrapper will get deleted by the
430 * normal mechanism for deleting renderbuffers.
431 */
432 (void) ctx;
433 (void) att;
434 }