Header file clean-up:
[mesa.git] / src / mesa / swrast / s_texstore.c
1 /* $Id: s_texstore.c,v 1.9 2002/10/24 23:57:24 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 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 "imports.h"
46 #include "macros.h"
47 #include "texformat.h"
48 #include "teximage.h"
49 #include "texstore.h"
50
51 #include "s_context.h"
52 #include "s_depth.h"
53 #include "s_span.h"
54
55 /*
56 * Read an RGBA image from the frame buffer.
57 * This is used by glCopyTex[Sub]Image[12]D().
58 * Input: ctx - the context
59 * x, y - lower left corner
60 * width, height - size of region to read
61 * Return: pointer to block of GL_RGBA, GLchan data.
62 */
63 static GLchan *
64 read_color_image( GLcontext *ctx, GLint x, GLint y,
65 GLsizei width, GLsizei height )
66 {
67 SWcontext *swrast = SWRAST_CONTEXT(ctx);
68 GLint stride, i;
69 GLchan *image, *dst;
70
71 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
72 if (!image)
73 return NULL;
74
75 /* Select buffer to read from */
76 _swrast_use_read_buffer(ctx);
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_use_draw_buffer(ctx);
92
93 return image;
94 }
95
96
97 /*
98 * As above, but read data from depth buffer.
99 */
100 static GLfloat *
101 read_depth_image( GLcontext *ctx, GLint x, GLint y,
102 GLsizei width, GLsizei height )
103 {
104 SWcontext *swrast = SWRAST_CONTEXT(ctx);
105 GLfloat *image, *dst;
106 GLint i;
107
108 image = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
109 if (!image)
110 return NULL;
111
112 RENDER_START(swrast,ctx);
113
114 dst = image;
115 for (i = 0; i < height; i++) {
116 _mesa_read_depth_span_float(ctx, width, x, y + i, dst);
117 dst += width;
118 }
119
120 RENDER_FINISH(swrast,ctx);
121
122 return image;
123 }
124
125
126
127 static GLboolean
128 is_depth_format(GLenum format)
129 {
130 switch (format) {
131 case GL_DEPTH_COMPONENT:
132 case GL_DEPTH_COMPONENT16_SGIX:
133 case GL_DEPTH_COMPONENT24_SGIX:
134 case GL_DEPTH_COMPONENT32_SGIX:
135 return GL_TRUE;
136 default:
137 return GL_FALSE;
138 }
139 }
140
141
142 /*
143 * Fallback for Driver.CopyTexImage1D().
144 */
145 void
146 _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level,
147 GLenum internalFormat,
148 GLint x, GLint y, GLsizei width, GLint border )
149 {
150 struct gl_texture_unit *texUnit;
151 struct gl_texture_object *texObj;
152 struct gl_texture_image *texImage;
153
154 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
155 texObj = _mesa_select_tex_object(ctx, texUnit, target);
156 ASSERT(texObj);
157 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
158 ASSERT(texImage);
159
160 ASSERT(ctx->Driver.TexImage1D);
161
162 if (is_depth_format(internalFormat)) {
163 /* read depth image from framebuffer */
164 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
165 if (!image) {
166 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
167 return;
168 }
169
170 /* call glTexImage1D to redefine the texture */
171 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
172 width, border,
173 GL_DEPTH_COMPONENT, GL_FLOAT, image,
174 &_mesa_native_packing, texObj, texImage);
175 FREE(image);
176 }
177 else {
178 /* read RGBA image from framebuffer */
179 GLchan *image = read_color_image(ctx, x, y, width, 1);
180 if (!image) {
181 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
182 return;
183 }
184
185 /* call glTexImage1D to redefine the texture */
186 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat,
187 width, border,
188 GL_RGBA, CHAN_TYPE, image,
189 &_mesa_native_packing, texObj, texImage);
190 FREE(image);
191 }
192
193 /* GL_SGIS_generate_mipmap */
194 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
195 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
196 }
197 }
198
199
200 /*
201 * Fallback for Driver.CopyTexImage2D().
202 */
203 void
204 _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level,
205 GLenum internalFormat,
206 GLint x, GLint y, GLsizei width, GLsizei height,
207 GLint border )
208 {
209 struct gl_texture_unit *texUnit;
210 struct gl_texture_object *texObj;
211 struct gl_texture_image *texImage;
212
213 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
214 texObj = _mesa_select_tex_object(ctx, texUnit, target);
215 ASSERT(texObj);
216 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
217 ASSERT(texImage);
218
219 ASSERT(ctx->Driver.TexImage2D);
220
221 if (is_depth_format(internalFormat)) {
222 /* read depth image from framebuffer */
223 GLfloat *image = read_depth_image(ctx, x, y, width, height);
224 if (!image) {
225 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
226 return;
227 }
228
229 /* call glTexImage2D to redefine the texture */
230 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
231 width, height, border,
232 GL_DEPTH_COMPONENT, GL_FLOAT, image,
233 &_mesa_native_packing, texObj, texImage);
234 FREE(image);
235 }
236 else {
237 /* read RGBA image from framebuffer */
238 GLchan *image = read_color_image(ctx, x, y, width, height);
239 if (!image) {
240 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
241 return;
242 }
243
244 /* call glTexImage2D to redefine the texture */
245 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat,
246 width, height, border,
247 GL_RGBA, CHAN_TYPE, image,
248 &_mesa_native_packing, texObj, texImage);
249 FREE(image);
250 }
251
252 /* GL_SGIS_generate_mipmap */
253 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
254 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
255 }
256 }
257
258
259 /*
260 * Fallback for Driver.CopyTexSubImage1D().
261 */
262 void
263 _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level,
264 GLint xoffset, GLint x, GLint y, GLsizei width )
265 {
266 struct gl_texture_unit *texUnit;
267 struct gl_texture_object *texObj;
268 struct gl_texture_image *texImage;
269
270 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
271 texObj = _mesa_select_tex_object(ctx, texUnit, target);
272 ASSERT(texObj);
273 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
274 ASSERT(texImage);
275
276 ASSERT(ctx->Driver.TexImage1D);
277
278 if (texImage->Format == GL_DEPTH_COMPONENT) {
279 /* read depth image from framebuffer */
280 GLfloat *image = read_depth_image(ctx, x, y, width, 1);
281 if (!image) {
282 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D");
283 return;
284 }
285
286 /* call glTexSubImage1D to redefine the texture */
287 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
288 GL_DEPTH_COMPONENT, GL_FLOAT, image,
289 &_mesa_native_packing, texObj, texImage);
290 FREE(image);
291 }
292 else {
293 /* read RGBA image from framebuffer */
294 GLchan *image = read_color_image(ctx, x, y, width, 1);
295 if (!image) {
296 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
297 return;
298 }
299
300 /* now call glTexSubImage1D to do the real work */
301 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width,
302 GL_RGBA, CHAN_TYPE, image,
303 &_mesa_native_packing, texObj, texImage);
304 FREE(image);
305 }
306
307 /* GL_SGIS_generate_mipmap */
308 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
309 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
310 }
311 }
312
313
314 /*
315 * Fallback for Driver.CopyTexSubImage2D().
316 */
317 void
318 _swrast_copy_texsubimage2d( GLcontext *ctx,
319 GLenum target, GLint level,
320 GLint xoffset, GLint yoffset,
321 GLint x, GLint y, GLsizei width, GLsizei height )
322 {
323 struct gl_texture_unit *texUnit;
324 struct gl_texture_object *texObj;
325 struct gl_texture_image *texImage;
326
327 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
328 texObj = _mesa_select_tex_object(ctx, texUnit, target);
329 ASSERT(texObj);
330 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
331 ASSERT(texImage);
332
333 ASSERT(ctx->Driver.TexImage2D);
334
335 if (texImage->Format == GL_DEPTH_COMPONENT) {
336 /* read depth image from framebuffer */
337 GLfloat *image = read_depth_image(ctx, x, y, width, height);
338 if (!image) {
339 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D");
340 return;
341 }
342
343 /* call glTexImage1D to redefine the texture */
344 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
345 xoffset, yoffset, width, height,
346 GL_DEPTH_COMPONENT, GL_FLOAT, image,
347 &_mesa_native_packing, texObj, texImage);
348 FREE(image);
349 }
350 else {
351 /* read RGBA image from framebuffer */
352 GLchan *image = read_color_image(ctx, x, y, width, height);
353 if (!image) {
354 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
355 return;
356 }
357
358 /* now call glTexSubImage2D to do the real work */
359 (*ctx->Driver.TexSubImage2D)(ctx, target, level,
360 xoffset, yoffset, width, height,
361 GL_RGBA, CHAN_TYPE, image,
362 &_mesa_native_packing, texObj, texImage);
363 FREE(image);
364 }
365
366 /* GL_SGIS_generate_mipmap */
367 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
368 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
369 }
370 }
371
372
373 /*
374 * Fallback for Driver.CopyTexSubImage3D().
375 */
376 void
377 _swrast_copy_texsubimage3d( GLcontext *ctx,
378 GLenum target, GLint level,
379 GLint xoffset, GLint yoffset, GLint zoffset,
380 GLint x, GLint y, GLsizei width, GLsizei height )
381 {
382 struct gl_texture_unit *texUnit;
383 struct gl_texture_object *texObj;
384 struct gl_texture_image *texImage;
385
386 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
387 texObj = _mesa_select_tex_object(ctx, texUnit, target);
388 ASSERT(texObj);
389 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
390 ASSERT(texImage);
391
392 ASSERT(ctx->Driver.TexImage3D);
393
394 if (texImage->Format == GL_DEPTH_COMPONENT) {
395 /* read depth image from framebuffer */
396 GLfloat *image = read_depth_image(ctx, x, y, width, height);
397 if (!image) {
398 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D");
399 return;
400 }
401
402 /* call glTexImage1D to redefine the texture */
403 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
404 xoffset, yoffset, zoffset, width, height, 1,
405 GL_DEPTH_COMPONENT, GL_FLOAT, image,
406 &_mesa_native_packing, texObj, texImage);
407 FREE(image);
408 }
409 else {
410 /* read RGBA image from framebuffer */
411 GLchan *image = read_color_image(ctx, x, y, width, height);
412 if (!image) {
413 _mesa_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage3D" );
414 return;
415 }
416
417 /* now call glTexSubImage3D to do the real work */
418 (*ctx->Driver.TexSubImage3D)(ctx, target, level,
419 xoffset, yoffset, zoffset, width, height, 1,
420 GL_RGBA, CHAN_TYPE, image,
421 &_mesa_native_packing, texObj, texImage);
422 FREE(image);
423 }
424
425 /* GL_SGIS_generate_mipmap */
426 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
427 _mesa_generate_mipmap(ctx, target, texUnit, texObj);
428 }
429 }