1adf281fbd5ce28f9df527831751c1e1c4c5b8c6
[mesa.git] / src / mesa / swrast / s_texrender.c
1
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"
11
12
13 /*
14 * Render-to-texture code for GL_EXT_framebuffer_object
15 */
16
17
18 /**
19 * Derived from gl_renderbuffer class
20 */
21 struct texture_renderbuffer
22 {
23 struct gl_renderbuffer Base; /**< Base class object */
24 struct swrast_texture_image *TexImage;
25 StoreTexelFunc Store;
26 FetchTexelFunc Fetch;
27 GLint Yoffset; /**< Layer for 1D array textures. */
28 GLint Zoffset; /**< Layer for 2D array textures, or slice
29 * for 3D textures
30 */
31 };
32
33
34 /** cast wrapper */
35 static inline struct texture_renderbuffer *
36 texture_renderbuffer(struct gl_renderbuffer *rb)
37 {
38 return (struct texture_renderbuffer *) rb;
39 }
40
41
42
43
44 static void
45 store_nop(struct swrast_texture_image *texImage,
46 GLint col, GLint row, GLint img,
47 const void *texel)
48 {
49 }
50
51
52 static void
53 delete_texture_wrapper(struct gl_renderbuffer *rb)
54 {
55 ASSERT(rb->RefCount == 0);
56 free(rb);
57 }
58
59
60 /**
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.
64 */
65 static void
66 wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
67 {
68 struct texture_renderbuffer *trb;
69 const GLuint name = 0;
70
71 ASSERT(att->Type == GL_TEXTURE);
72 ASSERT(att->Renderbuffer == NULL);
73
74 trb = CALLOC_STRUCT(texture_renderbuffer);
75 if (!trb) {
76 _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
77 return;
78 }
79
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! */
85
86 /* update attachment point */
87 _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base));
88 }
89
90 /**
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.
94 */
95 static void
96 update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
97 {
98 struct texture_renderbuffer *trb
99 = (struct texture_renderbuffer *) att->Renderbuffer;
100
101 (void) ctx;
102 ASSERT(trb);
103
104 trb->TexImage = swrast_texture_image(_mesa_get_attachment_teximage(att));
105 ASSERT(trb->TexImage);
106
107 trb->Store = _mesa_get_texel_store_func(trb->TexImage->Base.TexFormat);
108 if (!trb->Store) {
109 /* we'll never draw into some textures (compressed formats) */
110 trb->Store = store_nop;
111 }
112
113 if (!trb->TexImage->FetchTexel) {
114 _mesa_update_fetch_functions(trb->TexImage->Base.TexObject);
115 }
116 trb->Fetch = trb->TexImage->FetchTexel;
117 assert(trb->Fetch);
118
119 if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
120 trb->Yoffset = att->Zoffset;
121 trb->Zoffset = 0;
122 }
123 else {
124 trb->Yoffset = 0;
125 trb->Zoffset = att->Zoffset;
126 }
127
128 trb->Base.Width = trb->TexImage->Base.Width;
129 trb->Base.Height = trb->TexImage->Base.Height;
130 trb->Base.RowStride = trb->TexImage->RowStride;
131 trb->Base.InternalFormat = trb->TexImage->Base.InternalFormat;
132 trb->Base.Format = trb->TexImage->Base.TexFormat;
133
134 /* Set the gl_renderbuffer::Data field so that mapping the buffer
135 * in renderbuffer.c succeeds.
136 */
137 if (att->Texture->Target == GL_TEXTURE_3D ||
138 att->Texture->Target == GL_TEXTURE_2D_ARRAY_EXT) {
139 trb->Base.Data = trb->TexImage->Buffer +
140 trb->TexImage->ImageOffsets[trb->Zoffset] *
141 _mesa_get_format_bytes(trb->TexImage->Base.TexFormat);
142 }
143 else {
144 trb->Base.Data = trb->TexImage->Buffer;
145 }
146
147 /* XXX may need more special cases here */
148 switch (trb->TexImage->Base.TexFormat) {
149 case MESA_FORMAT_Z24_S8:
150 trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
151 trb->Base._BaseFormat = GL_DEPTH_STENCIL;
152 break;
153 case MESA_FORMAT_S8_Z24:
154 trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
155 trb->Base._BaseFormat = GL_DEPTH_STENCIL;
156 break;
157 case MESA_FORMAT_Z24_X8:
158 trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
159 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
160 break;
161 case MESA_FORMAT_X8_Z24:
162 trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
163 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
164 break;
165 case MESA_FORMAT_Z16:
166 trb->Base.DataType = GL_UNSIGNED_SHORT;
167 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
168 break;
169 case MESA_FORMAT_Z32:
170 trb->Base.DataType = GL_UNSIGNED_INT;
171 trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
172 break;
173 /* SRGB formats pre EXT_framebuffer_sRGB don't do sRGB translations on FBO readback */
174 case MESA_FORMAT_SRGB8:
175 trb->Fetch = _mesa_get_texel_fetch_func(MESA_FORMAT_RGB888, _mesa_get_texture_dimensions(att->Texture->Target));
176 trb->Base.DataType = CHAN_TYPE;
177 trb->Base._BaseFormat = GL_RGBA;
178 break;
179 case MESA_FORMAT_SRGBA8:
180 trb->Fetch = _mesa_get_texel_fetch_func(MESA_FORMAT_RGBA8888, _mesa_get_texture_dimensions(att->Texture->Target));
181 trb->Base.DataType = CHAN_TYPE;
182 trb->Base._BaseFormat = GL_RGBA;
183 break;
184 case MESA_FORMAT_SARGB8:
185 trb->Fetch = _mesa_get_texel_fetch_func(MESA_FORMAT_ARGB8888, _mesa_get_texture_dimensions(att->Texture->Target));
186 trb->Base.DataType = CHAN_TYPE;
187 trb->Base._BaseFormat = GL_RGBA;
188 break;
189 default:
190 trb->Base.DataType = CHAN_TYPE;
191 trb->Base._BaseFormat = GL_RGBA;
192 }
193 }
194
195
196
197 /**
198 * Called when rendering to a texture image begins, or when changing
199 * the dest mipmap level, cube face, etc.
200 * This is a fallback routine for software render-to-texture.
201 *
202 * Called via the glRenderbufferTexture1D/2D/3D() functions
203 * and elsewhere (such as glTexImage2D).
204 *
205 * The image we're rendering into is
206 * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
207 * It'll never be NULL.
208 *
209 * \param fb the framebuffer object the texture is being bound to
210 * \param att the fb attachment point of the texture
211 *
212 * \sa _mesa_framebuffer_renderbuffer
213 */
214 void
215 _swrast_render_texture(struct gl_context *ctx,
216 struct gl_framebuffer *fb,
217 struct gl_renderbuffer_attachment *att)
218 {
219 (void) fb;
220
221 if (!att->Renderbuffer) {
222 wrap_texture(ctx, att);
223 }
224 update_wrapper(ctx, att);
225 }
226
227
228 void
229 _swrast_finish_render_texture(struct gl_context *ctx,
230 struct gl_renderbuffer_attachment *att)
231 {
232 /* do nothing */
233 /* The renderbuffer texture wrapper will get deleted by the
234 * normal mechanism for deleting renderbuffers.
235 */
236 (void) ctx;
237 (void) att;
238 }