6 #include "renderbuffer.h"
10 * Render-to-texture code for GL_EXT_framebuffer_object
15 * Derived from gl_renderbuffer class
17 struct texture_renderbuffer
19 struct gl_renderbuffer Base
; /* Base class object */
20 struct gl_texture_image
*TexImage
;
27 * Get row of values from the renderbuffer that wraps a texture image.
30 texture_get_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
31 GLint x
, GLint y
, void *values
)
33 const struct texture_renderbuffer
*trb
34 = (const struct texture_renderbuffer
*) rb
;
35 const GLint z
= trb
->Zoffset
;
38 ASSERT(trb
->TexImage
->Width
== rb
->Width
);
39 ASSERT(trb
->TexImage
->Height
== rb
->Height
);
41 if (rb
->DataType
== CHAN_TYPE
) {
42 GLchan
*rgbaOut
= (GLchan
*) values
;
43 for (i
= 0; i
< count
; i
++) {
44 trb
->TexImage
->FetchTexelc(trb
->TexImage
, x
+ i
, y
, z
, rgbaOut
+ 4 * i
);
47 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
48 GLuint
*zValues
= (GLuint
*) values
;
50 const GLdouble scale = (GLdouble) 0xffffffff;
52 for (i
= 0; i
< count
; i
++) {
54 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
56 /* this should work, but doesn't (overflow due to low precision) */
57 zValues
[i
] = (GLuint
) (flt
* scale
);
60 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
64 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
65 GLuint
*zValues
= (GLuint
*) values
;
66 for (i
= 0; i
< count
; i
++) {
68 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
69 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
73 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_row");
79 texture_get_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
80 const GLint x
[], const GLint y
[], void *values
)
82 const struct texture_renderbuffer
*trb
83 = (const struct texture_renderbuffer
*) rb
;
84 const GLint z
= trb
->Zoffset
;
87 if (rb
->DataType
== CHAN_TYPE
) {
88 GLchan
*rgbaOut
= (GLchan
*) values
;
89 for (i
= 0; i
< count
; i
++) {
90 trb
->TexImage
->FetchTexelc(trb
->TexImage
, x
[i
], y
[i
], z
,
94 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
95 GLuint
*zValues
= (GLuint
*) values
;
96 for (i
= 0; i
< count
; i
++) {
98 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
], z
, &flt
);
100 zValues
[i
] = (GLuint
) (flt
* 0xffffffff);
102 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
106 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
107 GLuint
*zValues
= (GLuint
*) values
;
108 for (i
= 0; i
< count
; i
++) {
110 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
], z
, &flt
);
111 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
115 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_values");
121 * Put row of values into a renderbuffer that wraps a texture image.
124 texture_put_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
125 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
127 const struct texture_renderbuffer
*trb
128 = (const struct texture_renderbuffer
*) rb
;
129 const GLint z
= trb
->Zoffset
;
132 if (rb
->DataType
== CHAN_TYPE
) {
133 const GLchan
*rgba
= (const GLchan
*) values
;
134 for (i
= 0; i
< count
; i
++) {
135 if (!mask
|| mask
[i
]) {
136 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
141 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
142 const GLuint
*zValues
= (const GLuint
*) values
;
143 for (i
= 0; i
< count
; i
++) {
144 if (!mask
|| mask
[i
]) {
145 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, zValues
+ i
);
149 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
150 const GLuint
*zValues
= (const GLuint
*) values
;
151 for (i
= 0; i
< count
; i
++) {
152 if (!mask
|| mask
[i
]) {
153 GLfloat flt
= (zValues
[i
] >> 8) * (1.0 / 0xffffff);
154 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
159 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_row");
165 texture_put_mono_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
166 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
168 const struct texture_renderbuffer
*trb
169 = (const struct texture_renderbuffer
*) rb
;
170 const GLint z
= trb
->Zoffset
;
173 if (rb
->DataType
== CHAN_TYPE
) {
174 const GLchan
*rgba
= (const GLchan
*) value
;
175 for (i
= 0; i
< count
; i
++) {
176 if (!mask
|| mask
[i
]) {
177 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
181 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
182 const GLuint zValue
= *((const GLuint
*) value
);
183 for (i
= 0; i
< count
; i
++) {
184 if (!mask
|| mask
[i
]) {
185 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &zValue
);
189 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
190 const GLuint zValue
= *((const GLuint
*) value
);
191 const GLfloat flt
= (zValue
>> 8) * (1.0 / 0xffffff);
192 for (i
= 0; i
< count
; i
++) {
193 if (!mask
|| mask
[i
]) {
194 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
199 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_row");
205 texture_put_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
206 const GLint x
[], const GLint y
[], const void *values
,
209 const struct texture_renderbuffer
*trb
210 = (const struct texture_renderbuffer
*) rb
;
211 const GLint z
= trb
->Zoffset
;
214 if (rb
->DataType
== CHAN_TYPE
) {
215 const GLchan
*rgba
= (const GLchan
*) values
;
216 for (i
= 0; i
< count
; i
++) {
217 if (!mask
|| mask
[i
]) {
218 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, rgba
);
223 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
224 const GLuint
*zValues
= (const GLuint
*) values
;
225 for (i
= 0; i
< count
; i
++) {
226 if (!mask
|| mask
[i
]) {
227 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, zValues
+ i
);
231 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
232 const GLuint
*zValues
= (const GLuint
*) values
;
233 for (i
= 0; i
< count
; i
++) {
234 if (!mask
|| mask
[i
]) {
235 GLfloat flt
= (zValues
[i
] >> 8) * (1.0 / 0xffffff);
236 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, &flt
);
241 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_values");
247 texture_put_mono_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
248 GLuint count
, const GLint x
[], const GLint y
[],
249 const void *value
, const GLubyte
*mask
)
251 const struct texture_renderbuffer
*trb
252 = (const struct texture_renderbuffer
*) rb
;
253 const GLint z
= trb
->Zoffset
;
256 if (rb
->DataType
== CHAN_TYPE
) {
257 const GLchan
*rgba
= (const GLchan
*) value
;
258 for (i
= 0; i
< count
; i
++) {
259 if (!mask
|| mask
[i
]) {
260 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, rgba
);
264 else if (rb
->DataType
== GL_UNSIGNED_INT
) {
265 const GLuint zValue
= *((const GLuint
*) value
);
266 for (i
= 0; i
< count
; i
++) {
267 if (!mask
|| mask
[i
]) {
268 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, &zValue
);
272 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
273 const GLuint zValue
= *((const GLuint
*) value
);
274 const GLfloat flt
= (zValue
>> 8) * (1.0 / 0xffffff);
275 for (i
= 0; i
< count
; i
++) {
276 if (!mask
|| mask
[i
]) {
277 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, &flt
);
282 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_values");
288 delete_texture_wrapper(struct gl_renderbuffer
*rb
)
290 ASSERT(rb
->RefCount
== 0);
296 * This function creates a renderbuffer object which wraps a texture image.
297 * The new renderbuffer is plugged into the given attachment point.
298 * This allows rendering into the texture as if it were a renderbuffer.
301 wrap_texture(GLcontext
*ctx
, struct gl_renderbuffer_attachment
*att
)
303 struct texture_renderbuffer
*trb
;
304 const GLuint name
= 0;
306 ASSERT(att
->Type
== GL_TEXTURE
);
307 ASSERT(att
->Renderbuffer
== NULL
);
309 trb
= CALLOC_STRUCT(texture_renderbuffer
);
311 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "wrap_texture");
315 /* init base gl_renderbuffer fields */
316 _mesa_init_renderbuffer(&trb
->Base
, name
);
317 /* plug in our texture_renderbuffer-specific functions */
318 trb
->Base
.Delete
= delete_texture_wrapper
;
319 trb
->Base
.AllocStorage
= NULL
; /* illegal! */
320 trb
->Base
.GetRow
= texture_get_row
;
321 trb
->Base
.GetValues
= texture_get_values
;
322 trb
->Base
.PutRow
= texture_put_row
;
323 trb
->Base
.PutMonoRow
= texture_put_mono_row
;
324 trb
->Base
.PutValues
= texture_put_values
;
325 trb
->Base
.PutMonoValues
= texture_put_mono_values
;
327 /* update attachment point */
328 att
->Renderbuffer
= &(trb
->Base
);
334 * Update the renderbuffer wrapper for rendering to a texture.
335 * For example, update the width, height of the RB based on the texture size,
336 * update the internal format info, etc.
339 update_wrapper(GLcontext
*ctx
, const struct gl_renderbuffer_attachment
*att
)
341 struct texture_renderbuffer
*trb
342 = (struct texture_renderbuffer
*) att
->Renderbuffer
;
347 trb
->TexImage
= att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
348 ASSERT(trb
->TexImage
);
350 trb
->Store
= trb
->TexImage
->TexFormat
->StoreTexel
;
353 trb
->Zoffset
= att
->Zoffset
;
355 trb
->Base
.Width
= trb
->TexImage
->Width
;
356 trb
->Base
.Height
= trb
->TexImage
->Height
;
357 trb
->Base
.InternalFormat
= trb
->TexImage
->InternalFormat
;
358 /* XXX may need more special cases here */
359 if (trb
->TexImage
->TexFormat
->MesaFormat
== MESA_FORMAT_Z24_S8
) {
360 trb
->Base
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
361 trb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
363 else if (trb
->TexImage
->TexFormat
->MesaFormat
== MESA_FORMAT_Z16
) {
364 trb
->Base
._ActualFormat
= GL_DEPTH_COMPONENT
;
365 trb
->Base
.DataType
= GL_UNSIGNED_SHORT
;
367 else if (trb
->TexImage
->TexFormat
->MesaFormat
== MESA_FORMAT_Z32
) {
368 trb
->Base
._ActualFormat
= GL_DEPTH_COMPONENT
;
369 trb
->Base
.DataType
= GL_UNSIGNED_INT
;
372 trb
->Base
._ActualFormat
= trb
->TexImage
->InternalFormat
;
373 trb
->Base
.DataType
= CHAN_TYPE
;
375 trb
->Base
._BaseFormat
= trb
->TexImage
->TexFormat
->BaseFormat
;
377 /* fix/avoid this assertion someday */
378 ASSERT(trb
->Base
._BaseFormat
== GL_RGB
||
379 trb
->Base
._BaseFormat
== GL_RGBA
||
380 trb
->Base
._BaseFormat
== GL_DEPTH_COMPONENT
);
382 trb
->Base
.Data
= trb
->TexImage
->Data
;
384 trb
->Base
.RedBits
= trb
->TexImage
->TexFormat
->RedBits
;
385 trb
->Base
.GreenBits
= trb
->TexImage
->TexFormat
->GreenBits
;
386 trb
->Base
.BlueBits
= trb
->TexImage
->TexFormat
->BlueBits
;
387 trb
->Base
.AlphaBits
= trb
->TexImage
->TexFormat
->AlphaBits
;
388 trb
->Base
.DepthBits
= trb
->TexImage
->TexFormat
->DepthBits
;
394 * Called when rendering to a texture image begins, or when changing
395 * the dest mipmap level, cube face, etc.
396 * This is a fallback routine for software render-to-texture.
398 * Called via the glRenderbufferTexture1D/2D/3D() functions
399 * and elsewhere (such as glTexImage2D).
401 * The image we're rendering into is
402 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
403 * It'll never be NULL.
405 * \param fb the framebuffer object the texture is being bound to
406 * \param att the fb attachment point of the texture
408 * \sa _mesa_framebuffer_renderbuffer
411 _mesa_render_texture(GLcontext
*ctx
,
412 struct gl_framebuffer
*fb
,
413 struct gl_renderbuffer_attachment
*att
)
417 if (!att
->Renderbuffer
) {
418 wrap_texture(ctx
, att
);
420 update_wrapper(ctx
, att
);
425 _mesa_finish_render_texture(GLcontext
*ctx
,
426 struct gl_renderbuffer_attachment
*att
)
429 /* The renderbuffer texture wrapper will get deleted by the
430 * normal mechanism for deleting renderbuffers.