⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 savagetex.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. 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 * 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 * VIA, S3 GRAPHICS, AND/OR ITS 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. */#include <stdlib.h>#include <stdio.h>#include <GL/gl.h>#include "mm.h"#include "savagecontext.h"#include "savagetex.h"#include "savagetris.h"#include "savageioctl.h"#include "simple_list.h"#include "enums.h"#include "savage_bci.h"#include "macros.h"#include "texformat.h"#include "texstore.h"#include "texobj.h"#include "convolve.h"#include "colormac.h"#include "swrast/swrast.h"#include "xmlpool.h"#define TILE_INDEX_DXT1 0#define TILE_INDEX_8    1#define TILE_INDEX_16   2#define TILE_INDEX_DXTn 3#define TILE_INDEX_32   4/* On Savage4 the texure LOD-bias needs an offset of ~ 0.3 to get * somewhere close to software rendering. */#define SAVAGE4_LOD_OFFSET 10/* Tile info for S3TC formats counts in 4x4 blocks instead of texels. * In DXT1 each block is encoded in 64 bits. In DXT3 and 5 each block is * encoded in 128 bits. *//* Size 1, 2 and 4 images are packed into the last subtile. Each image * is repeated to fill a 4x4 pixel area. The figure below shows the * layout of those 4x4 pixel areas in the 8x8 subtile. * *    4 2 *    x 1 * * Yuck! 8-bit texture formats use 4x8 subtiles. See below. */static const savageTileInfo tileInfo_pro[5] = {    {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */    {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */    {64, 16,  8, 2, 8, 8, {0x48, 0x08}}, /* 16-bit */    {16,  8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */    {32, 16,  4, 2, 8, 8, {0x90, 0x10}}, /* 32-bit */};/* Size 1, 2 and 4 images are packed into the last two subtiles. Each * image is repeated to fill a 4x4 pixel area. The figures below show * the layout of those 4x4 pixel areas in the two 4x8 subtiles. * * second last subtile: 4   last subtile: 2 *                      x                 1 */static const savageTileInfo tileInfo_s3d_s4[5] = {    {16, 16, 16, 8, 1, 2, {0x18, 0x10}}, /* DXT1 */    {64, 32, 16, 4, 4, 8, {0x30, 0x20}}, /* 8-bit */    {64, 16, 16, 2, 4, 8, {0x60, 0x40}}, /* 16-bit */    {16,  8, 16, 4, 1, 2, {0x30, 0x20}}, /* DXT3, DXT5 */    {32, 16,  8, 2, 4, 8, {0xc0, 0x80}}, /* 32-bit */};/** \brief Template for subtile uploads. * \param h   height in pixels * \param w   width in bytes */#define SUBTILE_FUNC(w,h)					\static INLINE GLubyte *savageUploadSubtile_##w##x##h		\(GLubyte *dest, GLubyte *src, GLuint srcStride)			\{								\    GLuint y;							\    for (y = 0; y < h; ++y) {					\	memcpy (dest, src, w);					\	src += srcStride;					\	dest += w;						\    }								\    return dest;						\}SUBTILE_FUNC(2, 8) /* 4 bits per pixel, 4 pixels wide */SUBTILE_FUNC(4, 8)SUBTILE_FUNC(8, 8)SUBTILE_FUNC(16, 8)SUBTILE_FUNC(32, 8) /* 4 bytes per pixel, 8 pixels wide */SUBTILE_FUNC(8, 2) /* DXT1 */SUBTILE_FUNC(16, 2) /* DXT3 and DXT5 *//** \brief Upload a complete tile from src (srcStride) to dest * * \param tileInfo     Pointer to tiling information * \param wInSub       Width of source/dest image in subtiles * \param hInSub       Height of source/dest image in subtiles * \param bpp          Bytes per pixel * \param src          Pointer to source data * \param srcStride    Byte stride of rows in the source data * \param dest         Pointer to destination * * Writes linearly to the destination memory in order to exploit write * combining. * * For a complete tile wInSub and hInSub are set to the same values as * in tileInfo. If the source image is smaller than a whole tile in * one or both dimensions then they are set to the values of the * source image. This only works as long as the source image is bigger * than 8x8 pixels. */static void savageUploadTile (const savageTileInfo *tileInfo,			      GLuint wInSub, GLuint hInSub, GLuint bpp,			      GLubyte *src, GLuint srcStride, GLubyte *dest) {    GLuint subStride = tileInfo->subWidth * bpp;    GLubyte *srcSRow = src, *srcSTile = src;    GLubyte *(*subtileFunc) (GLubyte *, GLubyte *, GLuint);    GLuint sx, sy;    switch (subStride) {    case  2: subtileFunc = savageUploadSubtile_2x8; break;    case  4: subtileFunc = savageUploadSubtile_4x8; break;    case  8: subtileFunc = tileInfo->subHeight == 8 ?		 savageUploadSubtile_8x8 : savageUploadSubtile_8x2; break;    case 16: subtileFunc = tileInfo->subHeight == 8 ?		 savageUploadSubtile_16x8 : savageUploadSubtile_16x2; break;    case 32: subtileFunc = savageUploadSubtile_32x8; break;    default: assert(0);    }    for (sy = 0; sy < hInSub; ++sy) {	srcSTile = srcSRow;	for (sx = 0; sx < wInSub; ++sx) {	    src = srcSTile;	    dest = subtileFunc (dest, src, srcStride);	    srcSTile += subStride;	}	srcSRow += srcStride * tileInfo->subHeight;    }}/** \brief Upload a image that is smaller than 8 pixels in either dimension. * * \param tileInfo    Pointer to tiling information * \param width       Width of the image * \param height      Height of the image * \param bpp         Bytes per pixel * \param src         Pointer to source data * \param dest        Pointer to destination * * This function handles all the special cases that need to be taken * care off. The caller may need to call this function multiple times * with the destination offset in different ways since small texture * images must be repeated in order to fill a whole tile (or 4x4 for * the last 3 levels). * * FIXME: Repeating inside this function would be more efficient. */static void savageUploadTiny (const savageTileInfo *tileInfo,			      GLuint pixWidth, GLuint pixHeight,			      GLuint width, GLuint height, GLuint bpp,			      GLubyte *src, GLubyte *dest) {    GLuint size = MAX2(pixWidth, pixHeight);    if (width > tileInfo->subWidth) { /* assert: height <= subtile height */	GLuint wInSub = width / tileInfo->subWidth;	GLuint srcStride = width * bpp;	GLuint subStride = tileInfo->subWidth * bpp;	GLuint subSkip = (tileInfo->subHeight - height) * subStride;	GLubyte *srcSTile = src;	GLuint sx, y;	for (sx = 0; sx < wInSub; ++sx) {	    src = srcSTile;	    for (y = 0; y < height; ++y) {		memcpy (dest, src, subStride);		src += srcStride;		dest += subStride;	    }	    dest += subSkip;	    srcSTile += subStride;	}    } else if (size > 4) { /* a tile or less wide, except the last 3 levels */	GLuint srcStride = width * bpp;	GLuint subStride = tileInfo->subWidth * bpp;	/* if the subtile width is 4 we have to skip every other subtile */	GLuint subSkip = tileInfo->subWidth <= 4 ?	    subStride * tileInfo->subHeight : 0;	GLuint skipRemainder = tileInfo->subHeight - 1;	GLuint y;	for (y = 0; y < height; ++y) {	    memcpy (dest, src, srcStride);	    src += srcStride;	    dest += subStride;	    if ((y & skipRemainder) == skipRemainder)		dest += subSkip;	}    } else { /* the last 3 mipmap levels */	GLuint offset = (size <= 2 ? tileInfo->tinyOffset[size-1] : 0);	GLuint subStride = tileInfo->subWidth * bpp;	GLuint y;	dest += offset;	for (y = 0; y < height; ++y) {	    memcpy (dest, src, bpp*width);	    src += width * bpp;	    dest += subStride;	}    }}/** \brief Upload an image from mesa's internal copy. */static void savageUploadTexLevel( savageTexObjPtr t, int level ){    const struct gl_texture_image *image = t->base.tObj->Image[0][level];    const savageTileInfo *tileInfo = t->tileInfo;    GLuint pixWidth = image->Width2, pixHeight = image->Height2;    GLuint bpp = t->texelBytes;    GLuint width, height;    /* FIXME: Need triangle (rather than pixel) fallbacks to simulate     * this using normal textured triangles.     *     * DO THIS IN DRIVER STATE MANAGMENT, not hardware state.     */    if(image->Border != 0) 	fprintf (stderr, "Not supported texture border %d.\n",		 (int) image->Border);    if (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||	t->hwFormat == TFT_S3TC4Bit) {	width = (pixWidth+3) / 4;	height = (pixHeight+3) / 4;    } else {	width = pixWidth;	height = pixHeight;    }    if (pixWidth >= 8 && pixHeight >= 8) {	GLuint *dirtyPtr = t->image[level].dirtyTiles;	GLuint dirtyMask = 1;	if (width >= tileInfo->width && height >= tileInfo->height) {	    GLuint wInTiles = width / tileInfo->width;	    GLuint hInTiles = height / tileInfo->height;	    GLubyte *srcTRow = image->Data, *src;	    GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);	    GLuint x, y;	    for (y = 0; y < hInTiles; ++y) {		src = srcTRow;		for (x = 0; x < wInTiles; ++x) {		    if (*dirtyPtr & dirtyMask) {			savageUploadTile (tileInfo,					  tileInfo->wInSub, tileInfo->hInSub,					  bpp, src, width * bpp, dest);		    }		    src += tileInfo->width * bpp;		    dest += 2048; /* tile size is always 2k */		    if (dirtyMask == 1<<31) {			dirtyMask = 1;			dirtyPtr++;		    } else			dirtyMask <<= 1;		}		srcTRow += width * tileInfo->height * bpp;	    }	} else if (width >= tileInfo->width) {	    GLuint wInTiles = width / tileInfo->width;	    GLubyte *src = image->Data;	    GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);	    GLuint tileStride = tileInfo->width * bpp * height;	    savageContextPtr imesa = (savageContextPtr)t->base.heap->driverContext;	    GLuint x;	    /* Savage3D-based chips seem so use a constant tile stride	     * of 2048 for vertically incomplete tiles, but only if	     * the color depth is 32bpp. Nobody said this was supposed	     * to be logical!	     */	    if (bpp == 4 && imesa->savageScreen->chipset < S3_SAVAGE4)		tileStride = 2048;	    for (x = 0; x < wInTiles; ++x) {		if (*dirtyPtr & dirtyMask) {		    savageUploadTile (tileInfo,				      tileInfo->wInSub,				      height / tileInfo->subHeight,				      bpp, src, width * bpp, dest);		}		src += tileInfo->width * bpp;		dest += tileStride;		if (dirtyMask == 1<<31) {		    dirtyMask = 1;		    dirtyPtr++;		} else		    dirtyMask <<= 1;	    }	} else {	    savageUploadTile (tileInfo, width / tileInfo->subWidth,			      height / tileInfo->subHeight, bpp,			      image->Data, width * bpp,			      (GLubyte *)(t->bufAddr+t->image[level].offset));	}    } else {	GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;	if (t->hwFormat == TFT_S3TC4A4Bit || t->hwFormat == TFT_S3TC4CA4Bit ||	    t->hwFormat == TFT_S3TC4Bit)	    minWidth = minHeight = 1;	else	    minWidth = minHeight = 4;	if (width > minWidth || height > minHeight) {	    minWidth = tileInfo->subWidth;	    minHeight = tileInfo->subHeight;	}	hRepeat = width  >= minWidth  ? 1 : minWidth  / width;	vRepeat = height >= minHeight ? 1 : minHeight / height;	for (y = 0; y < vRepeat; ++y) {	    GLuint offset = y * tileInfo->subWidth*height * bpp;	    for (x = 0; x < hRepeat; ++x) {		savageUploadTiny (tileInfo, pixWidth, pixHeight,				  width, height, bpp, image->Data,				  (GLubyte *)(t->bufAddr +					      t->image[level].offset+offset));		offset += width * bpp;	    }	}    }}/** \brief Compute the destination size of a texture image */static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) {    /* full subtiles */    if (width >= 8 && height >= 8)	return width * height * bpp;    /* special case for the last three mipmap levels: the hardware computes     * the offset internally */    else if (width <= 4 && height <= 4)	return 0;    /* partially filled sub tiles waste memory     * on Savage3D and Savage4 with subtile width 4 every other subtile is     * skipped if width < 8 so we can assume a uniform subtile width of 8 */    else if (width >= 8)	return width * 8 * bpp;    else if (height >= 8)	return 8 * height * bpp;    else	return 64 * bpp;}/** \brief Compute the destination size of a compressed texture image */static GLuint savageCompressedTexImageSize (GLuint width, GLuint height,					    GLuint bpp) {    width = (width+3) / 4;    height = (height+3) / 4;    /* full subtiles */    if (width >= 2 && height >= 2)	return width * height * bpp;    /* special case for the last three mipmap levels: the hardware computes     * the offset internally */    else if (width <= 1 && height <= 1)	return 0;    /* partially filled sub tiles waste memory     * on Savage3D and Savage4 with subtile width 4 every other subtile is     * skipped if width < 8 so we can assume a uniform subtile width of 8 */    else if (width >= 2)	return width * 2 * bpp;    else if (height >= 2)	return 2 * height * bpp;    else	return 4 * bpp;}/** \brief Compute the number of (partial) tiles of a texture image */static GLuint savageTexImageTiles (GLuint width, GLuint height,				   const savageTileInfo *tileInfo){   return (width + tileInfo->width - 1) / tileInfo->width *      (height + tileInfo->height - 1) / tileInfo->height;}/** \brief Mark dirty tiles * * Some care must be taken because tileInfo may not be set or not * up-to-date. So we check if tileInfo is initialized and if the number * of tiles in the bit vector matches the number of tiles computed from

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -