5 #include "renderbuffer.h"
9 * Render-to-texture code for GL_EXT_framebuffer_object
14 * Derived from gl_renderbuffer class
16 struct texture_renderbuffer
18 struct gl_renderbuffer Base
; /* Base class object */
19 struct gl_texture_image
*TexImage
;
26 * Get row of values from the renderbuffer that wraps a texture image.
29 texture_get_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
30 GLint x
, GLint y
, void *values
)
32 const struct texture_renderbuffer
*trb
33 = (const struct texture_renderbuffer
*) rb
;
34 const GLint z
= trb
->Zoffset
;
37 ASSERT(trb
->TexImage
->Width
== rb
->Width
);
38 ASSERT(trb
->TexImage
->Height
== rb
->Height
);
40 if (rb
->DataType
== CHAN_TYPE
) {
41 GLchan
*rgbaOut
= (GLchan
*) values
;
42 for (i
= 0; i
< count
; i
++) {
43 trb
->TexImage
->FetchTexelc(trb
->TexImage
, x
+ i
, y
, z
, rgbaOut
+ 4 * i
);
46 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
47 GLuint
*zValues
= (GLuint
*) values
;
48 for (i
= 0; i
< count
; i
++) {
50 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
51 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
55 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_row");
61 texture_get_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
62 const GLint x
[], const GLint y
[], void *values
)
64 const struct texture_renderbuffer
*trb
65 = (const struct texture_renderbuffer
*) rb
;
66 const GLint z
= trb
->Zoffset
;
69 if (rb
->DataType
== CHAN_TYPE
) {
70 GLchan
*rgbaOut
= (GLchan
*) values
;
71 for (i
= 0; i
< count
; i
++) {
72 trb
->TexImage
->FetchTexelc(trb
->TexImage
, x
[i
], y
[i
], z
,
76 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
77 GLuint
*zValues
= (GLuint
*) values
;
78 for (i
= 0; i
< count
; i
++) {
80 trb
->TexImage
->FetchTexelf(trb
->TexImage
, x
[i
], y
[i
], z
, &flt
);
81 zValues
[i
] = ((GLuint
) (flt
* 0xffffff)) << 8;
85 _mesa_problem(ctx
, "invalid rb->DataType in texture_get_values");
91 * Put row of values into a renderbuffer that wraps a texture image.
94 texture_put_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
95 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
97 const struct texture_renderbuffer
*trb
98 = (const struct texture_renderbuffer
*) rb
;
99 const GLint z
= trb
->Zoffset
;
102 if (rb
->DataType
== CHAN_TYPE
) {
103 const GLchan
*rgba
= (const GLchan
*) values
;
104 for (i
= 0; i
< count
; i
++) {
105 if (!mask
|| mask
[i
]) {
106 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
111 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
112 const GLuint
*zValues
= (const GLuint
*) values
;
113 for (i
= 0; i
< count
; i
++) {
114 if (!mask
|| mask
[i
]) {
115 GLfloat flt
= (zValues
[i
] >> 8) * (1.0 / 0xffffff);
116 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
121 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_row");
127 texture_put_mono_row(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
128 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
130 const struct texture_renderbuffer
*trb
131 = (const struct texture_renderbuffer
*) rb
;
132 const GLint z
= trb
->Zoffset
;
135 if (rb
->DataType
== CHAN_TYPE
) {
136 const GLchan
*rgba
= (const GLchan
*) value
;
137 for (i
= 0; i
< count
; i
++) {
138 if (!mask
|| mask
[i
]) {
139 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, rgba
);
143 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
144 const GLuint zValue
= *((const GLuint
*) value
);
145 const GLfloat flt
= (zValue
>> 8) * (1.0 / 0xffffff);
146 for (i
= 0; i
< count
; i
++) {
147 if (!mask
|| mask
[i
]) {
148 trb
->Store(trb
->TexImage
, x
+ i
, y
, z
, &flt
);
153 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_row");
159 texture_put_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
160 const GLint x
[], const GLint y
[], const void *values
,
163 const struct texture_renderbuffer
*trb
164 = (const struct texture_renderbuffer
*) rb
;
165 const GLint z
= trb
->Zoffset
;
168 if (rb
->DataType
== CHAN_TYPE
) {
169 const GLchan
*rgba
= (const GLchan
*) values
;
170 for (i
= 0; i
< count
; i
++) {
171 if (!mask
|| mask
[i
]) {
172 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, rgba
);
177 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
178 const GLuint
*zValues
= (const GLuint
*) values
;
179 for (i
= 0; i
< count
; i
++) {
180 if (!mask
|| mask
[i
]) {
181 GLfloat flt
= (zValues
[i
] >> 8) * (1.0 / 0xffffff);
182 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, &flt
);
187 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_values");
193 texture_put_mono_values(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
194 GLuint count
, const GLint x
[], const GLint y
[],
195 const void *value
, const GLubyte
*mask
)
197 const struct texture_renderbuffer
*trb
198 = (const struct texture_renderbuffer
*) rb
;
199 const GLint z
= trb
->Zoffset
;
202 if (rb
->DataType
== CHAN_TYPE
) {
203 const GLchan
*rgba
= (const GLchan
*) value
;
204 for (i
= 0; i
< count
; i
++) {
205 if (!mask
|| mask
[i
]) {
206 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, rgba
);
210 else if (rb
->DataType
== GL_UNSIGNED_INT_24_8_EXT
) {
211 const GLuint zValue
= *((const GLuint
*) value
);
212 const GLfloat flt
= (zValue
>> 8) * (1.0 / 0xffffff);
213 for (i
= 0; i
< count
; i
++) {
214 if (!mask
|| mask
[i
]) {
215 trb
->Store(trb
->TexImage
, x
[i
], y
[i
], z
, &flt
);
220 _mesa_problem(ctx
, "invalid rb->DataType in texture_put_mono_values");
226 delete_texture_wrapper(struct gl_renderbuffer
*rb
)
228 ASSERT(rb
->RefCount
== 0);
234 * This function creates a renderbuffer object which wraps a texture image.
235 * The new renderbuffer is plugged into the given attachment point.
236 * This allows rendering into the texture as if it were a renderbuffer.
239 wrap_texture(GLcontext
*ctx
, struct gl_renderbuffer_attachment
*att
)
241 struct texture_renderbuffer
*trb
;
242 const GLuint name
= 0;
244 ASSERT(att
->Type
== GL_TEXTURE
);
245 ASSERT(att
->Renderbuffer
== NULL
);
247 trb
= CALLOC_STRUCT(texture_renderbuffer
);
249 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "wrap_texture");
253 /* init base gl_renderbuffer fields */
254 _mesa_init_renderbuffer(&trb
->Base
, name
);
255 /* plug in our texture_renderbuffer-specific functions */
256 trb
->Base
.Delete
= delete_texture_wrapper
;
257 trb
->Base
.AllocStorage
= NULL
; /* illegal! */
258 trb
->Base
.GetRow
= texture_get_row
;
259 trb
->Base
.GetValues
= texture_get_values
;
260 trb
->Base
.PutRow
= texture_put_row
;
261 trb
->Base
.PutMonoRow
= texture_put_mono_row
;
262 trb
->Base
.PutValues
= texture_put_values
;
263 trb
->Base
.PutMonoValues
= texture_put_mono_values
;
265 /* update attachment point */
266 att
->Renderbuffer
= &(trb
->Base
);
272 * Update the renderbuffer wrapper for rendering to a texture.
273 * For example, update the width, height of the RB based on the texture size,
274 * update the internal format info, etc.
277 update_wrapper(GLcontext
*ctx
, const struct gl_renderbuffer_attachment
*att
)
279 struct texture_renderbuffer
*trb
280 = (struct texture_renderbuffer
*) att
->Renderbuffer
;
284 trb
->TexImage
= att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
285 ASSERT(trb
->TexImage
);
287 trb
->Store
= trb
->TexImage
->TexFormat
->StoreTexel
;
290 trb
->Zoffset
= att
->Zoffset
;
292 trb
->Base
.Width
= trb
->TexImage
->Width
;
293 trb
->Base
.Height
= trb
->TexImage
->Height
;
294 trb
->Base
.InternalFormat
= trb
->TexImage
->InternalFormat
;
295 /* XXX may need more special cases here */
296 if (trb
->TexImage
->TexFormat
->BaseFormat
== GL_DEPTH_STENCIL_EXT
) {
297 trb
->Base
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
298 trb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
300 else if (trb
->TexImage
->TexFormat
->BaseFormat
== GL_DEPTH_COMPONENT
) {
301 trb
->Base
._ActualFormat
= GL_DEPTH_COMPONENT
;
302 trb
->Base
.DataType
= GL_FLOAT
;
305 trb
->Base
._ActualFormat
= trb
->TexImage
->InternalFormat
;
306 trb
->Base
.DataType
= CHAN_TYPE
;
308 trb
->Base
._BaseFormat
= trb
->TexImage
->TexFormat
->BaseFormat
;
310 /* fix/avoid this assertion someday */
311 ASSERT(trb
->Base
._BaseFormat
== GL_RGB
||
312 trb
->Base
._BaseFormat
== GL_RGBA
||
313 trb
->Base
._BaseFormat
== GL_DEPTH_COMPONENT
);
315 trb
->Base
.Data
= trb
->TexImage
->Data
;
317 trb
->Base
.RedBits
= trb
->TexImage
->TexFormat
->RedBits
;
318 trb
->Base
.GreenBits
= trb
->TexImage
->TexFormat
->GreenBits
;
319 trb
->Base
.BlueBits
= trb
->TexImage
->TexFormat
->BlueBits
;
320 trb
->Base
.AlphaBits
= trb
->TexImage
->TexFormat
->AlphaBits
;
321 trb
->Base
.DepthBits
= trb
->TexImage
->TexFormat
->DepthBits
;
327 * Called when rendering to a texture image begins, or when changing
328 * the dest mipmap level, cube face, etc.
329 * This is a fallback routine for software render-to-texture.
331 * Called via the glRenderbufferTexture1D/2D/3D() functions
332 * and elsewhere (such as glTexImage2D).
334 * The image we're rendering into is
335 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
336 * It'll never be NULL.
338 * \param fb the framebuffer object the texture is being bound to
339 * \param att the fb attachment point of the texture
341 * \sa _mesa_framebuffer_renderbuffer
344 _mesa_render_texture(GLcontext
*ctx
,
345 struct gl_framebuffer
*fb
,
346 struct gl_renderbuffer_attachment
*att
)
348 if (!att
->Renderbuffer
) {
349 wrap_texture(ctx
, att
);
351 update_wrapper(ctx
, att
);
356 _mesa_finish_render_texture(GLcontext
*ctx
,
357 struct gl_renderbuffer_attachment
*att
)
360 /* The renderbuffer texture wrapper will get deleted by the
361 * normal mechanism for deleting renderbuffers.