e87945ab42db298ecc6bf7fd0b6b4910a1634239
[mesa.git] / src / mesa / swrast / s_texstore.c
1 /* $Id: s_texstore.c,v 1.10 2003/03/01 01:50:26 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 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 "glheader.h"
42 #include "imports.h"
43 #include "colormac.h"
44 #include "context.h"
45 #include "convolve.h"
46 #include "image.h"
47 #include "macros.h"
48 #include "texformat.h"
49 #include "teximage.h"
50 #include "texstore.h"
51
52 #include "s_context.h"
53 #include "s_depth.h"
54 #include "s_span.h"
55
56 /*
57 * Read an RGBA image from the frame buffer.
58 * This is used by glCopyTex[Sub]Image[12]D().
59 * Input: ctx - the context
60 * x, y - lower left corner
61 * width, height - size of region to read
62 * Return: pointer to block of GL_RGBA, GLchan data.
63 */
64 static GLchan *
65 read_color_image( GLcontext *ctx, GLint x, GLint y,
66 GLsizei width, GLsizei height )
67 {
68 SWcontext *swrast = SWRAST_CONTEXT(ctx);
69 GLint stride, i;
70 GLchan *image, *dst;
71
72 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
73 if (!image)
74 return NULL;
75
76 /* Select buffer to read from */
77 _swrast_use_read_buffer(ctx);
78
79 RENDER_START(swrast,ctx);
80
81 dst = image;
82 stride = width * 4;
83 for (i = 0; i < height; i++) {
84 _mesa_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
85 (GLchan (*)[4]) dst );
86 dst += stride;
87 }
88
89 RENDER_FINISH(swrast,ctx);
90
91 /* Read from draw buffer (the default) */
92 _swrast_use_draw_buffer(ctx);
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 /* GL_SGIS_generate_mipmap */
195 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
196 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
197 }
198 }
199
200
201 /*
202 * Fallback for Driver.CopyTexImage2D().
203 */
204 void
205 _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
206 GLenum internalFormat,
207 GLint x, GLint y, GLsizei width, GLsizei height,
208 GLint border )
209 {
210 struct gl_texture_unit *texUnit;
211 struct gl_texture_object *texObj;
212 struct gl_texture_image *texImage;
213
214 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
215 texObj = _mesa_select_tex_object(ctx, texUnit, target);
216 ASSERT(texObj);
217 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
218 ASSERT(texImage);
219
220 ASSERT(ctx->Driver.TexImage2D);
221
222 if (is_depth_format(internalFormat)) {
223 /* read depth image from framebuffer */
224 GLfloat *image = read_depth_image(ctx, x, y, width, height);
225 if (!image) {
226 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
227 return;
228 }
229
230 /* call glTexImage2D to redefine the texture */
231 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
232 width, height, border,
233 GL_DEPTH_COMPONENT, GL_FLOAT, image,
234 &_mesa_native_packing, texObj, texImage);
235 FREE(image);
236 }
237 else {
238 /* read RGBA image from framebuffer */
239 GLchan *image = read_color_image(ctx, x, y, width, height);
240 if (!image) {
241 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
242 return;
243 }
244
245 /* call glTexImage2D to redefine the texture */
246 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
247 width, height, border,
248 GL_RGBA, CHAN_TYPE, image,
249 &_mesa_native_packing, texObj, texImage);
250 FREE(image);
251 }
252
253 /* GL_SGIS_generate_mipmap */
254 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
255 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
256 }
257 }
258
259
260 /*
261 * Fallback for Driver.CopyTexSubImage1D().
262 */
263 void
264 _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
265 GLint xoffset, GLint x, GLint y, GLsizei width )
266 {
267 struct gl_texture_unit *texUnit;
268 struct gl_texture_object *texObj;
269 struct gl_texture_image *texImage;
270
271 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
272 texObj = _mesa_select_tex_object(ctx, texUnit, target);
273 ASSERT(texObj);
274 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
275 ASSERT(texImage);
276
277 ASSERT(ctx->Driver.TexImage1D);
278
279 if (texImage->Format == GL_DEPTH_COMPONENT) {
280 /* read depth image from framebuffer */
281 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
282 if (!image) {
283 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
284 return;
285 }
286
287 /* call glTexSubImage1D to redefine the texture */
288 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
289 GL_DEPTH_COMPONENT, GL_FLOAT, image,
290 &_mesa_native_packing, texObj, texImage);
291 FREE(image);
292 }
293 else {
294 /* read RGBA image from framebuffer */
295 GLchan *image = read_color_image(ctx, x, y, width, 1);
296 if (!image) {
297 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
298 return;
299 }
300
301 /* now call glTexSubImage1D to do the real work */
302 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
303 GL_RGBA, CHAN_TYPE, image,
304 &_mesa_native_packing, texObj, texImage);
305 FREE(image);
306 }
307
308 /* GL_SGIS_generate_mipmap */
309 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
310 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
311 }
312 }
313
314
315 /*
316 * Fallback for Driver.CopyTexSubImage2D().
317 */
318 void
319 _swrast_copy_texsubimage2d( GLcontext *ctx,
320 GLenum target, GLint level,
321 GLint xoffset, GLint yoffset,
322 GLint x, GLint y, GLsizei width, GLsizei height )
323 {
324 struct gl_texture_unit *texUnit;
325 struct gl_texture_object *texObj;
326 struct gl_texture_image *texImage;
327
328 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
329 texObj = _mesa_select_tex_object(ctx, texUnit, target);
330 ASSERT(texObj);
331 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
332 ASSERT(texImage);
333
334 ASSERT(ctx->Driver.TexImage2D);
335
336 if (texImage->Format == GL_DEPTH_COMPONENT) {
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 else {
352 /* read RGBA image from framebuffer */
353 GLchan *image = read_color_image(ctx, x, y, width, height);
354 if (!image) {
355 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
356 return;
357 }
358
359 /* now call glTexSubImage2D to do the real work */
360 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
361 xoffset, yoffset, width, height,
362 GL_RGBA, CHAN_TYPE, image,
363 &_mesa_native_packing, texObj, texImage);
364 FREE(image);
365 }
366
367 /* GL_SGIS_generate_mipmap */
368 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
369 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
370 }
371 }
372
373
374 /*
375 * Fallback for Driver.CopyTexSubImage3D().
376 */
377 void
378 _swrast_copy_texsubimage3d( GLcontext *ctx,
379 GLenum target, GLint level,
380 GLint xoffset, GLint yoffset, GLint zoffset,
381 GLint x, GLint y, GLsizei width, GLsizei height )
382 {
383 struct gl_texture_unit *texUnit;
384 struct gl_texture_object *texObj;
385 struct gl_texture_image *texImage;
386
387 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
388 texObj = _mesa_select_tex_object(ctx, texUnit, target);
389 ASSERT(texObj);
390 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
391 ASSERT(texImage);
392
393 ASSERT(ctx->Driver.TexImage3D);
394
395 if (texImage->Format == GL_DEPTH_COMPONENT) {
396 /* read depth image from framebuffer */
397 GLfloat *image = read_depth_image(ctx, x, y, width, height);
398 if (!image) {
399 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
400 return;
401 }
402
403 /* call glTexImage1D to redefine the texture */
404 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
405 xoffset, yoffset, zoffset, width, height, 1,
406 GL_DEPTH_COMPONENT, GL_FLOAT, image,
407 &_mesa_native_packing, texObj, texImage);
408 FREE(image);
409 }
410 else {
411 /* read RGBA image from framebuffer */
412 GLchan *image = read_color_image(ctx, x, y, width, height);
413 if (!image) {
414 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
415 return;
416 }
417
418 /* now call glTexSubImage3D to do the real work */
419 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
420 xoffset, yoffset, zoffset, width, height, 1,
421 GL_RGBA, CHAN_TYPE, image,
422 &_mesa_native_packing, texObj, texImage);
423 FREE(image);
424 }
425
426 /* GL_SGIS_generate_mipmap */
427 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
428 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
429 }
430 }