1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 **************************************************************************/
11 #include "simple_list.h"
15 #include "texformat.h"
19 #include "swrast/swrast.h"
23 #include "intel_screen.h"
24 #include "intel_batchbuffer.h"
25 #include "intel_context.h"
26 #include "intel_tex.h"
27 #include "intel_ioctl.h"
32 intelValidateClientStorage( intelContextPtr intel
, GLenum target
,
34 GLint srcWidth
, GLint srcHeight
,
35 GLenum format
, GLenum type
, const void *pixels
,
36 const struct gl_pixelstore_attrib
*packing
,
37 struct gl_texture_object
*texObj
,
38 struct gl_texture_image
*texImage
)
41 GLcontext
*ctx
= &intel
->ctx
;
45 fprintf(stderr
, "intformat %s format %s type %s\n",
46 _mesa_lookup_enum_by_nr( internalFormat
),
47 _mesa_lookup_enum_by_nr( format
),
48 _mesa_lookup_enum_by_nr( type
));
50 if (!ctx
->Unpack
.ClientStorage
)
53 if (ctx
->_ImageTransferState
||
54 texImage
->IsCompressed
||
55 texObj
->GenerateMipmap
)
59 /* This list is incomplete
61 switch ( internalFormat
) {
63 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
64 texImage
->TexFormat
= &_mesa_texformat_argb8888
;
72 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
73 texImage
->TexFormat
= &_mesa_texformat_rgb565
;
81 if ( format
== GL_YCBCR_MESA
&&
82 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
83 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
86 else if ( format
== GL_YCBCR_MESA
&&
87 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
88 type
== GL_UNSIGNED_BYTE
)) {
89 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
101 /* Could deal with these packing issues, but currently don't:
103 if (packing
->SkipPixels
||
105 packing
->SwapBytes
||
111 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
116 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
117 __FUNCTION__
, srcRowStride
, srcRowStride
);
119 /* Could check this later in upload, pitch restrictions could be
120 * relaxed, but would need to store the image pitch somewhere,
121 * as packing details might change before image is uploaded:
123 if (!intelIsAgpMemory( intel
, pixels
, srcHeight
* srcRowStride
) ||
128 /* Have validated that _mesa_transfer_teximage would be a straight
129 * memcpy at this point. NOTE: future calls to TexSubImage will
130 * overwrite the client data. This is explicitly mentioned in the
133 texImage
->Data
= (void *)pixels
;
134 texImage
->IsClientData
= GL_TRUE
;
135 texImage
->RowStride
= srcRowStride
/ texelBytes
;
142 static void intelTexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
143 GLint internalFormat
,
144 GLint width
, GLint border
,
145 GLenum format
, GLenum type
, const GLvoid
*pixels
,
146 const struct gl_pixelstore_attrib
*packing
,
147 struct gl_texture_object
*texObj
,
148 struct gl_texture_image
*texImage
)
150 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
154 driSwapOutTextureObject( t
);
156 texImage
->IsClientData
= GL_FALSE
;
158 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
159 width
, border
, format
, type
,
160 pixels
, packing
, texObj
, texImage
);
162 t
->dirty_images
[0] |= (1 << level
);
165 static void intelTexSubImage1D( GLcontext
*ctx
,
170 GLenum format
, GLenum type
,
171 const GLvoid
*pixels
,
172 const struct gl_pixelstore_attrib
*packing
,
173 struct gl_texture_object
*texObj
,
174 struct gl_texture_image
*texImage
)
176 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
180 driSwapOutTextureObject( t
);
182 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
183 format
, type
, pixels
, packing
, texObj
,
188 /* Handles 2D, CUBE, RECT:
190 static void intelTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
191 GLint internalFormat
,
192 GLint width
, GLint height
, GLint border
,
193 GLenum format
, GLenum type
, const GLvoid
*pixels
,
194 const struct gl_pixelstore_attrib
*packing
,
195 struct gl_texture_object
*texObj
,
196 struct gl_texture_image
*texImage
)
198 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
201 /* which cube face or ordinary 2D image */
203 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
204 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
205 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
206 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
207 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
208 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
209 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
218 driSwapOutTextureObject( t
);
219 texImage
->IsClientData
= GL_FALSE
;
221 if (intelValidateClientStorage( INTEL_CONTEXT(ctx
), target
,
224 format
, type
, pixels
,
225 packing
, texObj
, texImage
)) {
226 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
227 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
230 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
231 width
, height
, border
, format
, type
,
232 pixels
, packing
, texObj
, texImage
);
234 t
->dirty_images
[face
] |= (1 << level
);
238 static void intelTexSubImage2D( GLcontext
*ctx
,
241 GLint xoffset
, GLint yoffset
,
242 GLsizei width
, GLsizei height
,
243 GLenum format
, GLenum type
,
244 const GLvoid
*pixels
,
245 const struct gl_pixelstore_attrib
*packing
,
246 struct gl_texture_object
*texObj
,
247 struct gl_texture_image
*texImage
)
249 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
252 /* which cube face or ordinary 2D image */
254 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
255 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
256 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
257 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
258 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
259 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
260 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
267 if (texImage
->IsClientData
&&
268 (char *)pixels
== (char *)texImage
->Data
+
269 ((xoffset
+ yoffset
* texImage
->RowStride
) *
270 texImage
->TexFormat
->TexelBytes
)) {
272 /* Notification only - no upload required */
275 assert( t
); /* this _should_ be true */
277 driSwapOutTextureObject( t
);
279 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
280 height
, format
, type
, pixels
, packing
, texObj
,
283 t
->dirty_images
[face
] |= (1 << level
);
289 static void intelTexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
290 GLint internalFormat
,
291 GLint width
, GLint height
, GLint depth
,
293 GLenum format
, GLenum type
, const GLvoid
*pixels
,
294 const struct gl_pixelstore_attrib
*packing
,
295 struct gl_texture_object
*texObj
,
296 struct gl_texture_image
*texImage
)
298 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
301 driSwapOutTextureObject( t
);
302 texImage
->IsClientData
= GL_FALSE
;
304 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
305 width
, height
, depth
, border
,
306 format
, type
, pixels
,
307 &ctx
->Unpack
, texObj
, texImage
);
309 t
->dirty_images
[0] |= (1 << level
);
314 intelTexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
315 GLint xoffset
, GLint yoffset
, GLint zoffset
,
316 GLsizei width
, GLsizei height
, GLsizei depth
,
317 GLenum format
, GLenum type
,
318 const GLvoid
*pixels
,
319 const struct gl_pixelstore_attrib
*packing
,
320 struct gl_texture_object
*texObj
,
321 struct gl_texture_image
*texImage
)
323 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
325 assert( t
); /* this _should_ be true */
326 driSwapOutTextureObject( t
);
328 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
329 width
, height
, depth
,
330 format
, type
, pixels
, packing
, texObj
, texImage
);
332 t
->dirty_images
[0] |= (1 << level
);
338 static void intelDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
340 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
344 driDestroyTextureObject( t
);
347 /* Free mipmap images and the texture object itself */
348 _mesa_delete_texture_object(ctx
, tObj
);
352 static const struct gl_texture_format
*
353 intelChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
354 GLenum format
, GLenum type
)
356 intelContextPtr intel
= INTEL_CONTEXT( ctx
);
357 const GLboolean do32bpt
= ( intel
->intelScreen
->cpp
== 4 &&
358 intel
->intelScreen
->textureSize
> 4*1024*1024);
360 switch ( internalFormat
) {
363 case GL_COMPRESSED_RGBA
:
364 if ( format
== GL_BGRA
) {
365 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
366 return &_mesa_texformat_argb8888
;
368 else if ( type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
369 return &_mesa_texformat_argb4444
;
371 else if ( type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
372 return &_mesa_texformat_argb1555
;
375 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
379 case GL_COMPRESSED_RGB
:
380 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
381 return &_mesa_texformat_rgb565
;
383 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
389 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
393 return &_mesa_texformat_argb4444
;
396 return &_mesa_texformat_argb1555
;
402 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
407 return &_mesa_texformat_rgb565
;
414 case GL_COMPRESSED_ALPHA
:
415 /* if (1 || intel->intelScreen->deviceID == PCI_CHIP_I915_G) */
416 return &_mesa_texformat_a8
;
418 /* return &_mesa_texformat_al88; */
426 case GL_COMPRESSED_LUMINANCE
:
427 return &_mesa_texformat_l8
;
430 case GL_LUMINANCE_ALPHA
:
431 case GL_LUMINANCE4_ALPHA4
:
432 case GL_LUMINANCE6_ALPHA2
:
433 case GL_LUMINANCE8_ALPHA8
:
434 case GL_LUMINANCE12_ALPHA4
:
435 case GL_LUMINANCE12_ALPHA12
:
436 case GL_LUMINANCE16_ALPHA16
:
437 case GL_COMPRESSED_LUMINANCE_ALPHA
:
438 return &_mesa_texformat_al88
;
445 case GL_COMPRESSED_INTENSITY
:
446 return &_mesa_texformat_i8
;
449 if (type
== GL_UNSIGNED_SHORT_8_8_MESA
||
450 type
== GL_UNSIGNED_BYTE
)
451 return &_mesa_texformat_ycbcr
;
453 return &_mesa_texformat_ycbcr_rev
;
456 fprintf(stderr
, "unexpected texture format in %s\n", __FUNCTION__
);
460 return NULL
; /* never get here */
465 void intelDestroyTexObj(intelContextPtr intel
, intelTextureObjectPtr t
)
472 if ( t
->age
> intel
->dirtyAge
)
473 intel
->dirtyAge
= t
->age
;
475 for ( i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++ ) {
476 if ( t
== intel
->CurrentTexObj
[ i
] )
477 intel
->CurrentTexObj
[ i
] = NULL
;
483 /* Upload an image from mesa's internal copy. Image may be 1D, 2D or
484 * 3D. Cubemaps are expanded elsewhere.
486 static void intelUploadTexImage( intelContextPtr intel
,
487 intelTextureObjectPtr t
,
488 const struct gl_texture_image
*image
,
489 const GLuint offset
)
492 if (!image
|| !image
->Data
)
495 if (image
->Depth
== 1 && image
->IsClientData
) {
496 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
497 fprintf(stderr
, "Blit uploading\n");
499 /* Do it with a blit.
501 intelEmitCopyBlitLocked( intel
,
502 image
->TexFormat
->TexelBytes
,
503 image
->RowStride
, /* ? */
504 intelGetMemoryOffsetMESA( NULL
, 0, image
->Data
),
505 t
->Pitch
/ image
->TexFormat
->TexelBytes
,
506 intelGetMemoryOffsetMESA( NULL
, 0, t
->BufAddr
+ offset
),
513 GLuint row_len
= image
->Width
* image
->TexFormat
->TexelBytes
;
514 GLubyte
*dst
= (GLubyte
*)(t
->BufAddr
+ offset
);
515 GLubyte
*src
= (GLubyte
*)image
->Data
;
518 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
520 "Upload image %dx%dx%d offset %xm row_len %x "
521 "pitch %x depth_pitch %x\n",
522 image
->Width
, image
->Height
, image
->Depth
, offset
,
523 row_len
, t
->Pitch
, t
->depth_pitch
);
525 if (row_len
== t
->Pitch
) {
526 for (d
= 0; d
< image
->Depth
; d
++) {
527 memcpy( dst
, src
, t
->Pitch
* image
->Height
);
528 dst
+= t
->depth_pitch
;
529 src
+= row_len
* image
->Height
;
533 for (d
= 0 ; d
< image
->Depth
; d
++) {
534 for (j
= 0 ; j
< image
->Height
; j
++) {
535 __memcpy(dst
, src
, row_len
);
540 dst
+= t
->depth_pitch
- (t
->Pitch
* image
->Height
);
548 int intelUploadTexImages( intelContextPtr intel
,
549 intelTextureObjectPtr t
,
552 const int numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
553 const struct gl_texture_image
*firstImage
= t
->image
[face
][t
->base
.firstLevel
].image
;
554 int pitch
= firstImage
->RowStride
* firstImage
->TexFormat
->TexelBytes
;
556 /* Can we texture out of the existing client data? */
557 if ( numLevels
== 1 &&
558 firstImage
->IsClientData
&&
561 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
562 fprintf(stderr
, "AGP texturing from client memory\n");
564 t
->TextureOffset
= intelAgpOffsetFromVirtual( intel
, firstImage
->Data
);
570 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
571 fprintf(stderr
, "Uploading client data to agp\n");
573 INTEL_FIREVERTICES( intel
);
574 LOCK_HARDWARE( intel
);
576 if ( t
->base
.memBlock
== NULL
) {
579 heap
= driAllocateTexture( intel
->texture_heaps
, intel
->nr_heaps
,
580 (driTextureObject
*) t
);
582 UNLOCK_HARDWARE( intel
);
586 /* Set the base offset of the texture image */
587 t
->BufAddr
= intel
->intelScreen
->tex
.map
+ t
->base
.memBlock
->ofs
;
588 t
->TextureOffset
= intel
->intelScreen
->textureOffset
+ t
->base
.memBlock
->ofs
;
593 /* Let the world know we've used this memory recently.
595 driUpdateTextureLRU( (driTextureObject
*) t
);
598 /* Upload any images that are new */
599 if (t
->base
.dirty_images
[face
]) {
602 intelWaitForIdle( intel
);
604 for (i
= 0 ; i
< numLevels
; i
++) {
605 int level
= i
+ t
->base
.firstLevel
;
607 if (t
->base
.dirty_images
[face
] & (1<<level
)) {
609 const struct gl_texture_image
*image
= t
->image
[face
][i
].image
;
610 GLuint offset
= t
->image
[face
][i
].offset
;
612 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
613 fprintf(stderr
, "upload level %d, offset %x\n",
616 intelUploadTexImage( intel
, t
, image
, offset
);
619 t
->base
.dirty_images
[face
] = 0;
620 intel
->perf_boxes
|= I830_BOX_TEXTURE_LOAD
;
623 UNLOCK_HARDWARE( intel
);
629 * Allocate a new texture object.
630 * Called via ctx->Driver.NewTextureObject.
631 * Note: this function will be called during context creation to
632 * allocate the default texture objects.
633 * Note: we could use containment here to 'derive' the driver-specific
634 * texture object from the core mesa gl_texture_object. Not done at this time.
636 static struct gl_texture_object
*
637 intelNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
639 struct gl_texture_object
*obj
= _mesa_new_texture_object(ctx
, name
, target
);
640 INTEL_CONTEXT(ctx
)->vtbl
.alloc_tex_obj( obj
);
645 void intelInitTextureFuncs( struct dd_function_table
*functions
)
647 functions
->NewTextureObject
= intelNewTextureObject
;
648 functions
->ChooseTextureFormat
= intelChooseTextureFormat
;
649 functions
->TexImage1D
= intelTexImage1D
;
650 functions
->TexImage2D
= intelTexImage2D
;
651 functions
->TexImage3D
= intelTexImage3D
;
652 functions
->TexSubImage1D
= intelTexSubImage1D
;
653 functions
->TexSubImage2D
= intelTexSubImage2D
;
654 functions
->TexSubImage3D
= intelTexSubImage3D
;
655 functions
->CopyTexImage1D
= _swrast_copy_teximage1d
;
656 functions
->CopyTexImage2D
= _swrast_copy_teximage2d
;
657 functions
->CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
658 functions
->CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
659 functions
->CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
660 functions
->DeleteTexture
= intelDeleteTexture
;
661 functions
->UpdateTexturePalette
= NULL
;
662 functions
->IsTextureResident
= driIsTextureResident
;
663 functions
->TestProxyTexImage
= _mesa_test_proxy_teximage
;
664 functions
->DeleteTexture
= intelDeleteTexture
;