Tile tables for Falcon 4.0, checksums for tiles to avoid texture download to GPU, improvements on saving memory bandwidth
This commit is contained in:
parent
4c1039172a
commit
fd5ecddd8b
File diff suppressed because one or more lines are too long
|
@ -18,8 +18,8 @@ public:
|
|||
static const int MaxTiles = 12;
|
||||
struct tilesize {GLint y; GLint x[MaxTiles];};
|
||||
public:
|
||||
bool initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, const tilesize* tilesizetable, bool use_client_storage);
|
||||
bool initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, FxU32 x_tile, FxU32 y_tile, bool use_client_storage);
|
||||
bool initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, const tilesize* tilesizetable);
|
||||
bool initialise_buffers(BufferStruct* framebuffer, BufferStruct* texbuffer, FxU32 width, FxU32 height, FxU32 x_tile, FxU32 y_tile);
|
||||
void free_buffers();
|
||||
void initialise_format(GrLfbWriteMode_t format);
|
||||
bool begin_write();
|
||||
|
@ -27,6 +27,18 @@ public:
|
|||
bool end_write(FxU32 alpha);
|
||||
bool end_write(FxU32 alpha, GLfloat depth, bool pixelpipeline);
|
||||
bool end_write_opaque();
|
||||
inline FxU16 GetChromaKeyValue() {return m_ChromaKey.Scalar;};
|
||||
inline void SetChromaKeyValue(FxU16 chromakey)
|
||||
{
|
||||
#ifdef __ALTIVEC__
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
(&m_ChromaKey.Scalar)[i] = chromakey;
|
||||
}
|
||||
#else
|
||||
m_ChromaKey.Scalar = chromakey;
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
void Clear();
|
||||
bool draw(const tilesize* tilesizetable, bool pixelpipeline);
|
||||
|
@ -34,22 +46,28 @@ protected:
|
|||
int buildVertexArrays(const tilesize* tilesizetable, int vertexarrayindex);
|
||||
void set_gl_state(bool pixelpipeline);
|
||||
void restore_gl_state(bool pixelpipeline);
|
||||
inline bool createTextureData(FxU32* texbuffer, FxU32 x, FxU32 y, FxU32 x_step, FxU32 y_step);
|
||||
inline bool Convert565Kto8888(FxU16* buffer1, FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride);
|
||||
enum TileUpdateState
|
||||
{
|
||||
TileUpdateState_TileEmpty = false,
|
||||
TileUpdateState_TileDownloadToGPU = 1, // true,
|
||||
TileUpdateState_TileDrawOnly = -1 // -true
|
||||
};
|
||||
static const int m_tileCount = MaxTiles * MaxTiles;
|
||||
GLuint m_textureNames[m_tileCount];
|
||||
inline TileUpdateState createTextureData(FxU32* texbuffer, FxU32 x, FxU32 y, FxU32 x_step, FxU32 y_step, int checksumIndex);
|
||||
inline TileUpdateState Convert565Kto8888(FxU16* buffer1, FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride);
|
||||
#ifdef __ALTIVEC__
|
||||
inline bool Convert565Kto8888_AV(FxU16* buffer1, FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride);
|
||||
inline TileUpdateState Convert565Kto8888_AV(FxU16* buffer1, FxU32* buffer2, register FxU32 width, register FxU32 height, register FxU32 stride, int checksumIndex);
|
||||
vector unsigned long m_tileChecksums[m_tileCount];
|
||||
#endif
|
||||
inline bool Convert1555Kto8888(FxU16* buffer1, register FxU32* buffer2, FxU32 register width, register FxU32 height, register FxU32 stride);
|
||||
inline bool ConvertARGB8888Kto8888(FxU32* buffer1, register FxU32* buffer2, FxU32 register width, register FxU32 height, register FxU32 stride);
|
||||
static const int m_max_client_storage_textures = MaxTiles * MaxTiles;
|
||||
GLuint m_tex_name[m_max_client_storage_textures];
|
||||
inline TileUpdateState Convert1555Kto8888(FxU16* buffer1, register FxU32* buffer2, FxU32 register width, register FxU32 height, register FxU32 stride);
|
||||
inline TileUpdateState ConvertARGB8888Kto8888(FxU32* buffer1, register FxU32* buffer2, FxU32 register width, register FxU32 height, register FxU32 stride);
|
||||
bool m_use_client_storage;
|
||||
bool m_must_clear_buffer;
|
||||
GrOriginLocation_t m_origin;
|
||||
GLint m_glInternalFormat;
|
||||
GLint m_glFormat;
|
||||
GLint m_glType;
|
||||
FxU16 m_ChromaKey;
|
||||
bool m_format_valid;
|
||||
BufferStruct* m_framebuffer;
|
||||
BufferStruct* m_texbuffer;
|
||||
|
@ -66,8 +84,22 @@ protected:
|
|||
int m_customtilesizesCount;
|
||||
int m_customtilesizesVertexArrayIndex;
|
||||
GLfloat m_glDepth;
|
||||
FxU32 m_glAlpha;
|
||||
union
|
||||
{
|
||||
FxU32 Scalar;
|
||||
#ifdef __ALTIVEC__
|
||||
vector unsigned long Vector;
|
||||
#endif
|
||||
} m_glAlpha;
|
||||
// Pixelpipeline
|
||||
bool m_bRestoreColorCombine;
|
||||
bool m_bRestoreAlphaCombine;
|
||||
private:
|
||||
union
|
||||
{
|
||||
FxU16 Scalar;
|
||||
#ifdef __ALTIVEC__
|
||||
vector bool short Vector;
|
||||
#endif
|
||||
} m_ChromaKey;
|
||||
};
|
||||
|
|
|
@ -13,16 +13,24 @@
|
|||
#include "GlideFramebuffer.h"
|
||||
#include "GlideSettings.h"
|
||||
|
||||
// Custom framebuffer tiles tables to minimise calls to glTexImage2D()
|
||||
// by defining tiles that:
|
||||
// - are empty (no color conversion takes place)
|
||||
// - don't change (so they have to be downloaded to the GPU only once)
|
||||
// This does not apply to drawing underlays because they are drawn with
|
||||
// max tile sizes as they're usally used to draw fullscreen backgrounds
|
||||
|
||||
// Optimised framebuffer tile layout for Carmageddon: Minimise calls to glTexImage2D
|
||||
// Note: Carmageddon uses only the glide resolution 640x480.
|
||||
// The sum of the first column must be 480 (vertical resolution)
|
||||
// The sum of each row must be 640 (horizontal resolution)
|
||||
// This does not apply to drawing the underlay
|
||||
// (Underlays are drawn with max tile sizes because they're usally used to draw backgrounds)
|
||||
// The sum of the first column must be Glide.WindowHeigth (vertical resolution)
|
||||
// The sum of all elements in the second element of each row must be Glide.WindowWidth (horizontal resolution)
|
||||
|
||||
// Optimised framebuffer tile layout for Carmageddon:
|
||||
// Carmageddon uses only the glide resolution 640x480. The table optimised
|
||||
// the outside car view. In cockpit mode the framebuffer must be rendered two times
|
||||
// which makes everything much slower, but in cockpit mode this table allows
|
||||
// for a fluid framerate even on slow (~450 Mhz) machines
|
||||
const Framebuffer::tilesize GlideFramebuffer::tilesize_table_carmageddon[11] =
|
||||
{
|
||||
{ 64, {128,128, 8,128,128, 64, 32, 16, 8,0,0}},
|
||||
{ 64, {128,128, 8,128,128, 64, 32, 16, 8,0,0,0}},
|
||||
{ 64, {128,128,128,128, 64, 64, 0, 0, 0,0,0,0}},
|
||||
{ 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}},
|
||||
{ 32, {128,128,128,128,128, 0, 0, 0, 0,0,0,0}},
|
||||
|
@ -35,6 +43,71 @@ const Framebuffer::tilesize GlideFramebuffer::tilesize_table_carmageddon[11] =
|
|||
{ 64, { 8,128,256,128, 32, 8, 64, 16, 0,0,0,0}}
|
||||
};
|
||||
|
||||
// Optimised framebuffer tile layouts for Falcon 4.0:
|
||||
// Falcon ofers a lot of screen resolutions, so we have to provide mopre than one table.
|
||||
// If the table can be derived from a smaller one, it is scaled up to the appropriate
|
||||
// screen size. In fact, just 640x480 and 800x600 have to be hardcoded.
|
||||
|
||||
// The table optimises the main cockpit view (looking forward after pressing "2" on the keyboard")
|
||||
// Areas are kept as large as possible in order to avoid producing many small textures in other views.
|
||||
// Static tiles with artwork only at the bottom are yield good performance as the better part of
|
||||
// the tile is just read (as if the tile was totally empty) and then never gets downloaded again.
|
||||
const Framebuffer::tilesize GlideFramebuffer::tilesizeTableFalcon40_640[7] =
|
||||
{
|
||||
{ 32, {256,128,256, 0, 0, 0, 0, 0, 0,0,0,0}},
|
||||
{ 128, {128, 64,256, 64,128, 0, 0, 0, 0,0,0,0}},
|
||||
{ 64, { 32,128, 32,256, 32,128, 32, 0, 0,0,0,0}},
|
||||
{ 64, { 64,128,128,128,128, 64, 0, 0, 0,0,0,0}},
|
||||
{ 64, { 64,128,128,128,128, 64, 0, 0, 0,0,0,0}},
|
||||
{ 128, { 64,128,128,128,128, 64, 0, 0, 0,0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0}}
|
||||
};
|
||||
|
||||
const Framebuffer::tilesize GlideFramebuffer::tilesizeTableFalcon40_800[8] =
|
||||
{
|
||||
{ 8, {256,256, 32,256, 0, 0, 0, 0,0,0,0,0}},
|
||||
{ 16, {256,256, 32,256, 0, 0, 0, 0,0,0,0,0}},
|
||||
{ 128, {128,128,256, 32,128,128, 0, 0,0,0,0,0}},
|
||||
{ 128, {128,128,256, 32,128,128, 0, 0,0,0,0,0}},
|
||||
{ 64, {128,256, 32,256,128, 0, 0, 0,0,0,0,0}},
|
||||
{ 64, {128,128,128, 32,128,128,128, 0,0,0,0,0}},
|
||||
{ 64, {128,128,128, 32,128,128,128, 0,0,0,0,0}},
|
||||
{ 128, {128,128,128, 32,128,128,128, 0,0,0,0,0}}
|
||||
};
|
||||
|
||||
void GlideFramebuffer::scaleTilesizeTable(const Framebuffer::tilesize* in, Framebuffer::tilesize* out, int factor)
|
||||
{
|
||||
GLint y_step;
|
||||
int w = 0;
|
||||
for(FxU32 y = 0; y < Glide.WindowHeight && w < MaxTiles ; y += y_step, w++)
|
||||
{
|
||||
y_step = in[w].y;
|
||||
out[w].y = y_step * factor;
|
||||
GLint x_step;
|
||||
int v = 0;
|
||||
for(FxU32 x = 0; x < Glide.WindowWidth && v < MaxTiles; x += x_step, v++ )
|
||||
{
|
||||
x_step = in[w].x[v];
|
||||
out[w].x[v] = x_step * factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Framebuffer::tilesize GlideFramebuffer::tilesizeTableFalcon40Scaled[Framebuffer::MaxTiles] =
|
||||
{
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}},
|
||||
{ 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0}}
|
||||
};
|
||||
|
||||
GlideFramebuffer::GlideFramebuffer()
|
||||
: m_write_opaque(false)
|
||||
, m_must_write(false)
|
||||
|
@ -65,17 +138,45 @@ void GlideFramebuffer::initialise(BufferStruct* framebuffer, BufferStruct* texbu
|
|||
m_grLfbLockWriteMode[4] = GR_LFBWRITEMODE_UNUSED;
|
||||
m_grLfbLockWriteMode[5] = GR_LFBWRITEMODE_UNUSED;
|
||||
GlideApplication::Type application = s_GlideApplication.GetType();
|
||||
if (application == GlideApplication::Carmageddon && Glide.WindowWidth == 640 && Glide.WindowHeight == 480)
|
||||
if (application == GlideApplication::Falcon40 && Glide.WindowWidth == 640)
|
||||
{
|
||||
initialise_buffers( framebuffer, texbuffer,
|
||||
Glide.WindowWidth, Glide.WindowHeight,
|
||||
tilesize_table_carmageddon, InternalConfig.EXT_Client_Storage);
|
||||
initialise_buffers(framebuffer, texbuffer,
|
||||
Glide.WindowWidth, Glide.WindowHeight,
|
||||
tilesizeTableFalcon40_640);
|
||||
}
|
||||
else if (application == GlideApplication::Falcon40 && Glide.WindowWidth == 800)
|
||||
{
|
||||
initialise_buffers(framebuffer, texbuffer,
|
||||
Glide.WindowWidth, Glide.WindowHeight,
|
||||
tilesizeTableFalcon40_800);
|
||||
}
|
||||
else if (application == GlideApplication::Falcon40 && Glide.WindowWidth == 1280)
|
||||
{
|
||||
scaleTilesizeTable(tilesizeTableFalcon40_640,
|
||||
tilesizeTableFalcon40Scaled,
|
||||
2);
|
||||
initialise_buffers(framebuffer, texbuffer,
|
||||
Glide.WindowWidth, Glide.WindowHeight,
|
||||
tilesizeTableFalcon40Scaled);
|
||||
}
|
||||
else if (application == GlideApplication::Falcon40 && Glide.WindowWidth == 1600)
|
||||
{
|
||||
scaleTilesizeTable(tilesizeTableFalcon40_800,
|
||||
tilesizeTableFalcon40Scaled,
|
||||
2);
|
||||
initialise_buffers(framebuffer, texbuffer,
|
||||
Glide.WindowWidth, Glide.WindowHeight,
|
||||
tilesizeTableFalcon40Scaled);
|
||||
}
|
||||
else if (application == GlideApplication::Carmageddon && Glide.WindowWidth == 640 && Glide.WindowHeight == 480)
|
||||
{
|
||||
initialise_buffers(framebuffer, texbuffer,
|
||||
Glide.WindowWidth, Glide.WindowHeight,
|
||||
tilesize_table_carmageddon);
|
||||
}
|
||||
else
|
||||
{
|
||||
initialise_buffers( framebuffer, texbuffer,
|
||||
Glide.WindowWidth, Glide.WindowHeight,
|
||||
128, 128, InternalConfig.EXT_Client_Storage);
|
||||
initialise_buffers(framebuffer, texbuffer, Glide.WindowWidth, Glide.WindowHeight, 128, 128);
|
||||
}
|
||||
framebuffer->WriteMode = GR_LFBWRITEMODE_UNUSED;
|
||||
texbuffer->WriteMode = GR_LFBWRITEMODE_UNUSED;
|
||||
|
@ -127,7 +228,7 @@ void GlideFramebuffer::OnBufferLockStartWrite(GrLock_t dwType, GrBuffer_t dwBuff
|
|||
if (m_chromakeyvalue_changed && m_framebuffer->PixelPipeline)
|
||||
{
|
||||
// Apply changes to the frame buffer
|
||||
m_ChromaKey = m_chromakeyvalue_new;
|
||||
SetChromaKeyValue(m_chromakeyvalue_new);
|
||||
m_chromakeyvalue_changed = false;
|
||||
m_must_clear_buffer = true;
|
||||
begin_write();
|
||||
|
@ -233,7 +334,7 @@ void GlideFramebuffer::OnClipWindow()
|
|||
// @todo: Think this is obsolete as the case is catched by OnChromaKeyValueChanged()
|
||||
if (m_chromakeyvalue_changed)
|
||||
{
|
||||
m_ChromaKey = m_chromakeyvalue_new;
|
||||
SetChromaKeyValue(m_chromakeyvalue_new);
|
||||
m_chromakeyvalue_changed = false;
|
||||
// Fill the framebuffer with the new chromakey value
|
||||
m_must_clear_buffer = true;
|
||||
|
@ -279,7 +380,7 @@ void GlideFramebuffer::OnBeforeBufferClear()
|
|||
#endif
|
||||
m_must_write = true;
|
||||
}
|
||||
else if (m_framebuffer->Address[Glide.WindowTotalPixels >> 1] == m_ChromaKey)
|
||||
else if (m_framebuffer->Address[Glide.WindowTotalPixels >> 1] == GetChromaKeyValue())
|
||||
{
|
||||
// In Carmageddon, an opaque background is written to the frame buffer
|
||||
// as the background for the Car Damage screen. By peeking just one pixel
|
||||
|
@ -354,7 +455,7 @@ void GlideFramebuffer::OnRenderDrawTriangles()
|
|||
{
|
||||
if (m_chromakeyvalue_changed && m_framebuffer->PixelPipeline)
|
||||
{
|
||||
m_ChromaKey = m_chromakeyvalue_new;
|
||||
SetChromaKeyValue(m_chromakeyvalue_new);
|
||||
m_chromakeyvalue_changed = false;
|
||||
// Fill the framebuffer with the new chromakey value
|
||||
m_must_clear_buffer = true;
|
||||
|
@ -473,7 +574,7 @@ void GlideFramebuffer::CopyFrameBuffer(FxU16* targetbuffer)
|
|||
GlideMsg( "GlideFrameBuffer::CopyFrameBuffer( 0x%x)\n", targetbuffer);
|
||||
#endif
|
||||
|
||||
FxU16 chromakey = m_ChromaKey;
|
||||
FxU16 chromakey = GetChromaKeyValue();
|
||||
FxU16* framebuffer = m_framebuffer->Address;
|
||||
FxU32 count = m_width * m_height;
|
||||
for (FxU16* end = framebuffer + count; framebuffer < end; framebuffer++, targetbuffer++)
|
||||
|
@ -506,7 +607,7 @@ void GlideFramebuffer::OnChromaKeyValueChanged()
|
|||
#endif
|
||||
|
||||
FxU16 chromakeyvalue = GetChromaKeyValue16(Glide.State.ChromakeyValue);
|
||||
m_chromakeyvalue_changed = m_ChromaKey != chromakeyvalue;
|
||||
m_chromakeyvalue_changed = GetChromaKeyValue() != chromakeyvalue;
|
||||
m_chromakeyvalue_new = chromakeyvalue;
|
||||
if (m_must_write)
|
||||
{
|
||||
|
@ -514,7 +615,7 @@ void GlideFramebuffer::OnChromaKeyValueChanged()
|
|||
{
|
||||
// Flush the current contents of the framebuffer
|
||||
WriteFrameBuffer(m_framebuffer->PixelPipeline);
|
||||
m_ChromaKey = m_chromakeyvalue_new;
|
||||
SetChromaKeyValue(m_chromakeyvalue_new);
|
||||
m_chromakeyvalue_changed = false;
|
||||
// Fill the framebuffer with the new chromakey value
|
||||
m_must_clear_buffer = true;
|
||||
|
|
|
@ -31,6 +31,10 @@ protected:
|
|||
GrLfbWriteMode_t m_grLfbLockWriteMode[6];
|
||||
unsigned int m_bufferclearcalls;
|
||||
static const tilesize tilesize_table_carmageddon[11];
|
||||
static const tilesize tilesizeTableFalcon40_640[7];
|
||||
static const tilesize tilesizeTableFalcon40_800[8];
|
||||
static tilesize tilesizeTableFalcon40Scaled[Framebuffer::MaxTiles];
|
||||
static void scaleTilesizeTable(const tilesize* in, tilesize* out, int factor);
|
||||
public:
|
||||
void initialise(BufferStruct* framebuffer, BufferStruct* texbuffer);
|
||||
void OnBufferLockStartWrite(GrLock_t dwType, GrBuffer_t dwBuffer, GrLfbWriteMode_t dwWriteMode, GrOriginLocation_t dwOrigin, FxBool bPixelPipeline);
|
||||
|
@ -53,7 +57,7 @@ public:
|
|||
inline bool GetRenderBufferChangedForRead() const {return m_renderbuffer_changed_for_read;};
|
||||
inline void ResetRenderBufferChangedForRead() {m_renderbuffer_changed_for_read = false;};
|
||||
void CopyFrameBuffer(FxU16* targetbuffer);
|
||||
inline FxU16 GetChromaKeyValue() {return m_ChromaKey;};
|
||||
inline FxU16 GetChromaKeyValue() {return Framebuffer::GetChromaKeyValue();};
|
||||
protected:
|
||||
void WriteFrameBuffer(bool pixelpipline);
|
||||
inline bool BackBufferIsLocked() {return m_grLfbLockWriteMode[GR_BUFFER_BACKBUFFER] != GR_LFBWRITEMODE_UNUSED;};
|
||||
|
|
Loading…
Reference in New Issue