2 #include "main/context.h"
3 #include "main/colormac.h"
4 #include "main/fbobject.h"
5 #include "main/macros.h"
6 #include "main/teximage.h"
7 #include "main/renderbuffer.h"
8 #include "swrast/swrast.h"
9 #include "swrast/s_context.h"
10 #include "swrast/s_texfetch.h"
14 * Render-to-texture code for GL_EXT_framebuffer_object
19 * Derived from gl_renderbuffer class
21 struct texture_renderbuffer
23 struct gl_renderbuffer Base
; /**< Base class object */
24 struct swrast_texture_image
*TexImage
;
27 GLint Yoffset
; /**< Layer for 1D array textures. */
28 GLint Zoffset
; /**< Layer for 2D array textures, or slice
35 * Get row of values from the renderbuffer that wraps a texture image.
38 texture_get_row(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
39 GLint x
, GLint y
, void *values
)
41 const struct texture_renderbuffer
*trb
42 = (const struct texture_renderbuffer
*) rb
;
43 const GLint z
= trb
->Zoffset
;
46 ASSERT(trb
->TexImage
->Base
.Width
== rb
->Width
);
47 ASSERT(trb
->TexImage
->Base
.Height
== rb
->Height
);
51 if (rb
->DataType
== CHAN_TYPE
) {
52 GLchan
*rgbaOut
= (GLchan
*) values
;
53 for (i
= 0; i
< count
; i
++) {
55 trb
->Fetch(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
56 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut
+ 4 * i
, rgba
);
59 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
60 GLushort
*zValues
= (GLushort
*) values
;
61 for (i
= 0; i
< count
; i
++) {
63 trb
->Fetch(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
64 zValues
[i
] = (GLushort
) (flt
* 0xffff);
67 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
68 GLuint
*zValues
= (GLuint
*) values
;
70 const GLdouble scale = (GLdouble) 0xffffffff;
72 for (i
= 0; i
< count
; i
++) {
74 trb
->Fetch(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
76 /* this should work, but doesn't (overflow due to low precision) */
77 zValues
[i
] = (GLuint
) (flt
* scale
);
80 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
84 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
85 GLuint
*zValues
= (GLuint
*) values
;
86 for (i
= 0; i
< count
; i
++) {
88 trb
->Fetch(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
89 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
92 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
93 GLuint
*zValues
= (GLuint
*) values
;
94 for (i
= 0; i
< count
; i
++) {
96 trb
->Fetch(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
97 zValues
[i
] = (GLuint
) (flt
* 0xffffff);
101 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_row");
107 texture_get_values(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
108 const GLint x
[], const GLint y
[], void *values
)
110 const struct texture_renderbuffer
*trb
111 = (const struct texture_renderbuffer
*) rb
;
112 const GLint z
= trb
->Zoffset
;
115 if (rb
->DataType
== CHAN_TYPE
) {
116 GLchan
*rgbaOut
= (GLchan
*) values
;
117 for (i
= 0; i
< count
; i
++) {
119 trb
->Fetch(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
121 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut
+ 4 * i
, rgba
);
124 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
125 GLushort
*zValues
= (GLushort
*) values
;
126 for (i
= 0; i
< count
; i
++) {
128 trb
->Fetch(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
130 zValues
[i
] = (GLushort
) (flt
* 0xffff);
133 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
134 GLuint
*zValues
= (GLuint
*) values
;
135 for (i
= 0; i
< count
; i
++) {
137 trb
->Fetch(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
140 zValues
[i
] = (GLuint
) (flt
* 0xffffffff);
142 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
146 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
147 GLuint
*zValues
= (GLuint
*) values
;
148 for (i
= 0; i
< count
; i
++) {
150 trb
->Fetch(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
152 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
155 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
156 GLuint
*zValues
= (GLuint
*) values
;
157 for (i
= 0; i
< count
; i
++) {
159 trb
->Fetch(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
161 zValues
[i
] = (GLuint
) (flt
* 0xffffff);
165 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_values");
171 * Put row of values into a renderbuffer that wraps a texture image.
174 texture_put_row(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
175 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
177 const struct texture_renderbuffer
*trb
178 = (const struct texture_renderbuffer
*) rb
;
179 const GLint z
= trb
->Zoffset
;
184 if (rb
->DataType
== CHAN_TYPE
) {
185 const GLchan
*rgba
= (const GLchan
*) values
;
186 for (i
= 0; i
< count
; i
++) {
187 if (!mask
|| mask
[i
]) {
188 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
193 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
194 const GLushort
*zValues
= (const GLushort
*) values
;
195 for (i
= 0; i
< count
; i
++) {
196 if (!mask
|| mask
[i
]) {
197 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
201 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
202 const GLuint
*zValues
= (const GLuint
*) values
;
203 for (i
= 0; i
< count
; i
++) {
204 if (!mask
|| mask
[i
]) {
205 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
209 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
210 const GLuint
*zValues
= (const GLuint
*) values
;
211 for (i
= 0; i
< count
; i
++) {
212 if (!mask
|| mask
[i
]) {
213 GLfloat flt
= (GLfloat
) ((zValues
[i
] >> 8) * (1.0 / 0xffffff));
214 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
218 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
219 const GLuint
*zValues
= (const GLuint
*) values
;
220 for (i
= 0; i
< count
; i
++) {
221 if (!mask
|| mask
[i
]) {
222 GLfloat flt
= (GLfloat
) ((zValues
[i
] & 0xffffff) * (1.0 / 0xffffff));
223 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
228 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_row");
233 * Put row of RGB values into a renderbuffer that wraps a texture image.
236 texture_put_row_rgb(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
237 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
239 const struct texture_renderbuffer
*trb
240 = (const struct texture_renderbuffer
*) rb
;
241 const GLint z
= trb
->Zoffset
;
246 if (rb
->DataType
== CHAN_TYPE
) {
247 const GLchan
*rgb
= (const GLchan
*) values
;
248 for (i
= 0; i
< count
; i
++) {
249 if (!mask
|| mask
[i
]) {
250 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgb
);
255 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
256 const GLushort
*zValues
= (const GLushort
*) values
;
257 for (i
= 0; i
< count
; i
++) {
258 if (!mask
|| mask
[i
]) {
259 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
263 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
264 const GLuint
*zValues
= (const GLuint
*) values
;
265 for (i
= 0; i
< count
; i
++) {
266 if (!mask
|| mask
[i
]) {
267 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
271 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
272 const GLuint
*zValues
= (const GLuint
*) values
;
273 for (i
= 0; i
< count
; i
++) {
274 if (!mask
|| mask
[i
]) {
275 GLfloat flt
= (GLfloat
) ((zValues
[i
] >> 8) * (1.0 / 0xffffff));
276 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
280 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
281 const GLuint
*zValues
= (const GLuint
*) values
;
282 for (i
= 0; i
< count
; i
++) {
283 if (!mask
|| mask
[i
]) {
284 GLfloat flt
= (GLfloat
) ((zValues
[i
] & 0xffffff) * (1.0 / 0xffffff));
285 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
290 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_row");
296 texture_put_mono_row(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
297 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
299 const struct texture_renderbuffer
*trb
300 = (const struct texture_renderbuffer
*) rb
;
301 const GLint z
= trb
->Zoffset
;
306 if (rb
->DataType
== CHAN_TYPE
) {
307 const GLchan
*rgba
= (const GLchan
*) value
;
308 for (i
= 0; i
< count
; i
++) {
309 if (!mask
|| mask
[i
]) {
310 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
314 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
315 const GLushort zValue
= *((const GLushort
*) value
);
316 for (i
= 0; i
< count
; i
++) {
317 if (!mask
|| mask
[i
]) {
318 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &zValue
);
322 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
323 const GLuint zValue
= *((const GLuint
*) value
);
324 for (i
= 0; i
< count
; i
++) {
325 if (!mask
|| mask
[i
]) {
326 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &zValue
);
330 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
331 const GLuint zValue
= *((const GLuint
*) value
);
332 const GLfloat flt
= (GLfloat
) ((zValue
>> 8) * (1.0 / 0xffffff));
333 for (i
= 0; i
< count
; i
++) {
334 if (!mask
|| mask
[i
]) {
335 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
339 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
340 const GLuint zValue
= *((const GLuint
*) value
);
341 const GLfloat flt
= (GLfloat
) ((zValue
& 0xffffff) * (1.0 / 0xffffff));
342 for (i
= 0; i
< count
; i
++) {
343 if (!mask
|| mask
[i
]) {
344 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
349 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_row");
355 texture_put_values(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
356 const GLint x
[], const GLint y
[], const void *values
,
359 const struct texture_renderbuffer
*trb
360 = (const struct texture_renderbuffer
*) rb
;
361 const GLint z
= trb
->Zoffset
;
364 if (rb
->DataType
== CHAN_TYPE
) {
365 const GLchan
*rgba
= (const GLchan
*) values
;
366 for (i
= 0; i
< count
; i
++) {
367 if (!mask
|| mask
[i
]) {
368 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, rgba
);
373 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
374 const GLushort
*zValues
= (const GLushort
*) values
;
375 for (i
= 0; i
< count
; i
++) {
376 if (!mask
|| mask
[i
]) {
377 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, zValues
+ i
);
381 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
382 const GLuint
*zValues
= (const GLuint
*) values
;
383 for (i
= 0; i
< count
; i
++) {
384 if (!mask
|| mask
[i
]) {
385 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, zValues
+ i
);
389 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
390 const GLuint
*zValues
= (const GLuint
*) values
;
391 for (i
= 0; i
< count
; i
++) {
392 if (!mask
|| mask
[i
]) {
393 GLfloat flt
= (GLfloat
) ((zValues
[i
] >> 8) * (1.0 / 0xffffff));
394 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
398 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
399 const GLuint
*zValues
= (const GLuint
*) values
;
400 for (i
= 0; i
< count
; i
++) {
401 if (!mask
|| mask
[i
]) {
402 GLfloat flt
= (GLfloat
) ((zValues
[i
] & 0xffffff) * (1.0 / 0xffffff));
403 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
408 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_values");
414 texture_put_mono_values(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
415 GLuint count
, const GLint x
[], const GLint y
[],
416 const void *value
, const GLubyte
*mask
)
418 const struct texture_renderbuffer
*trb
419 = (const struct texture_renderbuffer
*) rb
;
420 const GLint z
= trb
->Zoffset
;
423 if (rb
->DataType
== CHAN_TYPE
) {
424 const GLchan
*rgba
= (const GLchan
*) value
;
425 for (i
= 0; i
< count
; i
++) {
426 if (!mask
|| mask
[i
]) {
427 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, rgba
);
431 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
432 const GLuint zValue
= *((const GLuint
*) value
);
433 for (i
= 0; i
< count
; i
++) {
434 if (!mask
|| mask
[i
]) {
435 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &zValue
);
439 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
440 const GLushort zValue
= *((const GLushort
*) value
);
441 for (i
= 0; i
< count
; i
++) {
442 if (!mask
|| mask
[i
]) {
443 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &zValue
);
447 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
448 const GLuint zValue
= *((const GLuint
*) value
);
449 const GLfloat flt
= (GLfloat
) ((zValue
>> 8) * (1.0 / 0xffffff));
450 for (i
= 0; i
< count
; i
++) {
451 if (!mask
|| mask
[i
]) {
452 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
456 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
457 const GLuint zValue
= *((const GLuint
*) value
);
458 const GLfloat flt
= (GLfloat
) ((zValue
& 0xffffff) * (1.0 / 0xffffff));
459 for (i
= 0; i
< count
; i
++) {
460 if (!mask
|| mask
[i
]) {
461 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
466 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_values");
472 store_nop(struct swrast_texture_image
*texImage
,
473 GLint col
, GLint row
, GLint img
,
480 delete_texture_wrapper(struct gl_renderbuffer
*rb
)
482 ASSERT(rb
->RefCount
== 0);
488 * This function creates a renderbuffer object which wraps a texture image.
489 * The new renderbuffer is plugged into the given attachment point.
490 * This allows rendering into the texture as if it were a renderbuffer.
493 wrap_texture(struct gl_context
*ctx
, struct gl_renderbuffer_attachment
*att
)
495 struct texture_renderbuffer
*trb
;
496 const GLuint name
= 0;
498 ASSERT(att
->Type
== GL_TEXTURE
);
499 ASSERT(att
->Renderbuffer
== NULL
);
501 trb
= CALLOC_STRUCT(texture_renderbuffer
);
503 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "wrap_texture");
507 /* init base gl_renderbuffer fields */
508 _mesa_init_renderbuffer(&trb
->Base
, name
);
509 /* plug in our texture_renderbuffer-specific functions */
510 trb
->Base
.Delete
= delete_texture_wrapper
;
511 trb
->Base
.AllocStorage
= NULL
; /* illegal! */
512 trb
->Base
.GetRow
= texture_get_row
;
513 trb
->Base
.GetValues
= texture_get_values
;
514 trb
->Base
.PutRow
= texture_put_row
;
515 trb
->Base
.PutRowRGB
= texture_put_row_rgb
;
516 trb
->Base
.PutMonoRow
= texture_put_mono_row
;
517 trb
->Base
.PutValues
= texture_put_values
;
518 trb
->Base
.PutMonoValues
= texture_put_mono_values
;
520 /* update attachment point */
521 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &(trb
->Base
));
525 * Update the renderbuffer wrapper for rendering to a texture.
526 * For example, update the width, height of the RB based on the texture size,
527 * update the internal format info, etc.
530 update_wrapper(struct gl_context
*ctx
, struct gl_renderbuffer_attachment
*att
)
532 struct texture_renderbuffer
*trb
533 = (struct texture_renderbuffer
*) att
->Renderbuffer
;
538 trb
->TexImage
= swrast_texture_image(_mesa_get_attachment_teximage(att
));
539 ASSERT(trb
->TexImage
);
541 trb
->Store
= _mesa_get_texel_store_func(trb
->TexImage
->Base
.TexFormat
);
543 /* we'll never draw into some textures (compressed formats) */
544 trb
->Store
= store_nop
;
547 if (!trb
->TexImage
->FetchTexel
) {
548 _mesa_update_fetch_functions(trb
->TexImage
->Base
.TexObject
);
550 trb
->Fetch
= trb
->TexImage
->FetchTexel
;
553 if (att
->Texture
->Target
== GL_TEXTURE_1D_ARRAY_EXT
) {
554 trb
->Yoffset
= att
->Zoffset
;
559 trb
->Zoffset
= att
->Zoffset
;
562 trb
->Base
.Width
= trb
->TexImage
->Base
.Width
;
563 trb
->Base
.Height
= trb
->TexImage
->Base
.Height
;
564 trb
->Base
.InternalFormat
= trb
->TexImage
->Base
.InternalFormat
;
565 trb
->Base
.Format
= trb
->TexImage
->Base
.TexFormat
;
567 /* XXX may need more special cases here */
568 switch (trb
->TexImage
->Base
.TexFormat
) {
569 case MESA_FORMAT_Z24_S8
:
570 trb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
571 trb
->Base
._BaseFormat
= GL_DEPTH_STENCIL
;
573 case MESA_FORMAT_S8_Z24
:
574 trb
->Base
.DataType
= GL_UNSIGNED_INT_8_24_REV_MESA
;
575 trb
->Base
._BaseFormat
= GL_DEPTH_STENCIL
;
577 case MESA_FORMAT_Z24_X8
:
578 trb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
579 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
581 case MESA_FORMAT_X8_Z24
:
582 trb
->Base
.DataType
= GL_UNSIGNED_INT_8_24_REV_MESA
;
583 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
585 case MESA_FORMAT_Z16
:
586 trb
->Base
.DataType
= GL_UNSIGNED_SHORT
;
587 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
589 case MESA_FORMAT_Z32
:
590 trb
->Base
.DataType
= GL_UNSIGNED_INT
;
591 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
593 /* SRGB formats pre EXT_framebuffer_sRGB don't do sRGB translations on FBO readback */
594 case MESA_FORMAT_SRGB8
:
595 trb
->Fetch
= _mesa_get_texel_fetch_func(MESA_FORMAT_RGB888
, _mesa_get_texture_dimensions(att
->Texture
->Target
));
596 trb
->Base
.DataType
= CHAN_TYPE
;
597 trb
->Base
._BaseFormat
= GL_RGBA
;
599 case MESA_FORMAT_SRGBA8
:
600 trb
->Fetch
= _mesa_get_texel_fetch_func(MESA_FORMAT_RGBA8888
, _mesa_get_texture_dimensions(att
->Texture
->Target
));
601 trb
->Base
.DataType
= CHAN_TYPE
;
602 trb
->Base
._BaseFormat
= GL_RGBA
;
604 case MESA_FORMAT_SARGB8
:
605 trb
->Fetch
= _mesa_get_texel_fetch_func(MESA_FORMAT_ARGB8888
, _mesa_get_texture_dimensions(att
->Texture
->Target
));
606 trb
->Base
.DataType
= CHAN_TYPE
;
607 trb
->Base
._BaseFormat
= GL_RGBA
;
610 trb
->Base
.DataType
= CHAN_TYPE
;
611 trb
->Base
._BaseFormat
= GL_RGBA
;
613 trb
->Base
.Data
= trb
->TexImage
->Data
;
619 * Called when rendering to a texture image begins, or when changing
620 * the dest mipmap level, cube face, etc.
621 * This is a fallback routine for software render-to-texture.
623 * Called via the glRenderbufferTexture1D/2D/3D() functions
624 * and elsewhere (such as glTexImage2D).
626 * The image we're rendering into is
627 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
628 * It'll never be NULL.
630 * \param fb the framebuffer object the texture is being bound to
631 * \param att the fb attachment point of the texture
633 * \sa _mesa_framebuffer_renderbuffer
636 _swrast_render_texture(struct gl_context
*ctx
,
637 struct gl_framebuffer
*fb
,
638 struct gl_renderbuffer_attachment
*att
)
642 if (!att
->Renderbuffer
) {
643 wrap_texture(ctx
, att
);
645 update_wrapper(ctx
, att
);
650 _swrast_finish_render_texture(struct gl_context
*ctx
,
651 struct gl_renderbuffer_attachment
*att
)
654 /* The renderbuffer texture wrapper will get deleted by the
655 * normal mechanism for deleting renderbuffers.