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 static inline struct texture_renderbuffer
*
36 texture_renderbuffer(struct gl_renderbuffer
*rb
)
38 return (struct texture_renderbuffer
*) rb
;
45 store_nop(struct swrast_texture_image
*texImage
,
46 GLint col
, GLint row
, GLint img
,
53 delete_texture_wrapper(struct gl_renderbuffer
*rb
)
55 ASSERT(rb
->RefCount
== 0);
61 * This function creates a renderbuffer object which wraps a texture image.
62 * The new renderbuffer is plugged into the given attachment point.
63 * This allows rendering into the texture as if it were a renderbuffer.
66 wrap_texture(struct gl_context
*ctx
, struct gl_renderbuffer_attachment
*att
)
68 struct texture_renderbuffer
*trb
;
69 const GLuint name
= 0;
71 ASSERT(att
->Type
== GL_TEXTURE
);
72 ASSERT(att
->Renderbuffer
== NULL
);
74 trb
= CALLOC_STRUCT(texture_renderbuffer
);
76 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "wrap_texture");
80 /* init base gl_renderbuffer fields */
81 _mesa_init_renderbuffer(&trb
->Base
, name
);
82 /* plug in our texture_renderbuffer-specific functions */
83 trb
->Base
.Delete
= delete_texture_wrapper
;
84 trb
->Base
.AllocStorage
= NULL
; /* illegal! */
86 /* update attachment point */
87 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &(trb
->Base
));
91 * Update the renderbuffer wrapper for rendering to a texture.
92 * For example, update the width, height of the RB based on the texture size,
93 * update the internal format info, etc.
96 update_wrapper(struct gl_context
*ctx
, struct gl_renderbuffer_attachment
*att
)
98 struct texture_renderbuffer
*trb
99 = (struct texture_renderbuffer
*) att
->Renderbuffer
;
104 trb
->TexImage
= swrast_texture_image(_mesa_get_attachment_teximage(att
));
105 ASSERT(trb
->TexImage
);
107 trb
->Store
= _mesa_get_texel_store_func(trb
->TexImage
->Base
.TexFormat
);
109 /* we'll never draw into some textures (compressed formats) */
110 trb
->Store
= store_nop
;
113 if (!trb
->TexImage
->FetchTexel
) {
114 _mesa_update_fetch_functions(trb
->TexImage
->Base
.TexObject
);
116 trb
->Fetch
= trb
->TexImage
->FetchTexel
;
119 if (att
->Texture
->Target
== GL_TEXTURE_1D_ARRAY_EXT
) {
120 trb
->Yoffset
= att
->Zoffset
;
125 trb
->Zoffset
= att
->Zoffset
;
128 trb
->Base
.Width
= trb
->TexImage
->Base
.Width
;
129 trb
->Base
.Height
= trb
->TexImage
->Base
.Height
;
130 trb
->Base
.InternalFormat
= trb
->TexImage
->Base
.InternalFormat
;
131 trb
->Base
.Format
= trb
->TexImage
->Base
.TexFormat
;
133 /* Set the gl_renderbuffer::Data field so that mapping the buffer
134 * in renderbuffer.c succeeds.
136 if (att
->Texture
->Target
== GL_TEXTURE_3D
||
137 att
->Texture
->Target
== GL_TEXTURE_2D_ARRAY_EXT
) {
138 trb
->Base
.Buffer
= trb
->TexImage
->Buffer
+
139 trb
->TexImage
->ImageOffsets
[trb
->Zoffset
] *
140 _mesa_get_format_bytes(trb
->TexImage
->Base
.TexFormat
);
143 trb
->Base
.Buffer
= trb
->TexImage
->Buffer
;
146 /* XXX may need more special cases here */
147 switch (trb
->TexImage
->Base
.TexFormat
) {
148 case MESA_FORMAT_Z24_S8
:
149 trb
->Base
._BaseFormat
= GL_DEPTH_STENCIL
;
151 case MESA_FORMAT_S8_Z24
:
152 trb
->Base
._BaseFormat
= GL_DEPTH_STENCIL
;
154 case MESA_FORMAT_Z24_X8
:
155 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
157 case MESA_FORMAT_X8_Z24
:
158 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
160 case MESA_FORMAT_Z16
:
161 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
163 case MESA_FORMAT_Z32
:
164 trb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
166 /* SRGB formats pre EXT_framebuffer_sRGB don't do sRGB translations on FBO readback */
167 case MESA_FORMAT_SRGB8
:
168 trb
->Fetch
= _mesa_get_texel_fetch_func(MESA_FORMAT_RGB888
, _mesa_get_texture_dimensions(att
->Texture
->Target
));
169 trb
->Base
._BaseFormat
= GL_RGBA
;
171 case MESA_FORMAT_SRGBA8
:
172 trb
->Fetch
= _mesa_get_texel_fetch_func(MESA_FORMAT_RGBA8888
, _mesa_get_texture_dimensions(att
->Texture
->Target
));
173 trb
->Base
._BaseFormat
= GL_RGBA
;
175 case MESA_FORMAT_SARGB8
:
176 trb
->Fetch
= _mesa_get_texel_fetch_func(MESA_FORMAT_ARGB8888
, _mesa_get_texture_dimensions(att
->Texture
->Target
));
177 trb
->Base
._BaseFormat
= GL_RGBA
;
180 trb
->Base
._BaseFormat
= GL_RGBA
;
187 * Called when rendering to a texture image begins, or when changing
188 * the dest mipmap level, cube face, etc.
189 * This is a fallback routine for software render-to-texture.
191 * Called via the glRenderbufferTexture1D/2D/3D() functions
192 * and elsewhere (such as glTexImage2D).
194 * The image we're rendering into is
195 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
196 * It'll never be NULL.
198 * \param fb the framebuffer object the texture is being bound to
199 * \param att the fb attachment point of the texture
201 * \sa _mesa_framebuffer_renderbuffer
204 _swrast_render_texture(struct gl_context
*ctx
,
205 struct gl_framebuffer
*fb
,
206 struct gl_renderbuffer_attachment
*att
)
210 if (!att
->Renderbuffer
) {
211 wrap_texture(ctx
, att
);
213 update_wrapper(ctx
, att
);
218 _swrast_finish_render_texture(struct gl_context
*ctx
,
219 struct gl_renderbuffer_attachment
*att
)
222 /* The renderbuffer texture wrapper will get deleted by the
223 * normal mechanism for deleting renderbuffers.