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