summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/sis/sis_tex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/sis/sis_tex.c')
-rw-r--r--src/mesa/drivers/dri/sis/sis_tex.c474
1 files changed, 474 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/sis/sis_tex.c b/src/mesa/drivers/dri/sis/sis_tex.c
new file mode 100644
index 0000000000..52080b7037
--- /dev/null
+++ b/src/mesa/drivers/dri/sis/sis_tex.c
@@ -0,0 +1,474 @@
+/**************************************************************************
+
+Copyright 2003 Eric Anholt
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+/* $XFree86$ */
+
+/*
+ * Authors:
+ * Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "sis_context.h"
+#include "sis_alloc.h"
+#include "sis_tex.h"
+
+#include "swrast/swrast.h"
+#include "imports.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "teximage.h"
+
+#define ALIGN(value, align) (char *)((long)(value + align - 1) & ~(align - 1))
+
+#define TEXTURE_HW_ALIGNMENT 4
+#define TEXTURE_HW_PLUS (4 + 4)
+
+static sisTexObjPtr
+sisAllocTexObj( struct gl_texture_object *texObj )
+{
+ sisTexObjPtr t;
+
+ t = (sisTexObjPtr) CALLOC_STRUCT( sis_tex_obj );
+ texObj->DriverData = t;
+ return t;
+}
+
+static void
+sisAllocTexImage( sisContextPtr smesa, sisTexObjPtr t, int level,
+ const struct gl_texture_image *image )
+{
+ char *addr;
+ int size, texel_size;
+
+ if (t->format == 0) {
+ t->format = image->Format;
+ switch (t->format)
+ {
+ case GL_RGBA:
+ t->hwformat = TEXEL_ARGB_8888_32;
+ break;
+ case GL_INTENSITY:
+ t->hwformat = TEXEL_I8;
+ break;
+ case GL_ALPHA:
+ t->hwformat = TEXEL_A8;
+ break;
+ case GL_LUMINANCE:
+ t->hwformat = TEXEL_L8;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ t->hwformat = TEXEL_AL88;
+ break;
+ case GL_RGB:
+ t->hwformat = TEXEL_ARGB_0888_32;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ assert(t->format == image->Format);
+
+ texel_size = image->TexFormat->TexelBytes;
+ size = image->Width * image->Height * texel_size + TEXTURE_HW_PLUS;
+
+ addr = sisAllocFB( smesa, size, &t->image[level].handle );
+ if (addr == NULL) {
+ addr = sisAllocAGP( smesa, size, &t->image[level].handle );
+ if (addr == NULL) {
+ fprintf (stderr, "SIS driver : out of video/agp memory\n");
+ sis_fatal_error();
+ }
+ t->image[level].memType = AGP_TYPE;
+ }
+ else
+ t->image[level].memType = VIDEO_TYPE;
+
+ t->image[level].Data = ALIGN(addr, TEXTURE_HW_ALIGNMENT);
+ t->image[level].pitch = image->Width * texel_size;
+ t->image[level].size = image->Width * image->Height * texel_size;
+ t->numImages++;
+}
+
+static void
+sisFreeTexImage( sisContextPtr smesa, sisTexObjPtr t, int level )
+{
+ if (t->image[level].Data == NULL)
+ return;
+
+ switch (t->image[level].memType)
+ {
+ case VIDEO_TYPE:
+ sisFreeFB( smesa, t->image[level].handle );
+ break;
+ case AGP_TYPE:
+ sisFreeAGP( smesa, t->image[level].handle );
+ break;
+ }
+ t->image[level].Data = NULL;
+ t->image[level].handle = NULL;
+ /* If there are no textures loaded any more, reset the hw format so the
+ * object can be reused for new formats
+ */
+ t->numImages--;
+ if (t->numImages == 0) {
+ t->format = 0;
+ t->hwformat = 0;
+ }
+}
+
+static void
+sisDDTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
+}
+
+static void
+sisDDTexParameter( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj, GLenum pname,
+ const GLfloat *params )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
+}
+
+static void
+sisDDBindTexture( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *texObj )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+ sisTexObjPtr t;
+
+ if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
+ if ( texObj->DriverData == NULL ) {
+ sisAllocTexObj( texObj );
+ }
+ }
+
+ t = texObj->DriverData;
+
+ if (t == NULL)
+ return;
+
+ if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format) {
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
+ smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
+ }
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
+}
+
+static void
+sisDDDeleteTexture( GLcontext * ctx, struct gl_texture_object *texObj )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+ sisTexObjPtr t;
+ int i;
+
+ smesa->clearTexCache = GL_TRUE;
+
+ t = texObj->DriverData;
+ if (t == NULL) {
+ /*
+ * this shows the texture is default object and never be a
+ * argument of sisDDTexImage*
+ */
+ return;
+ }
+ for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
+ sisFreeTexImage( smesa, t, i );
+ }
+
+ FREE(t);
+ texObj->DriverData = NULL;
+}
+
+static GLboolean sisDDIsTextureResident( GLcontext * ctx,
+ struct gl_texture_object *texObj )
+{
+ return (texObj->DriverData != NULL);
+}
+
+static const struct gl_texture_format *
+sisDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ /* XXX 16-bit internal texture formats? */
+ switch ( internalFormat ) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_i8;
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_argb8888 /*_mesa_texformat_rgb888*/; /* XXX */
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ default:
+ _mesa_problem(ctx, "unexpected format in tdfxDDChooseTextureFormat: %d",
+ internalFormat);
+ return NULL;
+ }
+}
+
+static void sisDDTexImage1D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+ sisTexObjPtr t;
+
+ if ( texObj->DriverData == NULL )
+ sisAllocTexObj( texObj );
+ t = texObj->DriverData;
+
+ /* Note, this will call sisDDChooseTextureFormat */
+ _mesa_store_teximage1d( ctx, target, level, internalFormat,
+ width, border, format, type,
+ pixels, packing, texObj, texImage );
+
+ /* Allocate offscreen space for the texture */
+ sisFreeTexImage(smesa, t, level);
+ sisAllocTexImage(smesa, t, level, texImage);
+
+ /* Upload the texture */
+ memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
+
+ if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
+ {
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
+ smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
+ }
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
+}
+
+
+static void sisDDTexSubImage1D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+ sisTexObjPtr t;
+ GLuint copySize;
+ GLint texelBytes;
+ char *src, *dst;
+
+ if ( texObj->DriverData == NULL )
+ sisAllocTexObj( texObj );
+ t = texObj->DriverData;
+
+ _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+ format, type, pixels, packing, texObj,
+ texImage);
+
+ /* Allocate offscreen space for the texture */
+ sisFreeTexImage(smesa, t, level);
+ sisAllocTexImage(smesa, t, level, texImage);
+
+ /* Upload the texture */
+ texelBytes = texImage->TexFormat->TexelBytes;
+
+ copySize = width * texelBytes;
+ src = (char *)texImage->Data + xoffset * texelBytes;
+ dst = t->image[level].Data + xoffset * texelBytes;
+
+ memcpy( dst, src, copySize );
+
+ smesa->clearTexCache = GL_TRUE;
+
+ if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
+ {
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
+ smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
+ }
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
+}
+
+static void sisDDTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+ sisTexObjPtr t;
+
+ if ( texObj->DriverData == NULL )
+ sisAllocTexObj( texObj );
+ t = texObj->DriverData;
+
+ /* Note, this will call sisDDChooseTextureFormat */
+ _mesa_store_teximage2d(ctx, target, level, internalFormat,
+ width, height, border, format, type, pixels,
+ &ctx->Unpack, texObj, texImage);
+
+ /* Allocate offscreen space for the texture */
+ sisFreeTexImage(smesa, t, level);
+ sisAllocTexImage(smesa, t, level, texImage);
+
+ /* Upload the texture */
+ memcpy(t->image[level].Data, texImage->Data, t->image[level].size);
+
+ if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
+ {
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
+ smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
+ }
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
+}
+
+static void sisDDTexSubImage2D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ sisContextPtr smesa = SIS_CONTEXT(ctx);
+ sisTexObjPtr t;
+ GLuint copySize;
+ GLint texelBytes;
+ char *src, *dst;
+ int j;
+ GLuint soffset;
+
+ if ( texObj->DriverData == NULL )
+ sisAllocTexObj( texObj );
+ t = texObj->DriverData;
+
+ _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+ height, format, type, pixels, packing, texObj,
+ texImage);
+
+ /* Allocate offscreen space for the texture */
+ sisFreeTexImage(smesa, t, level);
+ sisAllocTexImage(smesa, t, level, texImage);
+
+ /* Upload the texture */
+ texelBytes = texImage->TexFormat->TexelBytes;
+
+ copySize = width * texelBytes;
+ src = (char *)texImage->Data + (xoffset + yoffset * texImage->Width) *
+ texelBytes;
+ dst = t->image[level].Data + (xoffset + yoffset * texImage->Width) *
+ texelBytes;
+ soffset = texImage->Width * texelBytes;
+
+ for (j = yoffset; j < yoffset + height; j++) {
+ memcpy( dst, src, copySize );
+ src += soffset;
+ dst += soffset;
+ }
+
+ smesa->clearTexCache = GL_TRUE;
+
+ if (smesa->PrevTexFormat[ctx->Texture.CurrentUnit] != t->format)
+ {
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURE_ENV;
+ smesa->PrevTexFormat[ctx->Texture.CurrentUnit] = t->format;
+ }
+ smesa->TexStates[ctx->Texture.CurrentUnit] |= NEW_TEXTURING;
+
+}
+
+void sisDDInitTextureFuncs( GLcontext *ctx )
+{
+ ctx->Driver.TexEnv = sisDDTexEnv;
+ ctx->Driver.ChooseTextureFormat = sisDDChooseTextureFormat;
+ ctx->Driver.TexImage1D = sisDDTexImage1D;
+ ctx->Driver.TexSubImage1D = sisDDTexSubImage1D;
+ ctx->Driver.TexImage2D = sisDDTexImage2D;
+ ctx->Driver.TexSubImage2D = sisDDTexSubImage2D;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+ ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+ ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+ ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+ ctx->Driver.TexParameter = sisDDTexParameter;
+ ctx->Driver.BindTexture = sisDDBindTexture;
+ ctx->Driver.DeleteTexture = sisDDDeleteTexture;
+ ctx->Driver.IsTextureResident = sisDDIsTextureResident;
+ ctx->Driver.PrioritizeTexture = NULL;
+}