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