draw: corrections to allow for different cliptest cases
[mesa.git] / src / mesa / drivers / dri / sis / sis_tex.c
1 /**************************************************************************
2
3 Copyright 2003 Eric Anholt
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 on the rights to use, copy, modify, merge, publish, distribute, sub
10 license, and/or sell copies of the Software, and to permit persons to whom
11 the Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice (including the next
14 paragraph) shall be included in all copies or substantial portions of the
15 Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 **************************************************************************/
25
26 /*
27 * Authors:
28 * Eric Anholt <anholt@FreeBSD.org>
29 */
30
31 #include "swrast/swrast.h"
32 #include "main/imports.h"
33 #include "main/texstore.h"
34 #include "main/texobj.h"
35
36 #include "sis_context.h"
37 #include "sis_alloc.h"
38 #include "sis_tex.h"
39 #include "xmlpool.h"
40
41 #define ALIGN(value, align) (GLubyte *)((long)(value + align - 1) & ~(align - 1))
42
43 #define TEXTURE_HW_ALIGNMENT 4
44 #define TEXTURE_HW_PLUS (4 + 4)
45
46 static sisTexObjPtr
47 sisAllocTexObj( struct gl_texture_object *texObj )
48 {
49 sisTexObjPtr t;
50
51 t = (sisTexObjPtr) CALLOC_STRUCT( sis_tex_obj );
52 texObj->DriverData = t;
53 return t;
54 }
55
56 static void
57 sisAllocTexImage( sisContextPtr smesa, sisTexObjPtr t, int level,
58 const struct gl_texture_image *image )
59 {
60 char *addr;
61 int size, texel_size;
62
63 if (t->format == 0) {
64 t->format = image->_BaseFormat;
65 switch (image->TexFormat)
66 {
67 case MESA_FORMAT_ARGB8888:
68 t->hwformat = TEXEL_ARGB_8888_32;
69 break;
70 case MESA_FORMAT_ARGB4444:
71 t->hwformat = TEXEL_ARGB_4444_16;
72 break;
73 case MESA_FORMAT_ARGB1555:
74 t->hwformat = TEXEL_ARGB_1555_16;
75 break;
76 case MESA_FORMAT_RGB565:
77 t->hwformat = TEXEL_RGB_565_16;
78 break;
79 case MESA_FORMAT_RGB332:
80 t->hwformat = TEXEL_RGB_332_8;
81 break;
82 case MESA_FORMAT_I8:
83 t->hwformat = TEXEL_I8;
84 break;
85 case MESA_FORMAT_A8:
86 t->hwformat = TEXEL_A8;
87 break;
88 case MESA_FORMAT_L8:
89 t->hwformat = TEXEL_L8;
90 break;
91 case MESA_FORMAT_AL88:
92 t->hwformat = TEXEL_AL88;
93 break;
94 case MESA_FORMAT_YCBCR:
95 t->hwformat = TEXEL_YUV422;
96 break;
97 case MESA_FORMAT_YCBCR_REV:
98 t->hwformat = TEXEL_VUY422;
99 break;
100 default:
101 sis_fatal_error("Bad texture format 0x%x.\n", image->TexFormat);
102 }
103 }
104 assert(t->format == image->_BaseFormat);
105
106 texel_size = _mesa_get_format_bytes(image->TexFormat);
107 size = image->Width * image->Height * texel_size + TEXTURE_HW_PLUS;
108
109 addr = sisAllocFB( smesa, size, &t->image[level].handle );
110 if (addr == NULL) {
111 addr = sisAllocAGP( smesa, size, &t->image[level].handle );
112 if (addr == NULL)
113 sis_fatal_error("Failure to allocate texture memory.\n");
114 t->image[level].memType = AGP_TYPE;
115 }
116 else
117 t->image[level].memType = VIDEO_TYPE;
118
119 t->image[level].Data = ALIGN(addr, TEXTURE_HW_ALIGNMENT);
120 t->image[level].pitch = image->Width * texel_size;
121 t->image[level].size = image->Width * image->Height * texel_size;
122 t->numImages++;
123 }
124
125 static void
126 sisFreeTexImage( sisContextPtr smesa, sisTexObjPtr t, int level )
127 {
128 assert(level >= 0);
129 assert(level < SIS_MAX_TEXTURE_LEVELS);
130 if (t->image[level].Data == NULL)
131 return;
132
133 switch (t->image[level].memType)
134 {
135 case VIDEO_TYPE:
136 sisFreeFB( smesa, t->image[level].handle );
137 break;
138 case AGP_TYPE:
139 sisFreeAGP( smesa, t->image[level].handle );
140 break;
141 }
142 t->image[level].Data = NULL;
143 t->image[level].handle = NULL;
144 /* If there are no textures loaded any more, reset the hw format so the
145 * object can be reused for new formats
146 */
147 t->numImages--;
148 if (t->numImages == 0) {
149 t->format = 0;
150 t->hwformat = 0;
151 }
152 }
153
154 static void
155 sisTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param )
156 {
157 sisContextPtr smesa = SIS_CONTEXT(ctx);
158
159 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
160 }
161
162 static void
163 sisTexParameter( GLcontext *ctx, GLenum target,
164 struct gl_texture_object *texObj, GLenum pname,
165 const GLfloat *params )
166 {
167 sisContextPtr smesa = SIS_CONTEXT(ctx);
168
169 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
170 }
171
172 static void
173 sisBindTexture( GLcontext *ctx, GLenum target,
174 struct gl_texture_object *texObj )
175 {
176 sisContextPtr smesa = SIS_CONTEXT(ctx);
177 sisTexObjPtr t;
178
179 if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
180 if ( texObj->DriverData == NULL ) {
181 sisAllocTexObj( texObj );
182 }
183 }
184
185 t = texObj->DriverData;
186 if (!t)
187 return;
188
189 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format) {
190 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
191 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
192 }
193 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
194 }
195
196 static void
197 sisDeleteTexture( GLcontext * ctx, struct gl_texture_object *texObj )
198 {
199 sisContextPtr smesa = SIS_CONTEXT(ctx);
200 sisTexObjPtr t;
201 int i;
202
203 smesa->clearTexCache = GL_TRUE;
204
205 t = texObj->DriverData;
206 if (t == NULL) {
207 /*
208 * this shows the texture is default object and never be a
209 * argument of sisTexImage*
210 */
211 return;
212 }
213 for (i = 0; i < SIS_MAX_TEXTURE_LEVELS; i++) {
214 sisFreeTexImage( smesa, t, i );
215 }
216
217 FREE(t);
218 texObj->DriverData = NULL;
219 /* Free mipmap images and the texture object itself */
220 _mesa_delete_texture_object(ctx, texObj);
221 }
222
223 static GLboolean sisIsTextureResident( GLcontext * ctx,
224 struct gl_texture_object *texObj )
225 {
226 return (texObj->DriverData != NULL);
227 }
228
229 static gl_format
230 sisChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
231 GLenum format, GLenum type )
232 {
233 sisContextPtr smesa = SIS_CONTEXT(ctx);
234
235 const GLboolean do32bpt =
236 (smesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32);
237 const GLboolean force16bpt =
238 (smesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
239
240 switch ( internalFormat ) {
241 case 4:
242 case GL_RGBA:
243 case GL_COMPRESSED_RGBA:
244 switch ( type ) {
245 case GL_UNSIGNED_INT_10_10_10_2:
246 case GL_UNSIGNED_INT_2_10_10_10_REV:
247 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
248 case GL_UNSIGNED_SHORT_4_4_4_4:
249 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
250 return MESA_FORMAT_ARGB4444;
251 case GL_UNSIGNED_SHORT_5_5_5_1:
252 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
253 return MESA_FORMAT_ARGB1555;
254 default:
255 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
256 }
257
258 case 3:
259 case GL_RGB:
260 case GL_COMPRESSED_RGB:
261 switch ( type ) {
262 case GL_UNSIGNED_SHORT_4_4_4_4:
263 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
264 return MESA_FORMAT_ARGB4444;
265 case GL_UNSIGNED_SHORT_5_5_5_1:
266 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
267 return MESA_FORMAT_ARGB1555;
268 case GL_UNSIGNED_SHORT_5_6_5:
269 case GL_UNSIGNED_SHORT_5_6_5_REV:
270 return MESA_FORMAT_RGB565;
271 default:
272 return do32bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
273 }
274
275 case GL_RGBA8:
276 case GL_RGBA12:
277 case GL_RGBA16:
278 return !force16bpt ?
279 MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB4444;
280
281 case GL_RGB10_A2:
282 return !force16bpt ?
283 MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB1555;
284
285 case GL_RGBA4:
286 case GL_RGBA2:
287 return MESA_FORMAT_ARGB4444;
288
289 case GL_RGB5_A1:
290 return MESA_FORMAT_ARGB1555;
291
292 case GL_RGB8:
293 case GL_RGB10:
294 case GL_RGB12:
295 case GL_RGB16:
296 return !force16bpt ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_RGB565;
297
298 case GL_RGB5:
299 case GL_RGB4:
300 return MESA_FORMAT_RGB565;
301
302 case GL_R3_G3_B2:
303 return MESA_FORMAT_RGB332;
304
305 case GL_ALPHA:
306 case GL_ALPHA4: /* FIXME: This could use its own texstore */
307 case GL_ALPHA8:
308 case GL_ALPHA12:
309 case GL_ALPHA16:
310 case GL_COMPRESSED_ALPHA:
311 return MESA_FORMAT_A8;
312
313 case 1:
314 case GL_LUMINANCE:
315 case GL_LUMINANCE4: /* FIXME: This could use its own texstore */
316 case GL_LUMINANCE8:
317 case GL_LUMINANCE12:
318 case GL_LUMINANCE16:
319 case GL_COMPRESSED_LUMINANCE:
320 return MESA_FORMAT_L8;
321
322 case 2:
323 case GL_LUMINANCE_ALPHA:
324 case GL_LUMINANCE4_ALPHA4: /* FIXME: This could use its own texstore */
325 case GL_LUMINANCE6_ALPHA2: /* FIXME: This could use its own texstore */
326 case GL_LUMINANCE8_ALPHA8:
327 case GL_LUMINANCE12_ALPHA4: /* FIXME: This could use its own texstore */
328 case GL_LUMINANCE12_ALPHA12:
329 case GL_LUMINANCE16_ALPHA16:
330 case GL_COMPRESSED_LUMINANCE_ALPHA:
331 return MESA_FORMAT_AL88;
332
333 case GL_INTENSITY:
334 case GL_INTENSITY4:
335 case GL_INTENSITY8:
336 case GL_INTENSITY12:
337 case GL_INTENSITY16:
338 case GL_COMPRESSED_INTENSITY:
339 return MESA_FORMAT_I8;
340
341 case GL_YCBCR_MESA:
342 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
343 type == GL_UNSIGNED_BYTE)
344 return MESA_FORMAT_YCBCR;
345 else
346 return MESA_FORMAT_YCBCR_REV;
347
348 default:
349 _mesa_problem(ctx, "unexpected format in sisDDChooseTextureFormat: %d",
350 internalFormat);
351 return MESA_FORMAT_NONE;
352 }
353 }
354
355 static void sisTexImage1D( GLcontext *ctx, GLenum target, GLint level,
356 GLint internalFormat,
357 GLint width, GLint border,
358 GLenum format, GLenum type, const GLvoid *pixels,
359 const struct gl_pixelstore_attrib *packing,
360 struct gl_texture_object *texObj,
361 struct gl_texture_image *texImage )
362 {
363 sisContextPtr smesa = SIS_CONTEXT(ctx);
364 sisTexObjPtr t;
365
366 if ( texObj->DriverData == NULL )
367 sisAllocTexObj( texObj );
368 t = texObj->DriverData;
369
370 /* Note, this will call sisChooseTextureFormat */
371 _mesa_store_teximage1d( ctx, target, level, internalFormat,
372 width, border, format, type,
373 pixels, packing, texObj, texImage );
374
375 /* Allocate offscreen space for the texture */
376 sisFreeTexImage(smesa, t, level);
377 sisAllocTexImage(smesa, t, level, texImage);
378
379 /* Upload the texture */
380 WaitEngIdle(smesa);
381 memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
382
383 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
384 {
385 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
386 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
387 }
388 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
389 }
390
391
392 static void sisTexSubImage1D( GLcontext *ctx,
393 GLenum target,
394 GLint level,
395 GLint xoffset,
396 GLsizei width,
397 GLenum format, GLenum type,
398 const GLvoid *pixels,
399 const struct gl_pixelstore_attrib *packing,
400 struct gl_texture_object *texObj,
401 struct gl_texture_image *texImage )
402 {
403 sisContextPtr smesa = SIS_CONTEXT(ctx);
404 sisTexObjPtr t;
405 GLuint copySize;
406 GLint texelBytes;
407 const char *src;
408 GLubyte *dst;
409
410 if ( texObj->DriverData == NULL )
411 sisAllocTexObj( texObj );
412 t = texObj->DriverData;
413
414 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
415 format, type, pixels, packing, texObj,
416 texImage);
417
418 /* Allocate offscreen space for the texture */
419 sisFreeTexImage(smesa, t, level);
420 sisAllocTexImage(smesa, t, level, texImage);
421
422 /* Upload the texture */
423 WaitEngIdle(smesa);
424 texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
425
426 copySize = width * texelBytes;
427 src = (char *)texImage->Data + xoffset * texelBytes;
428 dst = t->image[level].Data + xoffset * texelBytes;
429
430 memcpy( dst, src, copySize );
431
432 smesa->clearTexCache = GL_TRUE;
433
434 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
435 {
436 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
437 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
438 }
439 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
440 }
441
442 static void sisTexImage2D( GLcontext *ctx, GLenum target, GLint level,
443 GLint internalFormat,
444 GLint width, GLint height, GLint border,
445 GLenum format, GLenum type, const GLvoid *pixels,
446 const struct gl_pixelstore_attrib *packing,
447 struct gl_texture_object *texObj,
448 struct gl_texture_image *texImage )
449 {
450 sisContextPtr smesa = SIS_CONTEXT(ctx);
451 sisTexObjPtr t;
452
453 if ( texObj->DriverData == NULL )
454 sisAllocTexObj( texObj );
455 t = texObj->DriverData;
456
457 /* Note, this will call sisChooseTextureFormat */
458 _mesa_store_teximage2d(ctx, target, level, internalFormat,
459 width, height, border, format, type, pixels,
460 &ctx->Unpack, texObj, texImage);
461
462 /* Allocate offscreen space for the texture */
463 sisFreeTexImage(smesa, t, level);
464 sisAllocTexImage(smesa, t, level, texImage);
465
466 /* Upload the texture */
467 WaitEngIdle(smesa);
468 memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
469
470 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
471 {
472 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
473 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
474 }
475 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
476 }
477
478 static void sisTexSubImage2D( GLcontext *ctx,
479 GLenum target,
480 GLint level,
481 GLint xoffset, GLint yoffset,
482 GLsizei width, GLsizei height,
483 GLenum format, GLenum type,
484 const GLvoid *pixels,
485 const struct gl_pixelstore_attrib *packing,
486 struct gl_texture_object *texObj,
487 struct gl_texture_image *texImage )
488 {
489 sisContextPtr smesa = SIS_CONTEXT(ctx);
490 sisTexObjPtr t;
491 GLuint copySize;
492 GLint texelBytes;
493 const char *src;
494 GLubyte *dst;
495 int j;
496 GLuint soffset;
497
498 if ( texObj->DriverData == NULL )
499 sisAllocTexObj( texObj );
500 t = texObj->DriverData;
501
502 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
503 height, format, type, pixels, packing, texObj,
504 texImage);
505
506 /* Allocate offscreen space for the texture */
507 sisFreeTexImage(smesa, t, level);
508 sisAllocTexImage(smesa, t, level, texImage);
509
510 /* Upload the texture */
511 WaitEngIdle(smesa);
512 texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
513
514 copySize = width * texelBytes;
515 src = (char *)texImage->Data + (xoffset + yoffset * texImage->Width) *
516 texelBytes;
517 dst = t->image[level].Data + (xoffset + yoffset * texImage->Width) *
518 texelBytes;
519 soffset = texImage->Width * texelBytes;
520
521 for (j = yoffset; j < yoffset + height; j++) {
522 memcpy( dst, src, copySize );
523 src += soffset;
524 dst += soffset;
525 }
526
527 smesa->clearTexCache = GL_TRUE;
528
529 if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
530 {
531 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
532 smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
533 }
534 smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
535 }
536
537
538 /**
539 * Allocate a new texture object.
540 * Called via ctx->Driver.NewTextureObject.
541 * Note: this function will be called during context creation to
542 * allocate the default texture objects.
543 * Note: we could use containment here to 'derive' the driver-specific
544 * texture object from the core mesa gl_texture_object. Not done at this time.
545 */
546 static struct gl_texture_object *
547 sisNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
548 {
549 struct gl_texture_object *obj;
550 obj = _mesa_new_texture_object(ctx, name, target);
551 return obj;
552 }
553
554
555 void sisInitTextureFuncs( struct dd_function_table *functions )
556 {
557 functions->TexEnv = sisTexEnv;
558 functions->ChooseTextureFormat = sisChooseTextureFormat;
559 functions->TexImage1D = sisTexImage1D;
560 functions->TexSubImage1D = sisTexSubImage1D;
561 functions->TexImage2D = sisTexImage2D;
562 functions->TexSubImage2D = sisTexSubImage2D;
563 functions->TexParameter = sisTexParameter;
564 functions->BindTexture = sisBindTexture;
565 functions->NewTextureObject = sisNewTextureObject;
566 functions->DeleteTexture = sisDeleteTexture;
567 functions->IsTextureResident = sisIsTextureResident;
568 }