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