7 #include "renderbuffer.h"
11 * Render-to-texture code for GL_EXT_framebuffer_object
16 * Derived from gl_renderbuffer class
18 struct texture_renderbuffer
20 struct gl_renderbuffer Base
; /**< Base class object */
21 struct gl_texture_image
*TexImage
;
23 GLint Yoffset
; /**< Layer for 1D array textures. */
24 GLint Zoffset
; /**< Layer for 2D array textures, or slice
31 * Get row of values from the renderbuffer that wraps a texture image.
34 texture_get_row(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
35 GLint x
, GLint y
, void *values
)
37 const struct texture_renderbuffer
*trb
38 = (const struct texture_renderbuffer
*) rb
;
39 const GLint z
= trb
->Zoffset
;
42 ASSERT(trb
->TexImage
->Width
== rb
->Width
);
43 ASSERT(trb
->TexImage
->Height
== rb
->Height
);
47 if (rb
->DataType
== CHAN_TYPE
) {
48 GLchan
*rgbaOut
= (GLchan
*) values
;
49 for (i
= 0; i
< count
; i
++) {
51 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
52 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut
+ 4 * i
, rgba
);
55 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
56 GLushort
*zValues
= (GLushort
*) values
;
57 for (i
= 0; i
< count
; i
++) {
59 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
60 zValues
[i
] = (GLushort
) (flt
* 0xffff);
63 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
64 GLuint
*zValues
= (GLuint
*) values
;
66 const GLdouble scale = (GLdouble) 0xffffffff;
68 for (i
= 0; i
< count
; i
++) {
70 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
72 /* this should work, but doesn't (overflow due to low precision) */
73 zValues
[i
] = (GLuint
) (flt
* scale
);
76 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
80 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
81 GLuint
*zValues
= (GLuint
*) values
;
82 for (i
= 0; i
< count
; i
++) {
84 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
85 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
88 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
89 GLuint
*zValues
= (GLuint
*) values
;
90 for (i
= 0; i
< count
; i
++) {
92 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
93 zValues
[i
] = (GLuint
) (flt
* 0xffffff);
97 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_row");
103 texture_get_values(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
104 const GLint x
[], const GLint y
[], void *values
)
106 const struct texture_renderbuffer
*trb
107 = (const struct texture_renderbuffer
*) rb
;
108 const GLint z
= trb
->Zoffset
;
111 if (rb
->DataType
== CHAN_TYPE
) {
112 GLchan
*rgbaOut
= (GLchan
*) values
;
113 for (i
= 0; i
< count
; i
++) {
115 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
117 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut
+ 4 * i
, rgba
);
120 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
121 GLushort
*zValues
= (GLushort
*) values
;
122 for (i
= 0; i
< count
; i
++) {
124 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
126 zValues
[i
] = (GLushort
) (flt
* 0xffff);
129 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
130 GLuint
*zValues
= (GLuint
*) values
;
131 for (i
= 0; i
< count
; i
++) {
133 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
136 zValues
[i
] = (GLuint
) (flt
* 0xffffffff);
138 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
142 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
143 GLuint
*zValues
= (GLuint
*) values
;
144 for (i
= 0; i
< count
; i
++) {
146 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
148 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
151 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
152 GLuint
*zValues
= (GLuint
*) values
;
153 for (i
= 0; i
< count
; i
++) {
155 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
,
157 zValues
[i
] = (GLuint
) (flt
* 0xffffff);
161 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_values");
167 * Put row of values into a renderbuffer that wraps a texture image.
170 texture_put_row(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
171 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
173 const struct texture_renderbuffer
*trb
174 = (const struct texture_renderbuffer
*) rb
;
175 const GLint z
= trb
->Zoffset
;
180 if (rb
->DataType
== CHAN_TYPE
) {
181 const GLchan
*rgba
= (const GLchan
*) values
;
182 for (i
= 0; i
< count
; i
++) {
183 if (!mask
|| mask
[i
]) {
184 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
189 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
190 const GLushort
*zValues
= (const GLushort
*) values
;
191 for (i
= 0; i
< count
; i
++) {
192 if (!mask
|| mask
[i
]) {
193 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
197 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
198 const GLuint
*zValues
= (const GLuint
*) values
;
199 for (i
= 0; i
< count
; i
++) {
200 if (!mask
|| mask
[i
]) {
201 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
205 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
206 const GLuint
*zValues
= (const GLuint
*) values
;
207 for (i
= 0; i
< count
; i
++) {
208 if (!mask
|| mask
[i
]) {
209 GLfloat flt
= (GLfloat
) ((zValues
[i
] >> 8) * (1.0 / 0xffffff));
210 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
214 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
215 const GLuint
*zValues
= (const GLuint
*) values
;
216 for (i
= 0; i
< count
; i
++) {
217 if (!mask
|| mask
[i
]) {
218 GLfloat flt
= (GLfloat
) ((zValues
[i
] & 0xffffff) * (1.0 / 0xffffff));
219 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
224 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_row");
229 * Put row of RGB values into a renderbuffer that wraps a texture image.
232 texture_put_row_rgb(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
233 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
235 const struct texture_renderbuffer
*trb
236 = (const struct texture_renderbuffer
*) rb
;
237 const GLint z
= trb
->Zoffset
;
242 if (rb
->DataType
== CHAN_TYPE
) {
243 const GLchan
*rgb
= (const GLchan
*) values
;
244 for (i
= 0; i
< count
; i
++) {
245 if (!mask
|| mask
[i
]) {
246 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgb
);
251 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
252 const GLushort
*zValues
= (const GLushort
*) values
;
253 for (i
= 0; i
< count
; i
++) {
254 if (!mask
|| mask
[i
]) {
255 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
259 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
260 const GLuint
*zValues
= (const GLuint
*) values
;
261 for (i
= 0; i
< count
; i
++) {
262 if (!mask
|| mask
[i
]) {
263 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
267 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
268 const GLuint
*zValues
= (const GLuint
*) values
;
269 for (i
= 0; i
< count
; i
++) {
270 if (!mask
|| mask
[i
]) {
271 GLfloat flt
= (GLfloat
) ((zValues
[i
] >> 8) * (1.0 / 0xffffff));
272 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
276 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
277 const GLuint
*zValues
= (const GLuint
*) values
;
278 for (i
= 0; i
< count
; i
++) {
279 if (!mask
|| mask
[i
]) {
280 GLfloat flt
= (GLfloat
) ((zValues
[i
] & 0xffffff) * (1.0 / 0xffffff));
281 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
286 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_row");
292 texture_put_mono_row(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
293 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
295 const struct texture_renderbuffer
*trb
296 = (const struct texture_renderbuffer
*) rb
;
297 const GLint z
= trb
->Zoffset
;
302 if (rb
->DataType
== CHAN_TYPE
) {
303 const GLchan
*rgba
= (const GLchan
*) value
;
304 for (i
= 0; i
< count
; i
++) {
305 if (!mask
|| mask
[i
]) {
306 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
310 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
311 const GLushort zValue
= *((const GLushort
*) value
);
312 for (i
= 0; i
< count
; i
++) {
313 if (!mask
|| mask
[i
]) {
314 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &zValue
);
318 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
319 const GLuint zValue
= *((const GLuint
*) value
);
320 for (i
= 0; i
< count
; i
++) {
321 if (!mask
|| mask
[i
]) {
322 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &zValue
);
326 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
327 const GLuint zValue
= *((const GLuint
*) value
);
328 const GLfloat flt
= (GLfloat
) ((zValue
>> 8) * (1.0 / 0xffffff));
329 for (i
= 0; i
< count
; i
++) {
330 if (!mask
|| mask
[i
]) {
331 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
335 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
336 const GLuint zValue
= *((const GLuint
*) value
);
337 const GLfloat flt
= (GLfloat
) ((zValue
& 0xffffff) * (1.0 / 0xffffff));
338 for (i
= 0; i
< count
; i
++) {
339 if (!mask
|| mask
[i
]) {
340 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
345 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_row");
351 texture_put_values(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
352 const GLint x
[], const GLint y
[], const void *values
,
355 const struct texture_renderbuffer
*trb
356 = (const struct texture_renderbuffer
*) rb
;
357 const GLint z
= trb
->Zoffset
;
360 if (rb
->DataType
== CHAN_TYPE
) {
361 const GLchan
*rgba
= (const GLchan
*) values
;
362 for (i
= 0; i
< count
; i
++) {
363 if (!mask
|| mask
[i
]) {
364 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, rgba
);
369 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
370 const GLushort
*zValues
= (const GLushort
*) values
;
371 for (i
= 0; i
< count
; i
++) {
372 if (!mask
|| mask
[i
]) {
373 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, zValues
+ i
);
377 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
378 const GLuint
*zValues
= (const GLuint
*) values
;
379 for (i
= 0; i
< count
; i
++) {
380 if (!mask
|| mask
[i
]) {
381 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, zValues
+ i
);
385 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
386 const GLuint
*zValues
= (const GLuint
*) values
;
387 for (i
= 0; i
< count
; i
++) {
388 if (!mask
|| mask
[i
]) {
389 GLfloat flt
= (GLfloat
) ((zValues
[i
] >> 8) * (1.0 / 0xffffff));
390 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
394 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
395 const GLuint
*zValues
= (const GLuint
*) values
;
396 for (i
= 0; i
< count
; i
++) {
397 if (!mask
|| mask
[i
]) {
398 GLfloat flt
= (GLfloat
) ((zValues
[i
] & 0xffffff) * (1.0 / 0xffffff));
399 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
404 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_values");
410 texture_put_mono_values(struct gl_context
*ctx
, struct gl_renderbuffer
*rb
,
411 GLuint count
, const GLint x
[], const GLint y
[],
412 const void *value
, const GLubyte
*mask
)
414 const struct texture_renderbuffer
*trb
415 = (const struct texture_renderbuffer
*) rb
;
416 const GLint z
= trb
->Zoffset
;
419 if (rb
->DataType
== CHAN_TYPE
) {
420 const GLchan
*rgba
= (const GLchan
*) value
;
421 for (i
= 0; i
< count
; i
++) {
422 if (!mask
|| mask
[i
]) {
423 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, rgba
);
427 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
428 const GLuint zValue
= *((const GLuint
*) value
);
429 for (i
= 0; i
< count
; i
++) {
430 if (!mask
|| mask
[i
]) {
431 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &zValue
);
435 else if (rb
->DataType
== GL_UNSIGNED_SHORT
) {
436 const GLushort zValue
= *((const GLushort
*) value
);
437 for (i
= 0; i
< count
; i
++) {
438 if (!mask
|| mask
[i
]) {
439 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &zValue
);
443 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
444 const GLuint zValue
= *((const GLuint
*) value
);
445 const GLfloat flt
= (GLfloat
) ((zValue
>> 8) * (1.0 / 0xffffff));
446 for (i
= 0; i
< count
; i
++) {
447 if (!mask
|| mask
[i
]) {
448 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
452 else if (rb
->DataType
== GL_UNSIGNED_INT_8_24_REV_MESA
) {
453 const GLuint zValue
= *((const GLuint
*) value
);
454 const GLfloat flt
= (GLfloat
) ((zValue
& 0xffffff) * (1.0 / 0xffffff));
455 for (i
= 0; i
< count
; i
++) {
456 if (!mask
|| mask
[i
]) {
457 trb
->Store(trb
->TexImage
, x
[i
], y
[i
] + trb
->Yoffset
, z
, &flt
);
462 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_values");
468 store_nop(struct gl_texture_image
*texImage
,
469 GLint col
, GLint row
, GLint img
,
476 delete_texture_wrapper(struct gl_renderbuffer
*rb
)
478 ASSERT(rb
->RefCount
== 0);
484 * This function creates a renderbuffer object which wraps a texture image.
485 * The new renderbuffer is plugged into the given attachment point.
486 * This allows rendering into the texture as if it were a renderbuffer.
489 wrap_texture(struct gl_context
*ctx
, struct gl_renderbuffer_attachment
*att
)
491 struct texture_renderbuffer
*trb
;
492 const GLuint name
= 0;
494 ASSERT(att
->Type
== GL_TEXTURE
);
495 ASSERT(att
->Renderbuffer
== NULL
);
497 trb
= CALLOC_STRUCT(texture_renderbuffer
);
499 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "wrap_texture");
503 /* init base gl_renderbuffer fields */
504 _mesa_init_renderbuffer(&trb
->Base
, name
);
505 /* plug in our texture_renderbuffer-specific functions */
506 trb
->Base
.Delete
= delete_texture_wrapper
;
507 trb
->Base
.AllocStorage
= NULL
; /* illegal! */
508 trb
->Base
.GetRow
= texture_get_row
;
509 trb
->Base
.GetValues
= texture_get_values
;
510 trb
->Base
.PutRow
= texture_put_row
;
511 trb
->Base
.PutRowRGB
= texture_put_row_rgb
;
512 trb
->Base
.PutMonoRow
= texture_put_mono_row
;
513 trb
->Base
.PutValues
= texture_put_values
;
514 trb
->Base
.PutMonoValues
= texture_put_mono_values
;
516 /* update attachment point */
517 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &(trb
->Base
));
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.
528 update_wrapper(struct gl_context
*ctx
, const struct gl_renderbuffer_attachment
*att
)
530 struct texture_renderbuffer
*trb
531 = (struct texture_renderbuffer
*) att
->Renderbuffer
;
536 trb
->TexImage
= att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
537 ASSERT(trb
->TexImage
);
539 trb
->Store
= _mesa_get_texel_store_func(trb
->TexImage
->TexFormat
);
541 /* we'll never draw into some textures (compressed formats) */
542 trb
->Store
= store_nop
;
545 if (att
->Texture
->Target
== GL_TEXTURE_1D_ARRAY_EXT
) {
546 trb
->Yoffset
= att
->Zoffset
;
551 trb
->Zoffset
= att
->Zoffset
;
554 trb
->Base
.Width
= trb
->TexImage
->Width
;
555 trb
->Base
.Height
= trb
->TexImage
->Height
;
556 trb
->Base
.InternalFormat
= trb
->TexImage
->InternalFormat
;
557 trb
->Base
.Format
= trb
->TexImage
->TexFormat
;
559 /* XXX may need more special cases here */
560 switch (trb
->TexImage
->TexFormat
) {
561 case MESA_FORMAT_Z24_S8
:
562 trb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
563 trb
->Base
._BaseFormat
= GL_DEPTH_STENCIL
;
565 case MESA_FORMAT_S8_Z24
:
566 trb
->Base
.DataType
= GL_UNSIGNED_INT_8_24_REV_MESA
;
567 trb
->Base
._BaseFormat
= GL_DEPTH_STENCIL
;
569 case MESA_FORMAT_Z24_X8
:
570 trb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
571 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
573 case MESA_FORMAT_X8_Z24
:
574 trb
->Base
.DataType
= GL_UNSIGNED_INT_8_24_REV_MESA
;
575 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
577 case MESA_FORMAT_Z16
:
578 trb
->Base
.DataType
= GL_UNSIGNED_SHORT
;
579 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
581 case MESA_FORMAT_Z32
:
582 trb
->Base
.DataType
= GL_UNSIGNED_INT
;
583 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
586 trb
->Base
.DataType
= CHAN_TYPE
;
587 trb
->Base
._BaseFormat
= GL_RGBA
;
589 trb
->Base
.Data
= trb
->TexImage
->Data
;
595 * Called when rendering to a texture image begins, or when changing
596 * the dest mipmap level, cube face, etc.
597 * This is a fallback routine for software render-to-texture.
599 * Called via the glRenderbufferTexture1D/2D/3D() functions
600 * and elsewhere (such as glTexImage2D).
602 * The image we're rendering into is
603 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
604 * It'll never be NULL.
606 * \param fb the framebuffer object the texture is being bound to
607 * \param att the fb attachment point of the texture
609 * \sa _mesa_framebuffer_renderbuffer
612 _mesa_render_texture(struct gl_context
*ctx
,
613 struct gl_framebuffer
*fb
,
614 struct gl_renderbuffer_attachment
*att
)
618 if (!att
->Renderbuffer
) {
619 wrap_texture(ctx
, att
);
621 update_wrapper(ctx
, att
);
626 _mesa_finish_render_texture(struct gl_context
*ctx
,
627 struct gl_renderbuffer_attachment
*att
)
630 /* The renderbuffer texture wrapper will get deleted by the
631 * normal mechanism for deleting renderbuffers.