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