Add offset and pitch fields to intelRegion. Remove frontOffset, frontPitch,
[mesa.git] / src / mesa / drivers / dri / i915 / intel_tex.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "glheader.h"
29 #include "mtypes.h"
30 #include "imports.h"
31 #include "macros.h"
32 #include "simple_list.h"
33 #include "enums.h"
34 #include "image.h"
35 #include "texstore.h"
36 #include "texformat.h"
37 #include "teximage.h"
38 #include "texmem.h"
39 #include "texobj.h"
40 #include "swrast/swrast.h"
41
42 #include "mm.h"
43
44 #include "intel_screen.h"
45 #include "intel_batchbuffer.h"
46 #include "intel_context.h"
47 #include "intel_tex.h"
48 #include "intel_ioctl.h"
49
50
51
52 static GLboolean
53 intelValidateClientStorage( intelContextPtr intel, GLenum target,
54 GLint internalFormat,
55 GLint srcWidth, GLint srcHeight,
56 GLenum format, GLenum type, const void *pixels,
57 const struct gl_pixelstore_attrib *packing,
58 struct gl_texture_object *texObj,
59 struct gl_texture_image *texImage)
60
61 {
62 GLcontext *ctx = &intel->ctx;
63 int texelBytes;
64
65 if (0)
66 fprintf(stderr, "intformat %s format %s type %s\n",
67 _mesa_lookup_enum_by_nr( internalFormat ),
68 _mesa_lookup_enum_by_nr( format ),
69 _mesa_lookup_enum_by_nr( type ));
70
71 if (!ctx->Unpack.ClientStorage)
72 return 0;
73
74 if (ctx->_ImageTransferState ||
75 texImage->IsCompressed ||
76 texObj->GenerateMipmap)
77 return 0;
78
79
80 /* This list is incomplete
81 */
82 switch ( internalFormat ) {
83 case GL_RGBA:
84 if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
85 texImage->TexFormat = &_mesa_texformat_argb8888;
86 texelBytes = 4;
87 }
88 else
89 return 0;
90 break;
91
92 case GL_RGB:
93 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
94 texImage->TexFormat = &_mesa_texformat_rgb565;
95 texelBytes = 2;
96 }
97 else
98 return 0;
99 break;
100
101 case GL_YCBCR_MESA:
102 if ( format == GL_YCBCR_MESA &&
103 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
104 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
105 texelBytes = 2;
106 }
107 else if ( format == GL_YCBCR_MESA &&
108 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
109 type == GL_UNSIGNED_BYTE)) {
110 texImage->TexFormat = &_mesa_texformat_ycbcr;
111 texelBytes = 2;
112 }
113 else
114 return 0;
115 break;
116
117
118 default:
119 return 0;
120 }
121
122 /* Could deal with these packing issues, but currently don't:
123 */
124 if (packing->SkipPixels ||
125 packing->SkipRows ||
126 packing->SwapBytes ||
127 packing->LsbFirst) {
128 return 0;
129 }
130
131 {
132 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
133 format, type);
134
135
136 if (0)
137 fprintf(stderr, "%s: srcRowStride %d/%x\n",
138 __FUNCTION__, srcRowStride, srcRowStride);
139
140 /* Could check this later in upload, pitch restrictions could be
141 * relaxed, but would need to store the image pitch somewhere,
142 * as packing details might change before image is uploaded:
143 */
144 if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) ||
145 (srcRowStride & 63))
146 return 0;
147
148
149 /* Have validated that _mesa_transfer_teximage would be a straight
150 * memcpy at this point. NOTE: future calls to TexSubImage will
151 * overwrite the client data. This is explicitly mentioned in the
152 * extension spec.
153 */
154 texImage->Data = (void *)pixels;
155 texImage->IsClientData = GL_TRUE;
156 texImage->RowStride = srcRowStride / texelBytes;
157 return 1;
158 }
159 }
160
161
162
163 static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level,
164 GLint internalFormat,
165 GLint width, GLint border,
166 GLenum format, GLenum type, const GLvoid *pixels,
167 const struct gl_pixelstore_attrib *packing,
168 struct gl_texture_object *texObj,
169 struct gl_texture_image *texImage )
170 {
171 driTextureObject * t = (driTextureObject *) texObj->DriverData;
172
173 assert(t);
174 intelFlush( ctx );
175 driSwapOutTextureObject( t );
176
177 texImage->IsClientData = GL_FALSE;
178
179 _mesa_store_teximage1d( ctx, target, level, internalFormat,
180 width, border, format, type,
181 pixels, packing, texObj, texImage );
182
183 t->dirty_images[0] |= (1 << level);
184 }
185
186 static void intelTexSubImage1D( GLcontext *ctx,
187 GLenum target,
188 GLint level,
189 GLint xoffset,
190 GLsizei width,
191 GLenum format, GLenum type,
192 const GLvoid *pixels,
193 const struct gl_pixelstore_attrib *packing,
194 struct gl_texture_object *texObj,
195 struct gl_texture_image *texImage )
196 {
197 driTextureObject * t = (driTextureObject *) texObj->DriverData;
198
199 assert(t);
200 intelFlush( ctx );
201 driSwapOutTextureObject( t );
202
203 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
204 format, type, pixels, packing, texObj,
205 texImage);
206 }
207
208
209 /* Handles 2D, CUBE, RECT:
210 */
211 static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level,
212 GLint internalFormat,
213 GLint width, GLint height, GLint border,
214 GLenum format, GLenum type, const GLvoid *pixels,
215 const struct gl_pixelstore_attrib *packing,
216 struct gl_texture_object *texObj,
217 struct gl_texture_image *texImage )
218 {
219 driTextureObject * t = (driTextureObject *) texObj->DriverData;
220 GLuint face;
221
222 /* which cube face or ordinary 2D image */
223 switch (target) {
224 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
225 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
226 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
227 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
228 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
229 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
230 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
231 ASSERT(face < 6);
232 break;
233 default:
234 face = 0;
235 }
236
237 assert(t);
238 intelFlush( ctx );
239 driSwapOutTextureObject( t );
240 texImage->IsClientData = GL_FALSE;
241
242 if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,
243 internalFormat,
244 width, height,
245 format, type, pixels,
246 packing, texObj, texImage)) {
247 if (INTEL_DEBUG & DEBUG_TEXTURE)
248 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
249 }
250 else {
251 _mesa_store_teximage2d( ctx, target, level, internalFormat,
252 width, height, border, format, type,
253 pixels, packing, texObj, texImage );
254
255 t->dirty_images[face] |= (1 << level);
256 }
257 }
258
259 static void intelTexSubImage2D( GLcontext *ctx,
260 GLenum target,
261 GLint level,
262 GLint xoffset, GLint yoffset,
263 GLsizei width, GLsizei height,
264 GLenum format, GLenum type,
265 const GLvoid *pixels,
266 const struct gl_pixelstore_attrib *packing,
267 struct gl_texture_object *texObj,
268 struct gl_texture_image *texImage )
269 {
270 driTextureObject * t = (driTextureObject *) texObj->DriverData;
271 GLuint face;
272
273 /* which cube face or ordinary 2D image */
274 switch (target) {
275 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
276 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
277 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
278 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
279 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
280 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
281 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
282 ASSERT(face < 6);
283 break;
284 default:
285 face = 0;
286 }
287
288 if (texImage->IsClientData &&
289 (char *)pixels == (char *)texImage->Data +
290 ((xoffset + yoffset * texImage->RowStride) *
291 texImage->TexFormat->TexelBytes)) {
292
293 /* Notification only - no upload required */
294 }
295 else {
296 assert( t ); /* this _should_ be true */
297 intelFlush( ctx );
298 driSwapOutTextureObject( t );
299
300 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
301 height, format, type, pixels, packing, texObj,
302 texImage);
303
304 t->dirty_images[face] |= (1 << level);
305 }
306 }
307
308 static void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
309 GLint internalFormat,
310 GLint width, GLint height, GLint border,
311 GLsizei imageSize, const GLvoid *data,
312 struct gl_texture_object *texObj,
313 struct gl_texture_image *texImage )
314 {
315 driTextureObject * t = (driTextureObject *) texObj->DriverData;
316 GLuint face;
317
318 /* which cube face or ordinary 2D image */
319 switch (target) {
320 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
321 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
322 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
323 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
324 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
325 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
326 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
327 ASSERT(face < 6);
328 break;
329 default:
330 face = 0;
331 }
332
333 assert(t);
334 intelFlush( ctx );
335
336 driSwapOutTextureObject( t );
337 texImage->IsClientData = GL_FALSE;
338
339 if (INTEL_DEBUG & DEBUG_TEXTURE)
340 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
341
342 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
343 height, border, imageSize, data, texObj, texImage);
344
345 t->dirty_images[face] |= (1 << level);
346 }
347
348
349 static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
350 GLint xoffset, GLint yoffset,
351 GLsizei width, GLsizei height,
352 GLenum format,
353 GLsizei imageSize, const GLvoid *data,
354 struct gl_texture_object *texObj,
355 struct gl_texture_image *texImage )
356 {
357 driTextureObject * t = (driTextureObject *) texObj->DriverData;
358 GLuint face;
359
360
361 /* which cube face or ordinary 2D image */
362 switch (target) {
363 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
364 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
365 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
366 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
367 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
368 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
369 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
370 ASSERT(face < 6);
371 break;
372 default:
373 face = 0;
374 }
375
376 assert( t ); /* this _should_ be true */
377 intelFlush( ctx );
378 driSwapOutTextureObject( t );
379
380 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
381 height, format, imageSize, data, texObj, texImage);
382
383 t->dirty_images[face] |= (1 << level);
384 }
385
386
387 static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level,
388 GLint internalFormat,
389 GLint width, GLint height, GLint depth,
390 GLint border,
391 GLenum format, GLenum type, const GLvoid *pixels,
392 const struct gl_pixelstore_attrib *packing,
393 struct gl_texture_object *texObj,
394 struct gl_texture_image *texImage )
395 {
396 driTextureObject * t = (driTextureObject *) texObj->DriverData;
397
398 assert(t);
399 driSwapOutTextureObject( t );
400 texImage->IsClientData = GL_FALSE;
401
402 _mesa_store_teximage3d(ctx, target, level, internalFormat,
403 width, height, depth, border,
404 format, type, pixels,
405 &ctx->Unpack, texObj, texImage);
406
407 t->dirty_images[0] |= (1 << level);
408 }
409
410
411 static void
412 intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
413 GLint xoffset, GLint yoffset, GLint zoffset,
414 GLsizei width, GLsizei height, GLsizei depth,
415 GLenum format, GLenum type,
416 const GLvoid *pixels,
417 const struct gl_pixelstore_attrib *packing,
418 struct gl_texture_object *texObj,
419 struct gl_texture_image *texImage )
420 {
421 driTextureObject * t = (driTextureObject *) texObj->DriverData;
422
423 assert( t ); /* this _should_ be true */
424 driSwapOutTextureObject( t );
425
426 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
427 width, height, depth,
428 format, type, pixels, packing, texObj, texImage);
429
430 t->dirty_images[0] |= (1 << level);
431 }
432
433
434
435
436 static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
437 {
438 driTextureObject * t = (driTextureObject *) tObj->DriverData;
439
440 if ( t != NULL ) {
441 intelFlush( ctx );
442 driDestroyTextureObject( t );
443 }
444
445 /* Free mipmap images and the texture object itself */
446 _mesa_delete_texture_object(ctx, tObj);
447 }
448
449
450 static const struct gl_texture_format *
451 intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
452 GLenum format, GLenum type )
453 {
454 intelContextPtr intel = INTEL_CONTEXT( ctx );
455 const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
456 intel->intelScreen->tex.size > 4*1024*1024);
457
458 switch ( internalFormat ) {
459 case 4:
460 case GL_RGBA:
461 case GL_COMPRESSED_RGBA:
462 if ( format == GL_BGRA ) {
463 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
464 return &_mesa_texformat_argb8888;
465 }
466 else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
467 return &_mesa_texformat_argb4444;
468 }
469 else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
470 return &_mesa_texformat_argb1555;
471 }
472 }
473 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
474
475 case 3:
476 case GL_RGB:
477 case GL_COMPRESSED_RGB:
478 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
479 return &_mesa_texformat_rgb565;
480 }
481 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
482
483 case GL_RGBA8:
484 case GL_RGB10_A2:
485 case GL_RGBA12:
486 case GL_RGBA16:
487 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
488
489 case GL_RGBA4:
490 case GL_RGBA2:
491 return &_mesa_texformat_argb4444;
492
493 case GL_RGB5_A1:
494 return &_mesa_texformat_argb1555;
495
496 case GL_RGB8:
497 case GL_RGB10:
498 case GL_RGB12:
499 case GL_RGB16:
500 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
501
502 case GL_RGB5:
503 case GL_RGB4:
504 case GL_R3_G3_B2:
505 return &_mesa_texformat_rgb565;
506
507 case GL_ALPHA:
508 case GL_ALPHA4:
509 case GL_ALPHA8:
510 case GL_ALPHA12:
511 case GL_ALPHA16:
512 case GL_COMPRESSED_ALPHA:
513 return &_mesa_texformat_a8;
514
515 case 1:
516 case GL_LUMINANCE:
517 case GL_LUMINANCE4:
518 case GL_LUMINANCE8:
519 case GL_LUMINANCE12:
520 case GL_LUMINANCE16:
521 case GL_COMPRESSED_LUMINANCE:
522 return &_mesa_texformat_l8;
523
524 case 2:
525 case GL_LUMINANCE_ALPHA:
526 case GL_LUMINANCE4_ALPHA4:
527 case GL_LUMINANCE6_ALPHA2:
528 case GL_LUMINANCE8_ALPHA8:
529 case GL_LUMINANCE12_ALPHA4:
530 case GL_LUMINANCE12_ALPHA12:
531 case GL_LUMINANCE16_ALPHA16:
532 case GL_COMPRESSED_LUMINANCE_ALPHA:
533 return &_mesa_texformat_al88;
534
535 case GL_INTENSITY:
536 case GL_INTENSITY4:
537 case GL_INTENSITY8:
538 case GL_INTENSITY12:
539 case GL_INTENSITY16:
540 case GL_COMPRESSED_INTENSITY:
541 return &_mesa_texformat_i8;
542
543 case GL_YCBCR_MESA:
544 if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
545 type == GL_UNSIGNED_BYTE)
546 return &_mesa_texformat_ycbcr;
547 else
548 return &_mesa_texformat_ycbcr_rev;
549
550 case GL_COMPRESSED_RGB_FXT1_3DFX:
551 return &_mesa_texformat_rgb_fxt1;
552 case GL_COMPRESSED_RGBA_FXT1_3DFX:
553 return &_mesa_texformat_rgba_fxt1;
554
555 case GL_RGB_S3TC:
556 case GL_RGB4_S3TC:
557 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
558 return &_mesa_texformat_rgb_dxt1;
559
560 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
561 return &_mesa_texformat_rgba_dxt1;
562
563 case GL_RGBA_S3TC:
564 case GL_RGBA4_S3TC:
565 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
566 return &_mesa_texformat_rgba_dxt3;
567
568 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
569 return &_mesa_texformat_rgba_dxt5;
570
571 case GL_DEPTH_COMPONENT:
572 case GL_DEPTH_COMPONENT16:
573 case GL_DEPTH_COMPONENT24:
574 case GL_DEPTH_COMPONENT32:
575 return &_mesa_texformat_depth_component16;
576
577 default:
578 fprintf(stderr, "unexpected texture format %s in %s\n",
579 _mesa_lookup_enum_by_nr(internalFormat),
580 __FUNCTION__);
581 return NULL;
582 }
583
584 return NULL; /* never get here */
585 }
586
587
588
589 void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
590 {
591 unsigned i;
592
593 if ( intel == NULL )
594 return;
595
596 if ( t->age > intel->dirtyAge )
597 intel->dirtyAge = t->age;
598
599 for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
600 if ( t == intel->CurrentTexObj[ i ] )
601 intel->CurrentTexObj[ i ] = NULL;
602 }
603 }
604
605
606
607 /* Upload an image from mesa's internal copy. Image may be 1D, 2D or
608 * 3D. Cubemaps are expanded elsewhere.
609 */
610 static void intelUploadTexImage( intelContextPtr intel,
611 intelTextureObjectPtr t,
612 const struct gl_texture_image *image,
613 const GLuint offset )
614 {
615
616 if (!image || !image->Data)
617 return;
618
619 if (image->Depth == 1 && image->IsClientData) {
620 if (INTEL_DEBUG & DEBUG_TEXTURE)
621 fprintf(stderr, "Blit uploading\n");
622
623 /* Do it with a blit.
624 */
625 intelEmitCopyBlitLocked( intel,
626 image->TexFormat->TexelBytes,
627 image->RowStride, /* ? */
628 intelGetMemoryOffsetMESA( NULL, 0, image->Data ),
629 t->Pitch / image->TexFormat->TexelBytes,
630 intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ),
631 0, 0,
632 0, 0,
633 image->Width,
634 image->Height);
635 }
636 else if (image->IsCompressed) {
637 GLuint row_len = image->Width * 2;
638 GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
639 GLubyte *src = (GLubyte *)image->Data;
640 GLuint j;
641
642 if (INTEL_DEBUG & DEBUG_TEXTURE)
643 fprintf(stderr,
644 "Upload image %dx%dx%d offset %xm row_len %x "
645 "pitch %x depth_pitch %x\n",
646 image->Width, image->Height, image->Depth, offset,
647 row_len, t->Pitch, t->depth_pitch);
648
649 switch(image->IntFormat)
650 {
651 case GL_COMPRESSED_RGB_FXT1_3DFX:
652 case GL_COMPRESSED_RGBA_FXT1_3DFX:
653 case GL_RGB_S3TC:
654 case GL_RGB4_S3TC:
655 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
656 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
657 for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
658 __memcpy(dst, src, row_len );
659 src += row_len;
660 }
661 break;
662 case GL_RGBA_S3TC:
663 case GL_RGBA4_S3TC:
664 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
665 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
666 for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
667 __memcpy(dst, src, (image->Width*4) );
668 src += image->Width*4;
669 }
670 break;
671 default:
672 fprintf(stderr,"Internal Compressed format not supported %d\n", image->IntFormat);
673 break;
674 }
675 }
676 else {
677 GLuint row_len = image->Width * image->TexFormat->TexelBytes;
678 GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
679 GLubyte *src = (GLubyte *)image->Data;
680 GLuint d, j;
681
682 if (INTEL_DEBUG & DEBUG_TEXTURE)
683 fprintf(stderr,
684 "Upload image %dx%dx%d offset %xm row_len %x "
685 "pitch %x depth_pitch %x\n",
686 image->Width, image->Height, image->Depth, offset,
687 row_len, t->Pitch, t->depth_pitch);
688
689 if (row_len == t->Pitch) {
690 for (d = 0; d < image->Depth; d++) {
691 memcpy( dst, src, t->Pitch * image->Height );
692 dst += t->depth_pitch;
693 src += row_len * image->Height;
694 }
695 }
696 else {
697 for (d = 0 ; d < image->Depth ; d++) {
698 for (j = 0 ; j < image->Height ; j++) {
699 __memcpy(dst, src, row_len );
700 src += row_len;
701 dst += t->Pitch;
702 }
703
704 dst += t->depth_pitch - (t->Pitch * image->Height);
705 }
706 }
707 }
708 }
709
710
711
712 int intelUploadTexImages( intelContextPtr intel,
713 intelTextureObjectPtr t,
714 GLuint face)
715 {
716 const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
717 const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image;
718 int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes;
719
720 /* Can we texture out of the existing client data? */
721 if ( numLevels == 1 &&
722 firstImage->IsClientData &&
723 (pitch & 3) == 0) {
724
725 if (INTEL_DEBUG & DEBUG_TEXTURE)
726 fprintf(stderr, "AGP texturing from client memory\n");
727
728 t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data );
729 t->BufAddr = 0;
730 t->dirty = ~0;
731 return GL_TRUE;
732 }
733 else {
734 if (INTEL_DEBUG & DEBUG_TEXTURE)
735 fprintf(stderr, "Uploading client data to agp\n");
736
737 INTEL_FIREVERTICES( intel );
738 LOCK_HARDWARE( intel );
739
740 if ( t->base.memBlock == NULL ) {
741 int heap;
742
743 heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps,
744 (driTextureObject *) t );
745 if ( heap == -1 ) {
746 UNLOCK_HARDWARE( intel );
747 return GL_FALSE;
748 }
749
750 /* Set the base offset of the texture image */
751 t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
752 t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs;
753 t->dirty = ~0;
754 }
755
756
757 /* Let the world know we've used this memory recently.
758 */
759 driUpdateTextureLRU( (driTextureObject *) t );
760
761
762 /* Upload any images that are new */
763 if (t->base.dirty_images[face]) {
764 int i;
765
766 intelWaitForIdle( intel );
767
768 for (i = 0 ; i < numLevels ; i++) {
769 int level = i + t->base.firstLevel;
770
771 if (t->base.dirty_images[face] & (1<<level)) {
772
773 const struct gl_texture_image *image = t->image[face][i].image;
774 GLuint offset = t->image[face][i].offset;
775
776 if (INTEL_DEBUG & DEBUG_TEXTURE)
777 fprintf(stderr, "upload level %d, offset %x\n",
778 level, offset);
779
780 intelUploadTexImage( intel, t, image, offset );
781 }
782 }
783 t->base.dirty_images[face] = 0;
784 intel->perf_boxes |= I830_BOX_TEXTURE_LOAD;
785 }
786
787 UNLOCK_HARDWARE( intel );
788 return GL_TRUE;
789 }
790 }
791
792 /**
793 * Allocate a new texture object.
794 * Called via ctx->Driver.NewTextureObject.
795 * Note: this function will be called during context creation to
796 * allocate the default texture objects.
797 * Note: we could use containment here to 'derive' the driver-specific
798 * texture object from the core mesa gl_texture_object. Not done at this time.
799 */
800 static struct gl_texture_object *
801 intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
802 {
803 struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target);
804 INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj );
805 return obj;
806 }
807
808
809 void intelInitTextureFuncs( struct dd_function_table *functions )
810 {
811 functions->NewTextureObject = intelNewTextureObject;
812 functions->ChooseTextureFormat = intelChooseTextureFormat;
813 functions->TexImage1D = intelTexImage1D;
814 functions->TexImage2D = intelTexImage2D;
815 functions->TexImage3D = intelTexImage3D;
816 functions->TexSubImage1D = intelTexSubImage1D;
817 functions->TexSubImage2D = intelTexSubImage2D;
818 functions->TexSubImage3D = intelTexSubImage3D;
819 functions->CopyTexImage1D = _swrast_copy_teximage1d;
820 functions->CopyTexImage2D = _swrast_copy_teximage2d;
821 functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
822 functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
823 functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
824 functions->DeleteTexture = intelDeleteTexture;
825 functions->UpdateTexturePalette = NULL;
826 functions->IsTextureResident = driIsTextureResident;
827 functions->TestProxyTexImage = _mesa_test_proxy_teximage;
828 functions->DeleteTexture = intelDeleteTexture;
829 functions->CompressedTexImage2D = intelCompressedTexImage2D;
830 functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
831 }