mesa: Remove unnecessary header.
[mesa.git] / src / mesa / main / texrender.c
1
2 #include "context.h"
3 #include "colormac.h"
4 #include "texfetch.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 Yoffset; /**< Layer for 1D array textures. */
23 GLint Zoffset; /**< Layer for 2D array textures, or slice
24 * for 3D textures
25 */
26 };
27
28
29 /**
30 * Get row of values from the renderbuffer that wraps a texture image.
31 */
32 static void
33 texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
34 GLint x, GLint y, void *values)
35 {
36 const struct texture_renderbuffer *trb
37 = (const struct texture_renderbuffer *) rb;
38 const GLint z = trb->Zoffset;
39 GLuint i;
40
41 ASSERT(trb->TexImage->Width == rb->Width);
42 ASSERT(trb->TexImage->Height == rb->Height);
43
44 y += trb->Yoffset;
45
46 if (rb->DataType == CHAN_TYPE) {
47 GLchan *rgbaOut = (GLchan *) values;
48 for (i = 0; i < count; i++) {
49 GLfloat rgba[4];
50 trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, rgba);
51 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
52 }
53 }
54 else if (rb->DataType == GL_UNSIGNED_SHORT) {
55 GLushort *zValues = (GLushort *) values;
56 for (i = 0; i < count; i++) {
57 GLfloat flt;
58 trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
59 zValues[i] = (GLushort) (flt * 0xffff);
60 }
61 }
62 else if (rb->DataType == GL_UNSIGNED_INT) {
63 GLuint *zValues = (GLuint *) values;
64 /*
65 const GLdouble scale = (GLdouble) 0xffffffff;
66 */
67 for (i = 0; i < count; i++) {
68 GLfloat flt;
69 trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
70 #if 0
71 /* this should work, but doesn't (overflow due to low precision) */
72 zValues[i] = (GLuint) (flt * scale);
73 #else
74 /* temporary hack */
75 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
76 #endif
77 }
78 }
79 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
80 GLuint *zValues = (GLuint *) values;
81 for (i = 0; i < count; i++) {
82 GLfloat flt;
83 trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
84 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
85 }
86 }
87 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
88 GLuint *zValues = (GLuint *) values;
89 for (i = 0; i < count; i++) {
90 GLfloat flt;
91 trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
92 zValues[i] = (GLuint) (flt * 0xffffff);
93 }
94 }
95 else {
96 _mesa_problem(ctx, "invalid rb->DataType in texture_get_row");
97 }
98 }
99
100
101 static void
102 texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
103 const GLint x[], const GLint y[], void *values)
104 {
105 const struct texture_renderbuffer *trb
106 = (const struct texture_renderbuffer *) rb;
107 const GLint z = trb->Zoffset;
108 GLuint i;
109
110 if (rb->DataType == CHAN_TYPE) {
111 GLchan *rgbaOut = (GLchan *) values;
112 for (i = 0; i < count; i++) {
113 GLfloat rgba[4];
114 trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
115 z, rgba);
116 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
117 }
118 }
119 else if (rb->DataType == GL_UNSIGNED_SHORT) {
120 GLushort *zValues = (GLushort *) values;
121 for (i = 0; i < count; i++) {
122 GLfloat flt;
123 trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
124 z, &flt);
125 zValues[i] = (GLushort) (flt * 0xffff);
126 }
127 }
128 else if (rb->DataType == GL_UNSIGNED_INT) {
129 GLuint *zValues = (GLuint *) values;
130 for (i = 0; i < count; i++) {
131 GLfloat flt;
132 trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
133 z, &flt);
134 #if 0
135 zValues[i] = (GLuint) (flt * 0xffffffff);
136 #else
137 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
138 #endif
139 }
140 }
141 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
142 GLuint *zValues = (GLuint *) values;
143 for (i = 0; i < count; i++) {
144 GLfloat flt;
145 trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
146 z, &flt);
147 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
148 }
149 }
150 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
151 GLuint *zValues = (GLuint *) values;
152 for (i = 0; i < count; i++) {
153 GLfloat flt;
154 trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
155 z, &flt);
156 zValues[i] = (GLuint) (flt * 0xffffff);
157 }
158 }
159 else {
160 _mesa_problem(ctx, "invalid rb->DataType in texture_get_values");
161 }
162 }
163
164
165 /**
166 * Put row of values into a renderbuffer that wraps a texture image.
167 */
168 static void
169 texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
170 GLint x, GLint y, const void *values, const GLubyte *mask)
171 {
172 const struct texture_renderbuffer *trb
173 = (const struct texture_renderbuffer *) rb;
174 const GLint z = trb->Zoffset;
175 GLuint i;
176
177 y += trb->Yoffset;
178
179 if (rb->DataType == CHAN_TYPE) {
180 const GLchan *rgba = (const GLchan *) values;
181 for (i = 0; i < count; i++) {
182 if (!mask || mask[i]) {
183 trb->Store(trb->TexImage, x + i, y, z, rgba);
184 }
185 rgba += 4;
186 }
187 }
188 else if (rb->DataType == GL_UNSIGNED_SHORT) {
189 const GLushort *zValues = (const GLushort *) values;
190 for (i = 0; i < count; i++) {
191 if (!mask || mask[i]) {
192 trb->Store(trb->TexImage, x + i, y, z, zValues + i);
193 }
194 }
195 }
196 else if (rb->DataType == GL_UNSIGNED_INT) {
197 const GLuint *zValues = (const GLuint *) values;
198 for (i = 0; i < count; i++) {
199 if (!mask || mask[i]) {
200 trb->Store(trb->TexImage, x + i, y, z, zValues + i);
201 }
202 }
203 }
204 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
205 const GLuint *zValues = (const GLuint *) values;
206 for (i = 0; i < count; i++) {
207 if (!mask || mask[i]) {
208 GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
209 trb->Store(trb->TexImage, x + i, y, z, &flt);
210 }
211 }
212 }
213 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
214 const GLuint *zValues = (const GLuint *) values;
215 for (i = 0; i < count; i++) {
216 if (!mask || mask[i]) {
217 GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
218 trb->Store(trb->TexImage, x + i, y, z, &flt);
219 }
220 }
221 }
222 else {
223 _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
224 }
225 }
226
227 /**
228 * Put row of RGB values into a renderbuffer that wraps a texture image.
229 */
230 static void
231 texture_put_row_rgb(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
232 GLint x, GLint y, const void *values, const GLubyte *mask)
233 {
234 const struct texture_renderbuffer *trb
235 = (const struct texture_renderbuffer *) rb;
236 const GLint z = trb->Zoffset;
237 GLuint i;
238
239 y += trb->Yoffset;
240
241 if (rb->DataType == CHAN_TYPE) {
242 const GLchan *rgb = (const GLchan *) values;
243 for (i = 0; i < count; i++) {
244 if (!mask || mask[i]) {
245 trb->Store(trb->TexImage, x + i, y, z, rgb);
246 }
247 rgb += 3;
248 }
249 }
250 else if (rb->DataType == GL_UNSIGNED_SHORT) {
251 const GLushort *zValues = (const GLushort *) values;
252 for (i = 0; i < count; i++) {
253 if (!mask || mask[i]) {
254 trb->Store(trb->TexImage, x + i, y, z, zValues + i);
255 }
256 }
257 }
258 else if (rb->DataType == GL_UNSIGNED_INT) {
259 const GLuint *zValues = (const GLuint *) values;
260 for (i = 0; i < count; i++) {
261 if (!mask || mask[i]) {
262 trb->Store(trb->TexImage, x + i, y, z, zValues + i);
263 }
264 }
265 }
266 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
267 const GLuint *zValues = (const GLuint *) values;
268 for (i = 0; i < count; i++) {
269 if (!mask || mask[i]) {
270 GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
271 trb->Store(trb->TexImage, x + i, y, z, &flt);
272 }
273 }
274 }
275 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
276 const GLuint *zValues = (const GLuint *) values;
277 for (i = 0; i < count; i++) {
278 if (!mask || mask[i]) {
279 GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
280 trb->Store(trb->TexImage, x + i, y, z, &flt);
281 }
282 }
283 }
284 else {
285 _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
286 }
287 }
288
289
290 static void
291 texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
292 GLint x, GLint y, const void *value, const GLubyte *mask)
293 {
294 const struct texture_renderbuffer *trb
295 = (const struct texture_renderbuffer *) rb;
296 const GLint z = trb->Zoffset;
297 GLuint i;
298
299 y += trb->Yoffset;
300
301 if (rb->DataType == CHAN_TYPE) {
302 const GLchan *rgba = (const GLchan *) value;
303 for (i = 0; i < count; i++) {
304 if (!mask || mask[i]) {
305 trb->Store(trb->TexImage, x + i, y, z, rgba);
306 }
307 }
308 }
309 else if (rb->DataType == GL_UNSIGNED_SHORT) {
310 const GLushort zValue = *((const GLushort *) value);
311 for (i = 0; i < count; i++) {
312 if (!mask || mask[i]) {
313 trb->Store(trb->TexImage, x + i, y, z, &zValue);
314 }
315 }
316 }
317 else if (rb->DataType == GL_UNSIGNED_INT) {
318 const GLuint zValue = *((const GLuint *) value);
319 for (i = 0; i < count; i++) {
320 if (!mask || mask[i]) {
321 trb->Store(trb->TexImage, x + i, y, z, &zValue);
322 }
323 }
324 }
325 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
326 const GLuint zValue = *((const GLuint *) value);
327 const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
328 for (i = 0; i < count; i++) {
329 if (!mask || mask[i]) {
330 trb->Store(trb->TexImage, x + i, y, z, &flt);
331 }
332 }
333 }
334 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
335 const GLuint zValue = *((const GLuint *) value);
336 const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff));
337 for (i = 0; i < count; i++) {
338 if (!mask || mask[i]) {
339 trb->Store(trb->TexImage, x + i, y, z, &flt);
340 }
341 }
342 }
343 else {
344 _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row");
345 }
346 }
347
348
349 static void
350 texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
351 const GLint x[], const GLint y[], const void *values,
352 const GLubyte *mask)
353 {
354 const struct texture_renderbuffer *trb
355 = (const struct texture_renderbuffer *) rb;
356 const GLint z = trb->Zoffset;
357 GLuint i;
358
359 if (rb->DataType == CHAN_TYPE) {
360 const GLchan *rgba = (const GLchan *) values;
361 for (i = 0; i < count; i++) {
362 if (!mask || mask[i]) {
363 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
364 }
365 rgba += 4;
366 }
367 }
368 else if (rb->DataType == GL_UNSIGNED_SHORT) {
369 const GLushort *zValues = (const GLushort *) values;
370 for (i = 0; i < count; i++) {
371 if (!mask || mask[i]) {
372 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
373 }
374 }
375 }
376 else if (rb->DataType == GL_UNSIGNED_INT) {
377 const GLuint *zValues = (const GLuint *) values;
378 for (i = 0; i < count; i++) {
379 if (!mask || mask[i]) {
380 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
381 }
382 }
383 }
384 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
385 const GLuint *zValues = (const GLuint *) values;
386 for (i = 0; i < count; i++) {
387 if (!mask || mask[i]) {
388 GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
389 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
390 }
391 }
392 }
393 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
394 const GLuint *zValues = (const GLuint *) values;
395 for (i = 0; i < count; i++) {
396 if (!mask || mask[i]) {
397 GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
398 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
399 }
400 }
401 }
402 else {
403 _mesa_problem(ctx, "invalid rb->DataType in texture_put_values");
404 }
405 }
406
407
408 static void
409 texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb,
410 GLuint count, const GLint x[], const GLint y[],
411 const void *value, const GLubyte *mask)
412 {
413 const struct texture_renderbuffer *trb
414 = (const struct texture_renderbuffer *) rb;
415 const GLint z = trb->Zoffset;
416 GLuint i;
417
418 if (rb->DataType == CHAN_TYPE) {
419 const GLchan *rgba = (const GLchan *) value;
420 for (i = 0; i < count; i++) {
421 if (!mask || mask[i]) {
422 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
423 }
424 }
425 }
426 else if (rb->DataType == GL_UNSIGNED_INT) {
427 const GLuint zValue = *((const GLuint *) value);
428 for (i = 0; i < count; i++) {
429 if (!mask || mask[i]) {
430 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
431 }
432 }
433 }
434 else if (rb->DataType == GL_UNSIGNED_SHORT) {
435 const GLushort zValue = *((const GLushort *) value);
436 for (i = 0; i < count; i++) {
437 if (!mask || mask[i]) {
438 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
439 }
440 }
441 }
442 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
443 const GLuint zValue = *((const GLuint *) value);
444 const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
445 for (i = 0; i < count; i++) {
446 if (!mask || mask[i]) {
447 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
448 }
449 }
450 }
451 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
452 const GLuint zValue = *((const GLuint *) value);
453 const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff));
454 for (i = 0; i < count; i++) {
455 if (!mask || mask[i]) {
456 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
457 }
458 }
459 }
460 else {
461 _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values");
462 }
463 }
464
465
466 static void
467 store_nop(struct gl_texture_image *texImage,
468 GLint col, GLint row, GLint img,
469 const void *texel)
470 {
471 }
472
473
474 static void
475 delete_texture_wrapper(struct gl_renderbuffer *rb)
476 {
477 ASSERT(rb->RefCount == 0);
478 free(rb);
479 }
480
481
482 /**
483 * This function creates a renderbuffer object which wraps a texture image.
484 * The new renderbuffer is plugged into the given attachment point.
485 * This allows rendering into the texture as if it were a renderbuffer.
486 */
487 static void
488 wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
489 {
490 struct texture_renderbuffer *trb;
491 const GLuint name = 0;
492
493 ASSERT(att->Type == GL_TEXTURE);
494 ASSERT(att->Renderbuffer == NULL);
495
496 trb = CALLOC_STRUCT(texture_renderbuffer);
497 if (!trb) {
498 _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
499 return;
500 }
501
502 /* init base gl_renderbuffer fields */
503 _mesa_init_renderbuffer(&trb->Base, name);
504 /* plug in our texture_renderbuffer-specific functions */
505 trb->Base.Delete = delete_texture_wrapper;
506 trb->Base.AllocStorage = NULL; /* illegal! */
507 trb->Base.GetRow = texture_get_row;
508 trb->Base.GetValues = texture_get_values;
509 trb->Base.PutRow = texture_put_row;
510 trb->Base.PutRowRGB = texture_put_row_rgb;
511 trb->Base.PutMonoRow = texture_put_mono_row;
512 trb->Base.PutValues = texture_put_values;
513 trb->Base.PutMonoValues = texture_put_mono_values;
514
515 /* update attachment point */
516 _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base));
517 }
518
519
520
521 /**
522 * Update the renderbuffer wrapper for rendering to a texture.
523 * For example, update the width, height of the RB based on the texture size,
524 * update the internal format info, etc.
525 */
526 static void
527 update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
528 {
529 struct texture_renderbuffer *trb
530 = (struct texture_renderbuffer *) att->Renderbuffer;
531
532 (void) ctx;
533 ASSERT(trb);
534
535 trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
536 ASSERT(trb->TexImage);
537
538 trb->Store = _mesa_get_texel_store_func(trb->TexImage->TexFormat);
539 if (!trb->Store) {
540 /* we'll never draw into some textures (compressed formats) */
541 trb->Store = store_nop;
542 }
543
544 if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
545 trb->Yoffset = att->Zoffset;
546 trb->Zoffset = 0;
547 }
548 else {
549 trb->Yoffset = 0;
550 trb->Zoffset = att->Zoffset;
551 }
552
553 trb->Base.Width = trb->TexImage->Width;
554 trb->Base.Height = trb->TexImage->Height;
555 trb->Base.InternalFormat = trb->TexImage->InternalFormat;
556 trb->Base.Format = trb->TexImage->TexFormat;
557
558 /* XXX may need more special cases here */
559 switch (trb->TexImage->TexFormat) {
560 case MESA_FORMAT_Z24_S8:
561 trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
562 trb->Base._BaseFormat = GL_DEPTH_STENCIL;
563 break;
564 case MESA_FORMAT_S8_Z24:
565 trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
566 trb->Base._BaseFormat = GL_DEPTH_STENCIL;
567 break;
568 case MESA_FORMAT_Z24_X8:
569 trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
570 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
571 break;
572 case MESA_FORMAT_X8_Z24:
573 trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
574 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
575 break;
576 case MESA_FORMAT_Z16:
577 trb->Base.DataType = GL_UNSIGNED_SHORT;
578 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
579 break;
580 case MESA_FORMAT_Z32:
581 trb->Base.DataType = GL_UNSIGNED_INT;
582 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
583 break;
584 default:
585 trb->Base.DataType = CHAN_TYPE;
586 trb->Base._BaseFormat = GL_RGBA;
587 }
588 trb->Base.Data = trb->TexImage->Data;
589 }
590
591
592
593 /**
594 * Called when rendering to a texture image begins, or when changing
595 * the dest mipmap level, cube face, etc.
596 * This is a fallback routine for software render-to-texture.
597 *
598 * Called via the glRenderbufferTexture1D/2D/3D() functions
599 * and elsewhere (such as glTexImage2D).
600 *
601 * The image we're rendering into is
602 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
603 * It'll never be NULL.
604 *
605 * \param fb the framebuffer object the texture is being bound to
606 * \param att the fb attachment point of the texture
607 *
608 * \sa _mesa_framebuffer_renderbuffer
609 */
610 void
611 _mesa_render_texture(GLcontext *ctx,
612 struct gl_framebuffer *fb,
613 struct gl_renderbuffer_attachment *att)
614 {
615 (void) fb;
616
617 if (!att->Renderbuffer) {
618 wrap_texture(ctx, att);
619 }
620 update_wrapper(ctx, att);
621 }
622
623
624 void
625 _mesa_finish_render_texture(GLcontext *ctx,
626 struct gl_renderbuffer_attachment *att)
627 {
628 /* do nothing */
629 /* The renderbuffer texture wrapper will get deleted by the
630 * normal mechanism for deleting renderbuffers.
631 */
632 (void) ctx;
633 (void) att;
634 }