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