Tizen 2.0 Release
[profile/ivi/osmesa.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 }