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