Using APPLE_CLIENT_TEXTURE_EXT for all textures

This commit is contained in:
Jens Hemprich 2006-09-03 19:50:40 +00:00
parent 3b6147c73f
commit ac74e81105
2 changed files with 169 additions and 181 deletions

View File

@ -68,6 +68,17 @@ PGTexture::PGTexture( int mem_size )
m_chromakey_mode = GR_CHROMAKEY_DISABLE; m_chromakey_mode = GR_CHROMAKEY_DISABLE;
m_tex_memory_size = mem_size; m_tex_memory_size = mem_size;
m_memory = (FxU8*) AllocBuffer(mem_size, sizeof(FxU8)); m_memory = (FxU8*) AllocBuffer(mem_size, sizeof(FxU8));
if (InternalConfig.EXT_Client_Storage)
{
// Alloc 4-times the size of the Glide buffer for texture storage
m_textureCache = reinterpret_cast<FxU32*>(AllocBuffer(m_tex_memory_size, sizeof(FxU32)));
// No memory is wasted here because we save the internal OpenGL copy
}
else
{
m_textureCache = NULL;
}
// Needed for subtexturing and internal conversions
m_tex_temp = reinterpret_cast<FxU32*>(AllocBuffer(256 * 256, sizeof(FxU32))); m_tex_temp = reinterpret_cast<FxU32*>(AllocBuffer(256 * 256, sizeof(FxU32)));
m_ncc_select = GR_NCCTABLE_NCC0; m_ncc_select = GR_NCCTABLE_NCC0;
@ -97,21 +108,20 @@ PGTexture::~PGTexture( void )
{ {
FreeBuffer(m_memory); FreeBuffer(m_memory);
FreeBuffer(m_tex_temp); FreeBuffer(m_tex_temp);
if (m_textureCache) FreeBuffer(m_textureCache);
delete m_db; delete m_db;
} }
void PGTexture::DownloadMipMap( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info ) void PGTexture::DownloadMipMap( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info )
{ {
const FxU32 mip_size = MipMapMemRequired( info->smallLod, const FxU32 mip_size = MipMapMemRequired(info->smallLod,
info->aspectRatio, info->aspectRatio,
info->format ); info->format);
const FxU32 mip_offset = startAddress + TextureMemRequired( evenOdd, info ); const FxU32 mip_offset = startAddress + TextureMemRequired(evenOdd, info);
if ( mip_offset <= m_tex_memory_size ) if ( mip_offset <= m_tex_memory_size )
{ {
memcpy( m_memory + mip_offset - mip_size, info->data, mip_size ); memcpy( m_memory + mip_offset - mip_size, info->data, mip_size );
} }
// Any texture based on memory crossing this range // Any texture based on memory crossing this range
// is now out of date // is now out of date
m_db->WipeRange( startAddress, mip_offset, 0 ); m_db->WipeRange( startAddress, mip_offset, 0 );
@ -206,7 +216,7 @@ void PGTexture::DownloadMipMapLevelPartial(FxU32 startAddress,
m_db->WipeRange(startAddress, mip_offset, 0); m_db->WipeRange(startAddress, mip_offset, 0);
} }
void PGTexture::Source( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info ) void PGTexture::Source(FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info)
{ {
m_startAddress = startAddress; m_startAddress = startAddress;
m_evenOdd = evenOdd; m_evenOdd = evenOdd;
@ -565,28 +575,6 @@ bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_tr
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, OpenGL.TClampMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, OpenGL.TClampMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, OpenGL.MinFilterMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, OpenGL.MinFilterMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, OpenGL.MagFilterMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, OpenGL.MagFilterMode);
// Texture artefact fix for TR2
// This would solve remaining issues with texture artefacts caused by filtering,
// but degrades the overall image quality too much
/*
bool fix_subtexture_artefacts = false;
if (subtexcoords)
{
// While TR1 uses subtextures with power-of-2 sizes only (as far as I know),
// some TR2 textures don't fit into this scheme, and thus still produces artefacts
// (for instance the joins in Lara's hair and butler james clothes)
const GLfloat epsilon = 0.75;
if (subtexcoords->width / static_cast<GLfloat>(subtexcoords->texImageWidth) <= epsilon ||
subtexcoords->height / static_cast<GLfloat>(subtexcoords->texImageHeight) <= epsilon)
{
// The artefacts can be fixed by applying neither mipmapping nor anisotropic filtering
fix_subtexture_artefacts = true;
}
}
// These are constant parameters and don't change between calls
const unsigned long anisotropy_level = fix_subtexture_artefacts ? 1 : InternalConfig.AnisotropylLevel;
const bool enable_mipmaps = fix_subtexture_artefacts ? false : InternalConfig.Mipmapping;
*/
const unsigned long anisotropy_level = InternalConfig.AnisotropylLevel; const unsigned long anisotropy_level = InternalConfig.AnisotropylLevel;
const bool enable_mipmaps = InternalConfig.Mipmapping; const bool enable_mipmaps = InternalConfig.Mipmapping;
// Write only if enabled in config // Write only if enabled in config
@ -637,16 +625,6 @@ bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_tr
if (subtexcoords) if (subtexcoords)
{ {
/*
// Don't generate mipmaps in DownloadMipmapsToOpenGL()
if (fix_subtexture_artefacts)
{
// Pretend to have mipmap ext in order to
// avoid generating mipmaps without mipmap ext
use_mipmap_ext = true;
glBindTexture(GL_TEXTURE_2D, OpenGL.DummyTextureName);
}
*/
glPixelStorei(GL_UNPACK_SKIP_PIXELS, subtexcoords->left); glPixelStorei(GL_UNPACK_SKIP_PIXELS, subtexcoords->left);
glPixelStorei(GL_UNPACK_SKIP_ROWS, subtexcoords->top); glPixelStorei(GL_UNPACK_SKIP_ROWS, subtexcoords->top);
glPixelStorei(GL_UNPACK_ROW_LENGTH, texVals.width); glPixelStorei(GL_UNPACK_ROW_LENGTH, texVals.width);
@ -654,14 +632,29 @@ bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_tr
texVals.width = subtexcoords->texImageWidth; texVals.width = subtexcoords->texImageWidth;
texVals.height = subtexcoords->texImageHeight; texVals.height = subtexcoords->texImageHeight;
} }
// use client storage to avoid OpenGL-internal copy
// OpenGL may still make a copy if the colro format isn't supported natively
// by the graphics card but all xto8888 conversions should benefit from this
const bool useClientStorage = InternalConfig.EXT_Client_Storage && !subtexcoords;
FxU32* texBuffer;
if (useClientStorage)
{
texBuffer = &m_textureCache[m_startAddress];
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, true);
glReportError();
}
else
{
texBuffer = m_tex_temp;
}
// Convert Glide texture data to format understood by OpenGL
switch ( m_info.format ) switch ( m_info.format )
{ {
case GR_TEXFMT_RGB_565: case GR_TEXFMT_RGB_565:
if ( m_chromakey_mode ) if ( m_chromakey_mode )
{ {
// Read about anisotropy and chromakey issues in macFormatConversions.cpp // Read about anisotropy and chromakey issues in macFormatConversions.cpp
Convert565Kto8888((FxU16*)data, m_chromakey_value_565, m_tex_temp, texVals.nPixels); Convert565Kto8888((FxU16*)data, m_chromakey_value_565, texBuffer, texVals.nPixels);
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext);
} }
else else
@ -676,8 +669,8 @@ bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_tr
if (m_chromakey_mode) if (m_chromakey_mode)
{ {
// Read about anisotropy and chromakey issues in macFormatConversions.cpp // Read about anisotropy and chromakey issues in macFormatConversions.cpp
Convert1555Kto8888((FxU16*) data, m_chromakey_value_1555, m_tex_temp, texVals.nPixels); Convert1555Kto8888((FxU16*) data, m_chromakey_value_1555, texBuffer, texVals.nPixels);
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
} }
else else
{ {
@ -703,45 +696,45 @@ bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_tr
if (InternalConfig.AnisotropylLevel >= 2) if (InternalConfig.AnisotropylLevel >= 2)
{ {
// minimise anisotropy artefacts // minimise anisotropy artefacts
ConvertP8Kto8888(data, m_chromakey_value_8888, m_tex_temp, texVals.nPixels, m_palette); ConvertP8Kto8888(data, m_chromakey_value_8888, texBuffer, texVals.nPixels, m_palette);
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
} }
else else
{ {
ConvertP8to8888(data, m_tex_temp, texVals.nPixels, m_palette); ConvertP8to8888(data, texBuffer, texVals.nPixels, m_palette);
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
} }
} }
break; break;
case GR_TEXFMT_AP_88: case GR_TEXFMT_AP_88:
if ( use_two_textures ) if ( use_two_textures )
{ {
FxU32 *tex_temp2 = m_tex_temp + 256 * 128; FxU32 *texBuffer2 = texBuffer + 256 * 128;
glColorTable(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_palette); glColorTable(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, m_palette);
SplitAP88( (FxU16 *)data, (FxU8 *)m_tex_temp, (FxU8 *)tex_temp2, texVals.nPixels ); SplitAP88((FxU16*) data, (FxU8*) texBuffer, (FxU8*) texBuffer2, texVals.nPixels);
glTexImage2D( GL_TEXTURE_2D, texVals.lod, GL_COLOR_INDEX8_EXT, glTexImage2D(GL_TEXTURE_2D, texVals.lod, GL_COLOR_INDEX8_EXT,
texVals.width, texVals.height, 0, texVals.width, texVals.height, 0,
GL_COLOR_INDEX, GL_UNSIGNED_BYTE, m_tex_temp ); GL_COLOR_INDEX, GL_UNSIGNED_BYTE, texBuffer);
if (InternalConfig.Mipmapping && !use_mipmap_ext) if (InternalConfig.Mipmapping && !use_mipmap_ext)
{ {
genPaletteMipmaps( texVals.width, texVals.height, (FxU8 *)m_tex_temp ); genPaletteMipmaps(texVals.width, texVals.height, (FxU8*) texBuffer);
} }
glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1); glActiveTextureARB(OpenGL.ColorAlphaUnit1 + 1);
DownloadMipmapsToOpenGL( GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, tex_temp2, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL( GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, texBuffer2, texVals, !use_mipmap_ext);
glActiveTextureARB(OpenGL.ColorAlphaUnit1); glActiveTextureARB(OpenGL.ColorAlphaUnit1);
glReportError(); glReportError();
} }
else else
{ {
ConvertAP88to8888( (FxU16*)data, m_tex_temp, texVals.nPixels, m_palette ); ConvertAP88to8888((FxU16*) data, texBuffer, texVals.nPixels, m_palette );
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
} }
break; break;
case GR_TEXFMT_ALPHA_8: case GR_TEXFMT_ALPHA_8:
ConvertA8toAP88( (FxU8*)data, (FxU16*)m_tex_temp, texVals.nPixels ); ConvertA8toAP88((FxU8*)data, (FxU16*) texBuffer, texVals.nPixels);
DownloadMipmapsToOpenGL( 2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
// @todo: The statement below breaks the overlay texts in Myth TFL. // @todo: The statement below breaks the overlay texts in Myth TFL.
// As a result ,this optimsation has been undone for now // As a result, this optimsation has been undone for now
// DownloadMipmapsToOpenGL(1, GL_ALPHA, GL_UNSIGNED_BYTE, data, texVals, !use_mipmap_ext); // DownloadMipmapsToOpenGL(1, GL_ALPHA, GL_UNSIGNED_BYTE, data, texVals, !use_mipmap_ext);
break; break;
case GR_TEXFMT_ALPHA_INTENSITY_88: case GR_TEXFMT_ALPHA_INTENSITY_88:
@ -754,14 +747,14 @@ bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_tr
// @todo: untested // @todo: untested
// DownloadMipmapsToOpenGL(GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data, &texVals); // DownloadMipmapsToOpenGL(GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data, &texVals);
// @todo: untested // @todo: untested
ConvertAI44toAP88((FxU8*)data, (FxU16*)m_tex_temp, texVals.nPixels); ConvertAI44toAP88((FxU8*)data, (FxU16*)texBuffer, texVals.nPixels);
DownloadMipmapsToOpenGL(2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
/* /*
ConvertAI44toAP88( (FxU8*)data, (FxU16*)m_tex_temp, texVals.nPixels ); ConvertAI44toAP88((FxU8*) data, (FxU16*) texBuffer, texVals.nPixels );
glTexImage2D( GL_TEXTURE_2D, texVals.lod, 2, texVals.width, texVals.height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp ); glTexImage2D(GL_TEXTURE_2D, texVals.lod, 2, texVals.width, texVals.height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, texBuffer);
if (InternalConfig.Mipmapping && !use_mipmap_ext) if (InternalConfig.Mipmapping && !use_mipmap_ext)
{ {
gluBuild2DMipmaps( GL_TEXTURE_2D, 2, texVals.width, texVals.height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, m_tex_temp ); gluBuild2DMipmaps(GL_TEXTURE_2D, 2, texVals.width, texVals.height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, texBuffer);
} }
glReportError(); glReportError();
*/ */
@ -770,27 +763,33 @@ bool PGTexture::MakeReady(TTextureStruct* tex_coords, unsigned long number_of_tr
DownloadMipmapsToOpenGL(3, GL_RGB, GL_UNSIGNED_BYTE_3_3_2_EXT, data, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(3, GL_RGB, GL_UNSIGNED_BYTE_3_3_2_EXT, data, texVals, !use_mipmap_ext);
break; break;
case GR_TEXFMT_16BIT: //GR_TEXFMT_ARGB_8332: case GR_TEXFMT_16BIT: //GR_TEXFMT_ARGB_8332:
Convert8332to8888( (FxU16*)data, m_tex_temp, texVals.nPixels ); Convert8332to8888( (FxU16*)data, texBuffer, texVals.nPixels );
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
break; break;
case GR_TEXFMT_YIQ_422: case GR_TEXFMT_YIQ_422:
ConvertYIQto8888( (FxU8*)data, m_tex_temp, texVals.nPixels, &(m_ncc[m_ncc_select]) ); ConvertYIQto8888((FxU8*) data, texBuffer, texVals.nPixels, &(m_ncc[m_ncc_select]));
// @todo: Should just be RGB in order to apply constant color per default, shouldn't it? // @todo: Should just be RGB in order to apply constant alpha, shouldn't it?
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
break; break;
case GR_TEXFMT_AYIQ_8422: case GR_TEXFMT_AYIQ_8422:
ConvertAYIQto8888( (FxU16*)data, m_tex_temp, texVals.nPixels, &(m_ncc[m_ncc_select]) ); ConvertAYIQto8888((FxU16*) data, texBuffer, texVals.nPixels, &(m_ncc[m_ncc_select]));
DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(4, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
break; break;
case GR_TEXFMT_RSVD0: case GR_TEXFMT_RSVD0:
case GR_TEXFMT_RSVD1: case GR_TEXFMT_RSVD1:
case GR_TEXFMT_RSVD2: case GR_TEXFMT_RSVD2:
default: default:
GlideMsg("Error: grTexDownloadMipMapLevel - Unsupported format(%d)\n", m_info.format); GlideMsg("Error: grTexDownloadMipMapLevel - Unsupported format(%d)\n", m_info.format);
memset( m_tex_temp, 255, texVals.nPixels * 2 ); memset(texBuffer, 255, texVals.nPixels * 2);
DownloadMipmapsToOpenGL(1, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_tex_temp, texVals, !use_mipmap_ext); DownloadMipmapsToOpenGL(1, GL_LUMINANCE, GL_UNSIGNED_BYTE, texBuffer, texVals, !use_mipmap_ext);
break; break;
} }
// Cleanup
if (useClientStorage)
{
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, false);
glReportError();
}
if (subtexcoords) if (subtexcoords)
{ {
// restore values // restore values
@ -849,11 +848,6 @@ void PGTexture::GetTexValues( TexValues * tval ) const
tval->lod = 0; tval->lod = 0;
} }
void PGTexture::Clear( void )
{
m_db->Clear( );
}
void PGTexture::ChromakeyValue( GrColor_t value ) void PGTexture::ChromakeyValue( GrColor_t value )
{ {
m_chromakey_value_8888 = (value & 0xffffff00); // RGB, Alpha ommited m_chromakey_value_8888 = (value & 0xffffff00); // RGB, Alpha ommited

View File

@ -36,19 +36,12 @@ public:
static void genPaletteMipmaps( FxU32 width, FxU32 height, const FxU8 *data ); static void genPaletteMipmaps( FxU32 width, FxU32 height, const FxU8 *data );
void ChromakeyMode( GrChromakeyMode_t mode ); void ChromakeyMode( GrChromakeyMode_t mode );
void ChromakeyValue( GrColor_t value ); void ChromakeyValue( GrColor_t value );
inline float GetHAspect() const inline float GetHAspect() const {return m_hAspect;}
{ inline float GetWAspect() const {return m_wAspect;}
return m_hAspect; inline const GrTexInfo* GetCurrentTexInfo() const {return &m_info;}
} inline void Clear() {m_db->Clear();}
inline float GetWAspect() const inline void initOpenGL() {m_db->initOpenGL();}
{ inline void cleanupOpenGL() {m_db->cleanupOpenGL();}
return m_wAspect;
}
inline const GrTexInfo* GetCurrentTexInfo() const
{
return &m_info;
}
void Clear();
bool MakeReady(TTextureStruct* tex_coords = NULL, unsigned long number_of_triangles = 0); bool MakeReady(TTextureStruct* tex_coords = NULL, unsigned long number_of_triangles = 0);
void DownloadTable( GrTexTable_t type, const FxU32 *data, int first, int count ); void DownloadTable( GrTexTable_t type, const FxU32 *data, int first, int count );
void Source( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info ); void Source( FxU32 startAddress, FxU32 evenOdd, const GrTexInfo *info );
@ -109,6 +102,7 @@ private:
float m_wAspect; float m_wAspect;
float m_hAspect; float m_hAspect;
FxU32* m_tex_temp; FxU32* m_tex_temp;
FxU32* m_textureCache;
bool m_valid; bool m_valid;
FxU8 * m_memory; FxU8 * m_memory;
FxU32 m_startAddress; FxU32 m_startAddress;