mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 14:38:18 +00:00
added a fallback system in case a graphic card don't support the texture3D size we need for the tilesets. closes #1888
This commit is contained in:
parent
4373ab0784
commit
7ff37cb9b9
|
@ -176,7 +176,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
|
|||
else if(State.m_Dimension == 3 && (m_aTextures[State.m_Texture].m_State&CTexture::STATE_TEX3D))
|
||||
{
|
||||
glEnable(GL_TEXTURE_3D);
|
||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[State.m_Texture].m_Tex3D);
|
||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[State.m_Texture].m_Tex3D[State.m_TextureArrayIndex]);
|
||||
}
|
||||
else
|
||||
dbg_msg("render", "invalid texture %d %d %d\n", State.m_Texture, State.m_Dimension, m_aTextures[State.m_Texture].m_State);
|
||||
|
@ -249,6 +249,13 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
|
|||
void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand)
|
||||
{
|
||||
m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxTexSize);
|
||||
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_Max3DTexSize);
|
||||
dbg_msg("render", "opengl max texture sizes: %d, %d(3D)", m_MaxTexSize, m_Max3DTexSize);
|
||||
if(m_Max3DTexSize < IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION)
|
||||
dbg_msg("render", "*** warning *** max 3D texture size is too low - using the fallback system");
|
||||
m_TextureArraySize = IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION / min(m_Max3DTexSize, IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION);
|
||||
*pCommand->m_pTextureArraySize = m_TextureArraySize;
|
||||
}
|
||||
|
||||
void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand)
|
||||
|
@ -267,7 +274,10 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer:
|
|||
if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX2D)
|
||||
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex2D);
|
||||
if(m_aTextures[pCommand->m_Slot].m_State&CTexture::STATE_TEX3D)
|
||||
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex3D);
|
||||
{
|
||||
for(int i = 0; i < m_TextureArraySize; ++i)
|
||||
glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex3D[i]);
|
||||
}
|
||||
*m_pTextureMemoryUsage -= m_aTextures[pCommand->m_Slot].m_MemSize;
|
||||
m_aTextures[pCommand->m_Slot].m_State = CTexture::STATE_EMPTY;
|
||||
m_aTextures[pCommand->m_Slot].m_MemSize = 0;
|
||||
|
@ -283,16 +293,13 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
|||
// resample if needed
|
||||
if(pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGBA || pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGB)
|
||||
{
|
||||
int MaxTexSize;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexSize);
|
||||
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D)
|
||||
int MaxTexSize = m_MaxTexSize;
|
||||
if((pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D) && m_Max3DTexSize >= CTexture::MIN_GL_MAX_3D_TEXTURE_SIZE)
|
||||
{
|
||||
int Max3DTexSize;
|
||||
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &Max3DTexSize);
|
||||
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE2D)
|
||||
MaxTexSize = min(MaxTexSize, Max3DTexSize*16);
|
||||
MaxTexSize = min(MaxTexSize, m_Max3DTexSize * IGraphics::NUMTILES_DIMENSION);
|
||||
else
|
||||
MaxTexSize = Max3DTexSize*16;
|
||||
MaxTexSize = m_Max3DTexSize * IGraphics::NUMTILES_DIMENSION;
|
||||
}
|
||||
if(Width > MaxTexSize || Height > MaxTexSize)
|
||||
{
|
||||
|
@ -307,7 +314,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
|||
mem_free(pTexData);
|
||||
pTexData = pTmpData;
|
||||
}
|
||||
else if(Width > 16 && Height > 16 && (pCommand->m_Flags&CCommandBuffer::TEXFLAG_QUALITY) == 0)
|
||||
else if(Width > IGraphics::NUMTILES_DIMENSION && Height > IGraphics::NUMTILES_DIMENSION && (pCommand->m_Flags&CCommandBuffer::TEXFLAG_QUALITY) == 0)
|
||||
{
|
||||
Width>>=1;
|
||||
Height>>=1;
|
||||
|
@ -382,42 +389,45 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
|
|||
}
|
||||
|
||||
// 3D texture
|
||||
if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D)
|
||||
if((pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D) && m_Max3DTexSize >= CTexture::MIN_GL_MAX_3D_TEXTURE_SIZE)
|
||||
{
|
||||
Width /= 16;
|
||||
Height /= 16;
|
||||
Depth = 256;
|
||||
Width /= IGraphics::NUMTILES_DIMENSION;
|
||||
Height /= IGraphics::NUMTILES_DIMENSION;
|
||||
Depth = min(m_Max3DTexSize, IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION);
|
||||
|
||||
// copy and reorder texture data
|
||||
int MemSize = Width*Height*Depth*pCommand->m_PixelSize;
|
||||
int MemSize = Width*Height*IGraphics::NUMTILES_DIMENSION*IGraphics::NUMTILES_DIMENSION*pCommand->m_PixelSize;
|
||||
char *pTmpData = (char *)mem_alloc(MemSize, sizeof(void*));
|
||||
|
||||
const int TileSize = (Height * Width) * pCommand->m_PixelSize;
|
||||
const int TileRowSize = Width * pCommand->m_PixelSize;
|
||||
const int ImagePitch = Width*16 * pCommand->m_PixelSize;
|
||||
const int ImagePitch = Width * IGraphics::NUMTILES_DIMENSION * pCommand->m_PixelSize;
|
||||
mem_zero(pTmpData, MemSize);
|
||||
for(int i = 0; i < 256; i++)
|
||||
for(int i = 0; i < IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION; i++)
|
||||
{
|
||||
const int px = (i%16) * Width;
|
||||
const int py = (i/16) * Height;
|
||||
const char *pTileData = (const char *)pTexData + (py * Width*16 + px) * pCommand->m_PixelSize;
|
||||
const int px = (i%IGraphics::NUMTILES_DIMENSION) * Width;
|
||||
const int py = (i/IGraphics::NUMTILES_DIMENSION) * Height;
|
||||
const char *pTileData = (const char *)pTexData + (py * Width * IGraphics::NUMTILES_DIMENSION + px) * pCommand->m_PixelSize;
|
||||
for(int y = 0; y < Height; y++)
|
||||
mem_copy(pTmpData + i*TileSize + y*TileRowSize, pTileData + y * ImagePitch, TileRowSize);
|
||||
}
|
||||
|
||||
mem_free(pTexData);
|
||||
pTexData = pTmpData;
|
||||
|
||||
//
|
||||
glGenTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex3D);
|
||||
glGenTextures(m_TextureArraySize, m_aTextures[pCommand->m_Slot].m_Tex3D);
|
||||
m_aTextures[pCommand->m_Slot].m_State |= CTexture::STATE_TEX3D;
|
||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[pCommand->m_Slot].m_Tex3D);
|
||||
for(int i = 0; i < m_TextureArraySize; ++i)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[pCommand->m_Slot].m_Tex3D[i]);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
pTexData = pTmpData+i*(Width*Height*Depth*pCommand->m_PixelSize);
|
||||
glTexImage3D(GL_TEXTURE_3D, 0, StoreOglformat, Width, Height, Depth, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage3D(GL_TEXTURE_3D, 0, StoreOglformat, Width, Height, Depth, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
|
||||
|
||||
m_aTextures[pCommand->m_Slot].m_MemSize += Width*Height*pCommand->m_PixelSize;
|
||||
m_aTextures[pCommand->m_Slot].m_MemSize += Width*Height*pCommand->m_PixelSize;
|
||||
}
|
||||
pTexData = pTmpData;
|
||||
}
|
||||
|
||||
*m_pTextureMemoryUsage += m_aTextures[pCommand->m_Slot].m_MemSize;
|
||||
|
@ -756,13 +766,14 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
|
|||
|
||||
// issue init commands for OpenGL and SDL
|
||||
CCommandBuffer CmdBuffer(1024, 512);
|
||||
CCommandProcessorFragment_OpenGL::SCommand_Init CmdOpenGL;
|
||||
CmdOpenGL.m_pTextureMemoryUsage = &m_TextureMemoryUsage;
|
||||
CmdBuffer.AddCommand(CmdOpenGL);
|
||||
CCommandProcessorFragment_SDL::SCommand_Init CmdSDL;
|
||||
CmdSDL.m_pWindow = m_pWindow;
|
||||
CmdSDL.m_GLContext = m_GLContext;
|
||||
CmdBuffer.AddCommand(CmdSDL);
|
||||
CCommandProcessorFragment_OpenGL::SCommand_Init CmdOpenGL;
|
||||
CmdOpenGL.m_pTextureMemoryUsage = &m_TextureMemoryUsage;
|
||||
CmdOpenGL.m_pTextureArraySize = &m_TextureArraySize;
|
||||
CmdBuffer.AddCommand(CmdOpenGL);
|
||||
RunBuffer(&CmdBuffer);
|
||||
WaitForIdle();
|
||||
|
||||
|
|
|
@ -91,15 +91,21 @@ class CCommandProcessorFragment_OpenGL
|
|||
STATE_EMPTY = 0,
|
||||
STATE_TEX2D = 1,
|
||||
STATE_TEX3D = 2,
|
||||
|
||||
MIN_GL_MAX_3D_TEXTURE_SIZE = 64, // GL_MAX_3D_TEXTURE_SIZE must be at least 64 according to the standard
|
||||
MAX_ARRAYSIZE_TEX3D = IGraphics::NUMTILES_DIMENSION * IGraphics::NUMTILES_DIMENSION / MIN_GL_MAX_3D_TEXTURE_SIZE, // = 4
|
||||
};
|
||||
GLuint m_Tex2D;
|
||||
GLuint m_Tex3D;
|
||||
GLuint m_Tex3D[MAX_ARRAYSIZE_TEX3D];
|
||||
int m_State;
|
||||
int m_Format;
|
||||
int m_MemSize;
|
||||
};
|
||||
CTexture m_aTextures[CCommandBuffer::MAX_TEXTURES];
|
||||
volatile int *m_pTextureMemoryUsage;
|
||||
int m_MaxTexSize;
|
||||
int m_Max3DTexSize;
|
||||
int m_TextureArraySize;
|
||||
|
||||
public:
|
||||
enum
|
||||
|
@ -111,6 +117,7 @@ public:
|
|||
{
|
||||
SCommand_Init() : SCommand(CMD_INIT) {}
|
||||
volatile int *m_pTextureMemoryUsage;
|
||||
int *m_pTextureArraySize;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -189,11 +196,13 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
|
|||
ICommandProcessor *m_pProcessor;
|
||||
volatile int m_TextureMemoryUsage;
|
||||
int m_NumScreens;
|
||||
int m_TextureArraySize;
|
||||
public:
|
||||
virtual int Init(const char *pName, int *Screen, int *Width, int *Height, int FsaaSamples, int Flags, int *pDesktopWidth, int *pDesktopHeight);
|
||||
virtual int Shutdown();
|
||||
|
||||
virtual int MemoryUsage() const;
|
||||
virtual int GetTextureArraySize() const { return m_TextureArraySize; }
|
||||
|
||||
virtual int GetNumScreens() const { return m_NumScreens; }
|
||||
|
||||
|
|
|
@ -373,6 +373,9 @@ IGraphics::CTextureHandle CGraphics_Threaded::LoadTextureRaw(int Width, int Heig
|
|||
|
||||
//
|
||||
m_pCommandBuffer->AddCommand(Cmd);
|
||||
// kick the buffer and wait for the result
|
||||
KickCommandBuffer();
|
||||
WaitForIdle();
|
||||
|
||||
return CreateTextureHandle(Tex);
|
||||
}
|
||||
|
@ -522,6 +525,7 @@ void CGraphics_Threaded::QuadsBegin()
|
|||
QuadsSetSubset(0,0,1,1,-1);
|
||||
QuadsSetRotation(0);
|
||||
SetColor(1,1,1,1);
|
||||
m_TextureArrayIndex = m_pBackend->GetTextureArraySize() > 1 ? -1 : 0;
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::QuadsEnd()
|
||||
|
@ -572,17 +576,36 @@ void CGraphics_Threaded::SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft,
|
|||
SetColorVertex(Array, 4);
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::TilesetFallbackSystem(int TextureIndex)
|
||||
{
|
||||
int NewTextureArrayIndex = TextureIndex / (256 / m_pBackend->GetTextureArraySize());
|
||||
if(m_TextureArrayIndex == -1)
|
||||
m_TextureArrayIndex = NewTextureArrayIndex;
|
||||
else if(m_TextureArrayIndex != NewTextureArrayIndex)
|
||||
{
|
||||
// have to switch the texture index
|
||||
FlushVertices();
|
||||
m_TextureArrayIndex = NewTextureArrayIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics_Threaded::QuadsSetSubset(float TlU, float TlV, float BrU, float BrV, int TextureIndex)
|
||||
{
|
||||
dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin");
|
||||
|
||||
// tileset fallback system
|
||||
if(m_pBackend->GetTextureArraySize() > 1 && TextureIndex >= 0)
|
||||
TilesetFallbackSystem(TextureIndex);
|
||||
|
||||
m_State.m_TextureArrayIndex = m_TextureArrayIndex;
|
||||
|
||||
m_aTexture[0].u = TlU; m_aTexture[1].u = BrU;
|
||||
m_aTexture[0].v = TlV; m_aTexture[1].v = TlV;
|
||||
|
||||
m_aTexture[3].u = TlU; m_aTexture[2].u = BrU;
|
||||
m_aTexture[3].v = BrV; m_aTexture[2].v = BrV;
|
||||
|
||||
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / 256.0f;
|
||||
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / (256.0f/m_pBackend->GetTextureArraySize());
|
||||
m_State.m_Dimension = (TextureIndex < 0) ? 2 : 3;
|
||||
}
|
||||
|
||||
|
@ -590,12 +613,18 @@ void CGraphics_Threaded::QuadsSetSubsetFree(
|
|||
float x0, float y0, float x1, float y1,
|
||||
float x2, float y2, float x3, float y3, int TextureIndex)
|
||||
{
|
||||
// tileset fallback system
|
||||
if(m_pBackend->GetTextureArraySize() > 1 && TextureIndex >= 0)
|
||||
TilesetFallbackSystem(TextureIndex);
|
||||
|
||||
m_State.m_TextureArrayIndex = m_TextureArrayIndex;
|
||||
|
||||
m_aTexture[0].u = x0; m_aTexture[0].v = y0;
|
||||
m_aTexture[1].u = x1; m_aTexture[1].v = y1;
|
||||
m_aTexture[2].u = x2; m_aTexture[2].v = y2;
|
||||
m_aTexture[3].u = x3; m_aTexture[3].v = y3;
|
||||
|
||||
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / 256.0f;
|
||||
m_aTexture[0].i = m_aTexture[1].i = m_aTexture[2].i = m_aTexture[3].i = (0.5f + TextureIndex) / (256.0f/m_pBackend->GetTextureArraySize());
|
||||
m_State.m_Dimension = (TextureIndex < 0) ? 2 : 3;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,7 @@ public:
|
|||
int m_WrapModeU;
|
||||
int m_WrapModeV;
|
||||
int m_Texture;
|
||||
int m_TextureArrayIndex;
|
||||
int m_Dimension;
|
||||
SPoint m_ScreenTL;
|
||||
SPoint m_ScreenBR;
|
||||
|
@ -316,6 +317,7 @@ public:
|
|||
virtual int Shutdown() = 0;
|
||||
|
||||
virtual int MemoryUsage() const = 0;
|
||||
virtual int GetTextureArraySize() const = 0;
|
||||
|
||||
virtual int GetNumScreens() const = 0;
|
||||
|
||||
|
@ -372,6 +374,7 @@ class CGraphics_Threaded : public IEngineGraphics
|
|||
|
||||
CTextureHandle m_InvalidTexture;
|
||||
|
||||
int m_TextureArrayIndex;
|
||||
int m_aTextureIndices[MAX_TEXTURES];
|
||||
int m_FirstFreeTexture;
|
||||
int m_TextureMemoryUsage;
|
||||
|
@ -429,6 +432,7 @@ public:
|
|||
virtual void SetColor(float r, float g, float b, float a);
|
||||
virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight);
|
||||
|
||||
void TilesetFallbackSystem(int TextureIndex);
|
||||
virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV, int TextureIndex = -1);
|
||||
virtual void QuadsSetSubsetFree(
|
||||
float x0, float y0, float x1, float y1,
|
||||
|
|
|
@ -70,6 +70,8 @@ public:
|
|||
TEXLOAD_ARRAY_256 = 4,
|
||||
TEXLOAD_MULTI_DIMENSION = 8,
|
||||
TEXLOAD_LINEARMIPMAPS = 16,
|
||||
|
||||
NUMTILES_DIMENSION = 16, // number of tiles in each dimension within a texture
|
||||
};
|
||||
|
||||
/* Constants: Wrap Modes */
|
||||
|
|
Loading…
Reference in a new issue