1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
31 #include "simple_list.h"
35 #include "texformat.h"
39 #include "swrast/swrast.h"
43 #include "intel_screen.h"
44 #include "intel_batchbuffer.h"
45 #include "intel_context.h"
46 #include "intel_tex.h"
47 #include "intel_ioctl.h"
52 intelValidateClientStorage( intelContextPtr intel
, GLenum target
,
54 GLint srcWidth
, GLint srcHeight
,
55 GLenum format
, GLenum type
, const void *pixels
,
56 const struct gl_pixelstore_attrib
*packing
,
57 struct gl_texture_object
*texObj
,
58 struct gl_texture_image
*texImage
)
61 GLcontext
*ctx
= &intel
->ctx
;
65 fprintf(stderr
, "intformat %s format %s type %s\n",
66 _mesa_lookup_enum_by_nr( internalFormat
),
67 _mesa_lookup_enum_by_nr( format
),
68 _mesa_lookup_enum_by_nr( type
));
70 if (!ctx
->Unpack
.ClientStorage
)
73 if (ctx
->_ImageTransferState
||
74 texImage
->IsCompressed
||
75 texObj
->GenerateMipmap
)
79 /* This list is incomplete
81 switch ( internalFormat
) {
83 if ( format
== GL_BGRA
&& type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
84 texImage
->TexFormat
= &_mesa_texformat_argb8888
;
92 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
93 texImage
->TexFormat
= &_mesa_texformat_rgb565
;
101 if ( format
== GL_YCBCR_MESA
&&
102 type
== GL_UNSIGNED_SHORT_8_8_REV_APPLE
) {
103 texImage
->TexFormat
= &_mesa_texformat_ycbcr_rev
;
106 else if ( format
== GL_YCBCR_MESA
&&
107 (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
108 type
== GL_UNSIGNED_BYTE
)) {
109 texImage
->TexFormat
= &_mesa_texformat_ycbcr
;
121 /* Could deal with these packing issues, but currently don't:
123 if (packing
->SkipPixels
||
125 packing
->SwapBytes
||
131 GLint srcRowStride
= _mesa_image_row_stride(packing
, srcWidth
,
136 fprintf(stderr
, "%s: srcRowStride %d/%x\n",
137 __FUNCTION__
, srcRowStride
, srcRowStride
);
139 /* Could check this later in upload, pitch restrictions could be
140 * relaxed, but would need to store the image pitch somewhere,
141 * as packing details might change before image is uploaded:
143 if (!intelIsAgpMemory( intel
, pixels
, srcHeight
* srcRowStride
) ||
148 /* Have validated that _mesa_transfer_teximage would be a straight
149 * memcpy at this point. NOTE: future calls to TexSubImage will
150 * overwrite the client data. This is explicitly mentioned in the
153 texImage
->Data
= (void *)pixels
;
154 texImage
->IsClientData
= GL_TRUE
;
155 texImage
->RowStride
= srcRowStride
/ texelBytes
;
162 static void intelTexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
163 GLint internalFormat
,
164 GLint width
, GLint border
,
165 GLenum format
, GLenum type
, const GLvoid
*pixels
,
166 const struct gl_pixelstore_attrib
*packing
,
167 struct gl_texture_object
*texObj
,
168 struct gl_texture_image
*texImage
)
170 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
174 driSwapOutTextureObject( t
);
176 texImage
->IsClientData
= GL_FALSE
;
178 _mesa_store_teximage1d( ctx
, target
, level
, internalFormat
,
179 width
, border
, format
, type
,
180 pixels
, packing
, texObj
, texImage
);
182 t
->dirty_images
[0] |= (1 << level
);
185 static void intelTexSubImage1D( GLcontext
*ctx
,
190 GLenum format
, GLenum type
,
191 const GLvoid
*pixels
,
192 const struct gl_pixelstore_attrib
*packing
,
193 struct gl_texture_object
*texObj
,
194 struct gl_texture_image
*texImage
)
196 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
200 driSwapOutTextureObject( t
);
202 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
203 format
, type
, pixels
, packing
, texObj
,
208 /* Handles 2D, CUBE, RECT:
210 static void intelTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
211 GLint internalFormat
,
212 GLint width
, GLint height
, GLint border
,
213 GLenum format
, GLenum type
, const GLvoid
*pixels
,
214 const struct gl_pixelstore_attrib
*packing
,
215 struct gl_texture_object
*texObj
,
216 struct gl_texture_image
*texImage
)
218 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
221 /* which cube face or ordinary 2D image */
223 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
224 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
225 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
226 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
227 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
228 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
229 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
238 driSwapOutTextureObject( t
);
239 texImage
->IsClientData
= GL_FALSE
;
241 if (intelValidateClientStorage( INTEL_CONTEXT(ctx
), target
,
244 format
, type
, pixels
,
245 packing
, texObj
, texImage
)) {
246 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
247 fprintf(stderr
, "%s: Using client storage\n", __FUNCTION__
);
250 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
251 width
, height
, border
, format
, type
,
252 pixels
, packing
, texObj
, texImage
);
254 t
->dirty_images
[face
] |= (1 << level
);
258 static void intelTexSubImage2D( GLcontext
*ctx
,
261 GLint xoffset
, GLint yoffset
,
262 GLsizei width
, GLsizei height
,
263 GLenum format
, GLenum type
,
264 const GLvoid
*pixels
,
265 const struct gl_pixelstore_attrib
*packing
,
266 struct gl_texture_object
*texObj
,
267 struct gl_texture_image
*texImage
)
269 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
272 /* which cube face or ordinary 2D image */
274 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
276 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
277 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
278 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
279 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
280 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
287 if (texImage
->IsClientData
&&
288 (char *)pixels
== (char *)texImage
->Data
+
289 ((xoffset
+ yoffset
* texImage
->RowStride
) *
290 texImage
->TexFormat
->TexelBytes
)) {
292 /* Notification only - no upload required */
295 assert( t
); /* this _should_ be true */
297 driSwapOutTextureObject( t
);
299 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
300 height
, format
, type
, pixels
, packing
, texObj
,
303 t
->dirty_images
[face
] |= (1 << level
);
309 static void intelTexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
310 GLint internalFormat
,
311 GLint width
, GLint height
, GLint depth
,
313 GLenum format
, GLenum type
, const GLvoid
*pixels
,
314 const struct gl_pixelstore_attrib
*packing
,
315 struct gl_texture_object
*texObj
,
316 struct gl_texture_image
*texImage
)
318 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
321 driSwapOutTextureObject( t
);
322 texImage
->IsClientData
= GL_FALSE
;
324 _mesa_store_teximage3d(ctx
, target
, level
, internalFormat
,
325 width
, height
, depth
, border
,
326 format
, type
, pixels
,
327 &ctx
->Unpack
, texObj
, texImage
);
329 t
->dirty_images
[0] |= (1 << level
);
334 intelTexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
335 GLint xoffset
, GLint yoffset
, GLint zoffset
,
336 GLsizei width
, GLsizei height
, GLsizei depth
,
337 GLenum format
, GLenum type
,
338 const GLvoid
*pixels
,
339 const struct gl_pixelstore_attrib
*packing
,
340 struct gl_texture_object
*texObj
,
341 struct gl_texture_image
*texImage
)
343 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
345 assert( t
); /* this _should_ be true */
346 driSwapOutTextureObject( t
);
348 _mesa_store_texsubimage3d(ctx
, target
, level
, xoffset
, yoffset
, zoffset
,
349 width
, height
, depth
,
350 format
, type
, pixels
, packing
, texObj
, texImage
);
352 t
->dirty_images
[0] |= (1 << level
);
358 static void intelDeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
360 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
364 driDestroyTextureObject( t
);
367 /* Free mipmap images and the texture object itself */
368 _mesa_delete_texture_object(ctx
, tObj
);
372 static const struct gl_texture_format
*
373 intelChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
374 GLenum format
, GLenum type
)
376 intelContextPtr intel
= INTEL_CONTEXT( ctx
);
377 const GLboolean do32bpt
= ( intel
->intelScreen
->cpp
== 4 &&
378 intel
->intelScreen
->textureSize
> 4*1024*1024);
380 switch ( internalFormat
) {
383 case GL_COMPRESSED_RGBA
:
384 if ( format
== GL_BGRA
) {
385 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
386 return &_mesa_texformat_argb8888
;
388 else if ( type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
389 return &_mesa_texformat_argb4444
;
391 else if ( type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
392 return &_mesa_texformat_argb1555
;
395 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
399 case GL_COMPRESSED_RGB
:
400 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
401 return &_mesa_texformat_rgb565
;
403 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
409 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
413 return &_mesa_texformat_argb4444
;
416 return &_mesa_texformat_argb1555
;
422 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
427 return &_mesa_texformat_rgb565
;
434 case GL_COMPRESSED_ALPHA
:
435 /* if (1 || intel->intelScreen->deviceID == PCI_CHIP_I915_G) */
436 return &_mesa_texformat_a8
;
438 /* return &_mesa_texformat_al88; */
446 case GL_COMPRESSED_LUMINANCE
:
447 return &_mesa_texformat_l8
;
450 case GL_LUMINANCE_ALPHA
:
451 case GL_LUMINANCE4_ALPHA4
:
452 case GL_LUMINANCE6_ALPHA2
:
453 case GL_LUMINANCE8_ALPHA8
:
454 case GL_LUMINANCE12_ALPHA4
:
455 case GL_LUMINANCE12_ALPHA12
:
456 case GL_LUMINANCE16_ALPHA16
:
457 case GL_COMPRESSED_LUMINANCE_ALPHA
:
458 return &_mesa_texformat_al88
;
465 case GL_COMPRESSED_INTENSITY
:
466 return &_mesa_texformat_i8
;
469 if (type
== GL_UNSIGNED_SHORT_8_8_MESA
||
470 type
== GL_UNSIGNED_BYTE
)
471 return &_mesa_texformat_ycbcr
;
473 return &_mesa_texformat_ycbcr_rev
;
476 fprintf(stderr
, "unexpected texture format in %s\n", __FUNCTION__
);
480 return NULL
; /* never get here */
485 void intelDestroyTexObj(intelContextPtr intel
, intelTextureObjectPtr t
)
492 if ( t
->age
> intel
->dirtyAge
)
493 intel
->dirtyAge
= t
->age
;
495 for ( i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++ ) {
496 if ( t
== intel
->CurrentTexObj
[ i
] )
497 intel
->CurrentTexObj
[ i
] = NULL
;
503 /* Upload an image from mesa's internal copy. Image may be 1D, 2D or
504 * 3D. Cubemaps are expanded elsewhere.
506 static void intelUploadTexImage( intelContextPtr intel
,
507 intelTextureObjectPtr t
,
508 const struct gl_texture_image
*image
,
509 const GLuint offset
)
512 if (!image
|| !image
->Data
)
515 if (image
->Depth
== 1 && image
->IsClientData
) {
516 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
517 fprintf(stderr
, "Blit uploading\n");
519 /* Do it with a blit.
521 intelEmitCopyBlitLocked( intel
,
522 image
->TexFormat
->TexelBytes
,
523 image
->RowStride
, /* ? */
524 intelGetMemoryOffsetMESA( NULL
, 0, image
->Data
),
525 t
->Pitch
/ image
->TexFormat
->TexelBytes
,
526 intelGetMemoryOffsetMESA( NULL
, 0, t
->BufAddr
+ offset
),
533 GLuint row_len
= image
->Width
* image
->TexFormat
->TexelBytes
;
534 GLubyte
*dst
= (GLubyte
*)(t
->BufAddr
+ offset
);
535 GLubyte
*src
= (GLubyte
*)image
->Data
;
538 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
540 "Upload image %dx%dx%d offset %xm row_len %x "
541 "pitch %x depth_pitch %x\n",
542 image
->Width
, image
->Height
, image
->Depth
, offset
,
543 row_len
, t
->Pitch
, t
->depth_pitch
);
545 if (row_len
== t
->Pitch
) {
546 for (d
= 0; d
< image
->Depth
; d
++) {
547 memcpy( dst
, src
, t
->Pitch
* image
->Height
);
548 dst
+= t
->depth_pitch
;
549 src
+= row_len
* image
->Height
;
553 for (d
= 0 ; d
< image
->Depth
; d
++) {
554 for (j
= 0 ; j
< image
->Height
; j
++) {
555 __memcpy(dst
, src
, row_len
);
560 dst
+= t
->depth_pitch
- (t
->Pitch
* image
->Height
);
568 int intelUploadTexImages( intelContextPtr intel
,
569 intelTextureObjectPtr t
,
572 const int numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
573 const struct gl_texture_image
*firstImage
= t
->image
[face
][t
->base
.firstLevel
].image
;
574 int pitch
= firstImage
->RowStride
* firstImage
->TexFormat
->TexelBytes
;
576 /* Can we texture out of the existing client data? */
577 if ( numLevels
== 1 &&
578 firstImage
->IsClientData
&&
581 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
582 fprintf(stderr
, "AGP texturing from client memory\n");
584 t
->TextureOffset
= intelAgpOffsetFromVirtual( intel
, firstImage
->Data
);
590 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
591 fprintf(stderr
, "Uploading client data to agp\n");
593 INTEL_FIREVERTICES( intel
);
594 LOCK_HARDWARE( intel
);
596 if ( t
->base
.memBlock
== NULL
) {
599 heap
= driAllocateTexture( intel
->texture_heaps
, intel
->nr_heaps
,
600 (driTextureObject
*) t
);
602 UNLOCK_HARDWARE( intel
);
606 /* Set the base offset of the texture image */
607 t
->BufAddr
= intel
->intelScreen
->tex
.map
+ t
->base
.memBlock
->ofs
;
608 t
->TextureOffset
= intel
->intelScreen
->textureOffset
+ t
->base
.memBlock
->ofs
;
613 /* Let the world know we've used this memory recently.
615 driUpdateTextureLRU( (driTextureObject
*) t
);
618 /* Upload any images that are new */
619 if (t
->base
.dirty_images
[face
]) {
622 intelWaitForIdle( intel
);
624 for (i
= 0 ; i
< numLevels
; i
++) {
625 int level
= i
+ t
->base
.firstLevel
;
627 if (t
->base
.dirty_images
[face
] & (1<<level
)) {
629 const struct gl_texture_image
*image
= t
->image
[face
][i
].image
;
630 GLuint offset
= t
->image
[face
][i
].offset
;
632 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
633 fprintf(stderr
, "upload level %d, offset %x\n",
636 intelUploadTexImage( intel
, t
, image
, offset
);
639 t
->base
.dirty_images
[face
] = 0;
640 intel
->perf_boxes
|= I830_BOX_TEXTURE_LOAD
;
643 UNLOCK_HARDWARE( intel
);
649 * Allocate a new texture object.
650 * Called via ctx->Driver.NewTextureObject.
651 * Note: this function will be called during context creation to
652 * allocate the default texture objects.
653 * Note: we could use containment here to 'derive' the driver-specific
654 * texture object from the core mesa gl_texture_object. Not done at this time.
656 static struct gl_texture_object
*
657 intelNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
659 struct gl_texture_object
*obj
= _mesa_new_texture_object(ctx
, name
, target
);
660 INTEL_CONTEXT(ctx
)->vtbl
.alloc_tex_obj( obj
);
665 void intelInitTextureFuncs( struct dd_function_table
*functions
)
667 functions
->NewTextureObject
= intelNewTextureObject
;
668 functions
->ChooseTextureFormat
= intelChooseTextureFormat
;
669 functions
->TexImage1D
= intelTexImage1D
;
670 functions
->TexImage2D
= intelTexImage2D
;
671 functions
->TexImage3D
= intelTexImage3D
;
672 functions
->TexSubImage1D
= intelTexSubImage1D
;
673 functions
->TexSubImage2D
= intelTexSubImage2D
;
674 functions
->TexSubImage3D
= intelTexSubImage3D
;
675 functions
->CopyTexImage1D
= _swrast_copy_teximage1d
;
676 functions
->CopyTexImage2D
= _swrast_copy_teximage2d
;
677 functions
->CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
678 functions
->CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
679 functions
->CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
680 functions
->DeleteTexture
= intelDeleteTexture
;
681 functions
->UpdateTexturePalette
= NULL
;
682 functions
->IsTextureResident
= driIsTextureResident
;
683 functions
->TestProxyTexImage
= _mesa_test_proxy_teximage
;
684 functions
->DeleteTexture
= intelDeleteTexture
;