GL_INTENSITY case was incorrect in extract_float_rgba()
[mesa.git] / src / mesa / swrast / s_texstore.c
1 /* $Id: s_texstore.c,v 1.2 2001/03/28 20:40:52 gareth Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 /*
28 * Authors:
29 * Brian Paul
30 */
31
32
33 /*
34 * The functions in this file are mostly related to software texture fallbacks.
35 * This includes texture image transfer/packing and texel fetching.
36 * Hardware drivers will likely override most of this.
37 */
38
39
40
41 #include "colormac.h"
42 #include "context.h"
43 #include "convolve.h"
44 #include "image.h"
45 #include "macros.h"
46 #include "mem.h"
47 #include "texformat.h"
48 #include "teximage.h"
49
50 #include "s_context.h"
51 #include "s_depth.h"
52 #include "s_span.h"
53
54 /*
55 * Read an RGBA image from the frame buffer.
56 * This is used by glCopyTex[Sub]Image[12]D().
57 * Input: ctx - the context
58 * x, y - lower left corner
59 * width, height - size of region to read
60 * Return: pointer to block of GL_RGBA, GLchan data.
61 */
62 static GLchan *
63 read_color_image( GLcontext *ctx, GLint x, GLint y,
64 GLsizei width, GLsizei height )
65 {
66 SWcontext *swrast = SWRAST_CONTEXT(ctx);
67 GLint stride, i;
68 GLchan *image, *dst;
69
70 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
71 if (!image)
72 return NULL;
73
74 /* Select buffer to read from */
75 (*swrast->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
76 ctx->Pixel.DriverReadBuffer );
77
78 RENDER_START(swrast,ctx);
79
80 dst = image;
81 stride = width * 4;
82 for (i = 0; i < height; i++) {
83 _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
84 (GLchan (*)[4]) dst );
85 dst += stride;
86 }
87
88 RENDER_FINISH(swrast,ctx);
89
90 /* Read from draw buffer (the default) */
91 (*swrast->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
92 ctx->Color.DriverDrawBuffer );
93
94 return image;
95 }
96
97
98 /*
99 * As above, but read data from depth buffer.
100 */
101 static GLfloat *
102 read_depth_image( GLcontext *ctx, GLint x, GLint y,
103 GLsizei width, GLsizei height )
104 {
105 SWcontext *swrast = SWRAST_CONTEXT(ctx);
106 GLfloat *image, *dst;
107 GLint i;
108
109 image = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
110 if (!image)
111 return NULL;
112
113 RENDER_START(swrast,ctx);
114
115 dst = image;
116 for (i = 0; i < height; i++) {
117 _mesa_read_depth_span_float(ctx, width, x, y + i, dst);
118 dst += width;
119 }
120
121 RENDER_FINISH(swrast,ctx);
122
123 return image;
124 }
125
126
127
128 static GLboolean
129 is_depth_format(GLenum format)
130 {
131 switch (format) {
132 case GL_DEPTH_COMPONENT:
133 case GL_DEPTH_COMPONENT16_SGIX:
134 case GL_DEPTH_COMPONENT24_SGIX:
135 case GL_DEPTH_COMPONENT32_SGIX:
136 return GL_TRUE;
137 default:
138 return GL_FALSE;
139 }
140 }
141
142
143 /*
144 * Fallback for Driver.CopyTexImage1D().
145 */
146 void
147 _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
148 GLenum internalFormat,
149 GLint x, GLint y, GLsizei width, GLint border )
150 {
151 struct gl_texture_unit *texUnit;
152 struct gl_texture_object *texObj;
153 struct gl_texture_image *texImage;
154
155 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
156 texObj = _mesa_select_tex_object(ctx, texUnit, target);
157 ASSERT(texObj);
158 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
159 ASSERT(texImage);
160
161 ASSERT(ctx->Driver.TexImage1D);
162
163 if (is_depth_format(internalFormat)) {
164 /* read depth image from framebuffer */
165 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
166 if (!image) {
167 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
168 return;
169 }
170
171 /* call glTexImage1D to redefine the texture */
172 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
173 width, border,
174 GL_DEPTH_COMPONENT, GL_FLOAT, image,
175 &_mesa_native_packing, texObj, texImage);
176 FREE(image);
177 }
178 else {
179 /* read RGBA image from framebuffer */
180 GLchan *image = read_color_image(ctx, x, y, width, 1);
181 if (!image) {
182 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
183 return;
184 }
185
186 /* call glTexImage1D to redefine the texture */
187 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
188 width, border,
189 GL_RGBA, CHAN_TYPE, image,
190 &_mesa_native_packing, texObj, texImage);
191 FREE(image);
192 }
193 }
194
195
196 /*
197 * Fallback for Driver.CopyTexImage2D().
198 */
199 void
200 _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
201 GLenum internalFormat,
202 GLint x, GLint y, GLsizei width, GLsizei height,
203 GLint border )
204 {
205 struct gl_texture_unit *texUnit;
206 struct gl_texture_object *texObj;
207 struct gl_texture_image *texImage;
208
209 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
210 texObj = _mesa_select_tex_object(ctx, texUnit, target);
211 ASSERT(texObj);
212 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
213 ASSERT(texImage);
214
215 ASSERT(ctx->Driver.TexImage2D);
216
217 if (is_depth_format(internalFormat)) {
218 /* read depth image from framebuffer */
219 GLfloat *image = read_depth_image(ctx, x, y, width, height);
220 if (!image) {
221 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
222 return;
223 }
224
225 /* call glTexImage2D to redefine the texture */
226 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
227 width, height, border,
228 GL_DEPTH_COMPONENT, GL_FLOAT, image,
229 &_mesa_native_packing, texObj, texImage);
230 FREE(image);
231 }
232 else {
233 /* read RGBA image from framebuffer */
234 GLchan *image = read_color_image(ctx, x, y, width, height);
235 if (!image) {
236 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
237 return;
238 }
239
240 /* call glTexImage2D to redefine the texture */
241 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
242 width, height, border,
243 GL_RGBA, CHAN_TYPE, image,
244 &_mesa_native_packing, texObj, texImage);
245 FREE(image);
246 }
247 }
248
249
250 /*
251 * Fallback for Driver.CopyTexSubImage1D().
252 */
253 void
254 _swrast_copy_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
255 GLint xoffset, GLint x, GLint y, GLsizei width)
256 {
257 struct gl_texture_unit *texUnit;
258 struct gl_texture_object *texObj;
259 struct gl_texture_image *texImage;
260
261 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
262 texObj = _mesa_select_tex_object(ctx, texUnit, target);
263 ASSERT(texObj);
264 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
265 ASSERT(texImage);
266
267 ASSERT(ctx->Driver.TexImage1D);
268
269 if (texImage->Format != GL_DEPTH_COMPONENT) {
270 /* read RGBA image from framebuffer */
271 GLchan *image = read_color_image(ctx, x, y, width, 1);
272 if (!image) {
273 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
274 return;
275 }
276
277 /* now call glTexSubImage1D to do the real work */
278 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
279 GL_RGBA, CHAN_TYPE, image,
280 &_mesa_native_packing, texObj, texImage);
281 FREE(image);
282 }
283 else {
284 /* read depth image from framebuffer */
285 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
286 if (!image) {
287 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
288 return;
289 }
290
291 /* call glTexSubImage1D to redefine the texture */
292 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
293 GL_DEPTH_COMPONENT, GL_FLOAT, image,
294 &_mesa_native_packing, texObj, texImage);
295 FREE(image);
296 }
297 }
298
299
300 /*
301 * Fallback for Driver.CopyTexSubImage2D().
302 */
303 void
304 _swrast_copy_texsubimage2d( GLcontext *ctx,
305 GLenum target, GLint level,
306 GLint xoffset, GLint yoffset,
307 GLint x, GLint y, GLsizei width, GLsizei height )
308 {
309 struct gl_texture_unit *texUnit;
310 struct gl_texture_object *texObj;
311 struct gl_texture_image *texImage;
312
313 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
314 texObj = _mesa_select_tex_object(ctx, texUnit, target);
315 ASSERT(texObj);
316 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
317 ASSERT(texImage);
318
319 ASSERT(ctx->Driver.TexImage2D);
320
321 if (texImage->Format != GL_DEPTH_COMPONENT) {
322 /* read RGBA image from framebuffer */
323 GLchan *image = read_color_image(ctx, x, y, width, height);
324 if (!image) {
325 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
326 return;
327 }
328
329 /* now call glTexSubImage2D to do the real work */
330 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
331 xoffset, yoffset, width, height,
332 GL_RGBA, CHAN_TYPE, image,
333 &_mesa_native_packing, texObj, texImage);
334 FREE(image);
335 }
336 else {
337 /* read depth image from framebuffer */
338 GLfloat *image = read_depth_image(ctx, x, y, width, height);
339 if (!image) {
340 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
341 return;
342 }
343
344 /* call glTexImage1D to redefine the texture */
345 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
346 xoffset, yoffset, width, height,
347 GL_DEPTH_COMPONENT, GL_FLOAT, image,
348 &_mesa_native_packing, texObj, texImage);
349 FREE(image);
350 }
351 }
352
353
354 /*
355 * Fallback for Driver.CopyTexSubImage3D().
356 */
357 void
358 _swrast_copy_texsubimage3d( GLcontext *ctx,
359 GLenum target, GLint level,
360 GLint xoffset, GLint yoffset, GLint zoffset,
361 GLint x, GLint y, GLsizei width, GLsizei height )
362 {
363 struct gl_texture_unit *texUnit;
364 struct gl_texture_object *texObj;
365 struct gl_texture_image *texImage;
366
367 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
368 texObj = _mesa_select_tex_object(ctx, texUnit, target);
369 ASSERT(texObj);
370 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
371 ASSERT(texImage);
372
373 ASSERT(ctx->Driver.TexImage3D);
374
375 if (texImage->Format != GL_DEPTH_COMPONENT) {
376 /* read RGBA image from framebuffer */
377 GLchan *image = read_color_image(ctx, x, y, width, height);
378 if (!image) {
379 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
380 return;
381 }
382
383 /* now call glTexSubImage3D to do the real work */
384 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
385 xoffset, yoffset, zoffset, width, height, 1,
386 GL_RGBA, CHAN_TYPE, image,
387 &_mesa_native_packing, texObj, texImage);
388 FREE(image);
389 }
390 else {
391 /* read depth image from framebuffer */
392 GLfloat *image = read_depth_image(ctx, x, y, width, height);
393 if (!image) {
394 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
395 return;
396 }
397
398 /* call glTexImage1D to redefine the texture */
399 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
400 xoffset, yoffset, zoffset, width, height, 1,
401 GL_DEPTH_COMPONENT, GL_FLOAT, image,
402 &_mesa_native_packing, texObj, texImage);
403 FREE(image);
404 }
405 }