9c21e03515aeebc0bf5a8bc988cf8979ceb12553
[mesa.git] / src / mesa / main / texrender.c
1
2 #include "context.h"
3 #include "fbobject.h"
4 #include "texrender.h"
5 #include "renderbuffer.h"
6
7
8 /*
9 * Render-to-texture code for GL_EXT_framebuffer_object
10 */
11
12
13 /**
14 * Derived from gl_renderbuffer class
15 */
16 struct texture_renderbuffer
17 {
18 struct gl_renderbuffer Base; /* Base class object */
19 struct gl_texture_image *TexImage;
20 StoreTexelFunc Store;
21 GLint Zoffset;
22 };
23
24
25
26 static void
27 texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
28 GLint x, GLint y, void *values)
29 {
30 const struct texture_renderbuffer *trb
31 = (const struct texture_renderbuffer *) rb;
32 const GLint z = trb->Zoffset;
33 GLchan *rgbaOut = (GLchan *) values;
34 GLuint i;
35 for (i = 0; i < count; i++) {
36 trb->TexImage->FetchTexelc(trb->TexImage, x + i, y, z, rgbaOut + 4 * i);
37 }
38 }
39
40 static void
41 texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
42 const GLint x[], const GLint y[], void *values)
43 {
44 const struct texture_renderbuffer *trb
45 = (const struct texture_renderbuffer *) rb;
46 const GLint z = trb->Zoffset;
47 GLchan *rgbaOut = (GLchan *) values;
48 GLuint i;
49 for (i = 0; i < count; i++) {
50 trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i], z,
51 rgbaOut + 4 * i);
52 }
53 }
54
55 static void
56 texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
57 GLint x, GLint y, const void *values, const GLubyte *mask)
58 {
59 const struct texture_renderbuffer *trb
60 = (const struct texture_renderbuffer *) rb;
61 const GLint z = trb->Zoffset;
62 const GLchan *rgba = (const GLchan *) values;
63 GLuint i;
64 for (i = 0; i < count; i++) {
65 if (!mask || mask[i]) {
66 trb->Store(trb->TexImage, x + i, y, z, rgba);
67 }
68 rgba += 4;
69 }
70 }
71
72 static void
73 texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
74 GLint x, GLint y, const void *value, const GLubyte *mask)
75 {
76 const struct texture_renderbuffer *trb
77 = (const struct texture_renderbuffer *) rb;
78 const GLint z = trb->Zoffset;
79 const GLchan *rgba = (const GLchan *) value;
80 GLuint i;
81 for (i = 0; i < count; i++) {
82 if (!mask || mask[i]) {
83 trb->Store(trb->TexImage, x + i, y, z, rgba);
84 }
85 }
86 }
87
88 static void
89 texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
90 const GLint x[], const GLint y[], const void *values,
91 const GLubyte *mask)
92 {
93 const struct texture_renderbuffer *trb
94 = (const struct texture_renderbuffer *) rb;
95 const GLint z = trb->Zoffset;
96 const GLchan *rgba = (const GLchan *) values;
97 GLuint i;
98 for (i = 0; i < count; i++) {
99 if (!mask || mask[i]) {
100 trb->Store(trb->TexImage, x[i], y[i], z, rgba);
101 }
102 rgba += 4;
103 }
104 }
105
106 static void
107 texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb,
108 GLuint count, const GLint x[], const GLint y[],
109 const void *value, const GLubyte *mask)
110 {
111 const struct texture_renderbuffer *trb
112 = (const struct texture_renderbuffer *) rb;
113 const GLint z = trb->Zoffset;
114 const GLchan *rgba = (const GLchan *) value;
115 GLuint i;
116 for (i = 0; i < count; i++) {
117 if (!mask || mask[i]) {
118 trb->Store(trb->TexImage, x[i], y[i], z, rgba);
119 }
120 }
121 }
122
123
124 static void
125 delete_texture_wrapper(struct gl_renderbuffer *rb)
126 {
127 _mesa_free(rb);
128 }
129
130
131 /**
132 * If a render buffer attachment specifies a texture image, we'll use
133 * this function to make a gl_renderbuffer wrapper around the texture image.
134 * This allows other parts of Mesa to access the texture image as if it
135 * was a renderbuffer.
136 */
137 static void
138 wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
139 {
140 struct texture_renderbuffer *trb;
141 const GLuint name = 0;
142
143 ASSERT(att->Type == GL_TEXTURE);
144 ASSERT(att->Renderbuffer == NULL);
145 /*
146 ASSERT(att->Complete);
147 */
148
149 trb = CALLOC_STRUCT(texture_renderbuffer);
150 if (!trb) {
151 _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
152 return;
153 }
154
155 _mesa_init_renderbuffer(&trb->Base, name);
156
157 trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
158 assert(trb->TexImage);
159
160 trb->Store = trb->TexImage->TexFormat->StoreTexel;
161 assert(trb->Store);
162
163 trb->Zoffset = att->Zoffset;
164
165 trb->Base.Width = trb->TexImage->Width;
166 trb->Base.Height = trb->TexImage->Height;
167 trb->Base.InternalFormat = trb->TexImage->InternalFormat; /* XXX fix? */
168 trb->Base._BaseFormat = trb->TexImage->TexFormat->BaseFormat;
169 #if 0
170 /* fix/avoid this assertion someday */
171 assert(trb->Base._BaseFormat == GL_RGB ||
172 trb->Base._BaseFormat == GL_RGBA ||
173 trb->Base._BaseFormat == GL_DEPTH_COMPONENT);
174 #endif
175 trb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix! */
176 trb->Base.Data = trb->TexImage->Data;
177
178 trb->Base.GetRow = texture_get_row;
179 trb->Base.GetValues = texture_get_values;
180 trb->Base.PutRow = texture_put_row;
181 trb->Base.PutMonoRow = texture_put_mono_row;
182 trb->Base.PutValues = texture_put_values;
183 trb->Base.PutMonoValues = texture_put_mono_values;
184
185 trb->Base.Delete = delete_texture_wrapper;
186 trb->Base.AllocStorage = NULL; /* illegal! */
187
188 /* XXX fix these */
189 trb->Base.RedBits = trb->TexImage->TexFormat->RedBits;
190 trb->Base.GreenBits = trb->TexImage->TexFormat->GreenBits;
191 trb->Base.BlueBits = trb->TexImage->TexFormat->BlueBits;
192 trb->Base.AlphaBits = trb->TexImage->TexFormat->AlphaBits;
193 trb->Base.DepthBits = trb->TexImage->TexFormat->DepthBits;
194
195 att->Renderbuffer = &(trb->Base);
196 }
197
198
199
200 /**
201 * Software fallback for ctx->Driver.RenderbufferTexture.
202 * This is called via the glRenderbufferTexture1D/2D/3D() functions.
203 * If we're unbinding a texture, texObj will be NULL.
204 * The framebuffer of interest is ctx->DrawBuffer.
205 * \sa _mesa_framebuffer_renderbuffer
206 */
207 void
208 _mesa_renderbuffer_texture(GLcontext *ctx,
209 struct gl_renderbuffer_attachment *att,
210 struct gl_texture_object *texObj,
211 GLenum texTarget, GLuint level, GLuint zoffset)
212 {
213 if (texObj) {
214 _mesa_set_texture_attachment(ctx, att, texObj,
215 texTarget, level, zoffset);
216
217 wrap_texture(ctx, att);
218 }
219 else {
220 _mesa_remove_attachment(ctx, att);
221 }
222 }