forked from Mirrors/openclonk
C4Surface: Remove broken "support" for split textures
Most code already didn't handle textures larger than GL_MAX_TEXTURE_SIZE and only used the first one in case of a split texture.liquid_container
parent
7b04914fc4
commit
64a5388d4d
|
@ -349,7 +349,7 @@ bool C4Draw::BlitUnscaled(C4Surface * sfcSource, float fx, float fy, float fwdt,
|
|||
// prepare rendering to surface
|
||||
if (!PrepareRendering(sfcTarget)) return false;
|
||||
// texture present?
|
||||
if (sfcSource->textures.empty())
|
||||
if (!sfcSource->texture)
|
||||
{
|
||||
// primary surface?
|
||||
if (sfcSource->fPrimary)
|
||||
|
@ -361,83 +361,47 @@ bool C4Draw::BlitUnscaled(C4Surface * sfcSource, float fx, float fy, float fwdt,
|
|||
}
|
||||
// blit with basesfc?
|
||||
bool fBaseSfc=false;
|
||||
if (sfcSource->pMainSfc) if (!sfcSource->pMainSfc->textures.empty()) fBaseSfc = true;
|
||||
if (sfcSource->pMainSfc) if (sfcSource->pMainSfc->texture) fBaseSfc = true;
|
||||
// get involved texture offsets
|
||||
int iTexSizeX=sfcSource->iTexSize;
|
||||
int iTexSizeY=sfcSource->iTexSize;
|
||||
int iTexX=std::max(int(fx/iTexSizeX), 0);
|
||||
int iTexY=std::max(int(fy/iTexSizeY), 0);
|
||||
int iTexX2=std::min((int)(fx+fwdt-1)/iTexSizeX +1, sfcSource->iTexX);
|
||||
int iTexY2=std::min((int)(fy+fhgt-1)/iTexSizeY +1, sfcSource->iTexY);
|
||||
// blit from all these textures
|
||||
for (int iY=iTexY; iY<iTexY2; ++iY)
|
||||
|
||||
C4TexRef *pTex = sfcSource->texture.get();
|
||||
// set up blit data
|
||||
C4BltVertex vertices[6];
|
||||
vertices[0].ftx = tx; vertices[0].fty = ty;
|
||||
vertices[1].ftx = tx + twdt; vertices[1].fty = ty;
|
||||
vertices[2].ftx = tx + twdt; vertices[2].fty = ty + thgt;
|
||||
vertices[3].ftx = tx; vertices[3].fty = ty + thgt;
|
||||
vertices[0].tx = fx / pTex->iSizeX; vertices[0].ty = fy / pTex->iSizeY;
|
||||
vertices[1].tx = (fx + fwdt) / pTex->iSizeX; vertices[1].ty = fy / pTex->iSizeY;
|
||||
vertices[2].tx = (fx + fwdt) / pTex->iSizeX; vertices[2].ty = (fy + fhgt) / pTex->iSizeY;
|
||||
vertices[3].tx = fx / pTex->iSizeX; vertices[3].ty = (fy + fhgt) / pTex->iSizeY;
|
||||
DwTo4UB(0xffffffff, vertices[0].color);
|
||||
DwTo4UB(0xffffffff, vertices[1].color);
|
||||
DwTo4UB(0xffffffff, vertices[2].color);
|
||||
DwTo4UB(0xffffffff, vertices[3].color);
|
||||
|
||||
// duplicate vertices
|
||||
vertices[4] = vertices[0]; vertices[5] = vertices[2];
|
||||
|
||||
C4TexRef * pBaseTex = pTex;
|
||||
// is there a base-surface to be blitted first?
|
||||
if (fBaseSfc)
|
||||
{
|
||||
for (int iX=iTexX; iX<iTexX2; ++iX)
|
||||
{
|
||||
C4TexRef *pTex = &sfcSource->textures[iY * sfcSource->iTexX + iX];
|
||||
// get current blitting offset in texture
|
||||
int iBlitX=sfcSource->iTexSize*iX;
|
||||
int iBlitY=sfcSource->iTexSize*iY;
|
||||
// size changed? recalc dependant, relevant (!) values
|
||||
if (iTexSizeX != pTex->iSizeX)
|
||||
{
|
||||
iTexSizeX = pTex->iSizeX;
|
||||
}
|
||||
if (iTexSizeY != pTex->iSizeY)
|
||||
{
|
||||
iTexSizeY = pTex->iSizeY;
|
||||
}
|
||||
|
||||
// get new texture source bounds
|
||||
FLOAT_RECT fTexBlt;
|
||||
fTexBlt.left = std::max<float>(fx - iBlitX, 0);
|
||||
fTexBlt.top = std::max<float>(fy - iBlitY, 0);
|
||||
fTexBlt.right = std::min<float>(fx + fwdt - (float)iBlitX, (float)iTexSizeX);
|
||||
fTexBlt.bottom= std::min<float>(fy + fhgt - (float)iBlitY, (float)iTexSizeY);
|
||||
// get new dest bounds
|
||||
FLOAT_RECT tTexBlt;
|
||||
tTexBlt.left = (fTexBlt.left + iBlitX - fx) * scaleX + tx;
|
||||
tTexBlt.top = (fTexBlt.top + iBlitY - fy) * scaleY + ty;
|
||||
tTexBlt.right = (fTexBlt.right + iBlitX - fx) * scaleX + tx;
|
||||
tTexBlt.bottom= (fTexBlt.bottom+ iBlitY - fy) * scaleY + ty;
|
||||
|
||||
// set up blit data as rect
|
||||
C4BltVertex vertices[6];
|
||||
vertices[0].ftx = tTexBlt.left; vertices[0].fty = tTexBlt.top;
|
||||
vertices[1].ftx = tTexBlt.right; vertices[1].fty = tTexBlt.top;
|
||||
vertices[2].ftx = tTexBlt.right; vertices[2].fty = tTexBlt.bottom;
|
||||
vertices[3].ftx = tTexBlt.left; vertices[3].fty = tTexBlt.bottom;
|
||||
vertices[0].tx = fTexBlt.left / iTexSizeX; vertices[0].ty = fTexBlt.top / iTexSizeY;
|
||||
vertices[1].tx = fTexBlt.right / iTexSizeX; vertices[1].ty = fTexBlt.top / iTexSizeY;
|
||||
vertices[2].tx = fTexBlt.right / iTexSizeX; vertices[2].ty = fTexBlt.bottom / iTexSizeY;
|
||||
vertices[3].tx = fTexBlt.left / iTexSizeX; vertices[3].ty = fTexBlt.bottom / iTexSizeY;
|
||||
DwTo4UB(0xffffffff, vertices[0].color);
|
||||
DwTo4UB(0xffffffff, vertices[1].color);
|
||||
DwTo4UB(0xffffffff, vertices[2].color);
|
||||
DwTo4UB(0xffffffff, vertices[3].color);
|
||||
|
||||
// duplicate vertices
|
||||
vertices[4] = vertices[0]; vertices[5] = vertices[2];
|
||||
|
||||
C4TexRef * pBaseTex = pTex;
|
||||
// is there a base-surface to be blitted first?
|
||||
if (fBaseSfc)
|
||||
{
|
||||
// then get this surface as same offset as from other surface
|
||||
// assuming this is only valid as long as there's no texture management,
|
||||
// organizing partially used textures together!
|
||||
pBaseTex = &sfcSource->pMainSfc->textures[iY * sfcSource->iTexX + iX];
|
||||
}
|
||||
|
||||
C4TexRef* pNormalTex = NULL;
|
||||
if (sfcSource->pNormalSfc)
|
||||
pNormalTex = &sfcSource->pNormalSfc->textures[iY * sfcSource->iTexX + iX];
|
||||
|
||||
// ClrByOwner is always fully opaque
|
||||
const DWORD dwOverlayClrMod = 0xff000000 | sfcSource->ClrByOwnerClr;
|
||||
PerformMultiTris(sfcTarget, vertices, 6, pTransform, pBaseTex, fBaseSfc ? pTex : NULL, pNormalTex, dwOverlayClrMod, NULL);
|
||||
}
|
||||
// then get this surface as same offset as from other surface
|
||||
// assuming this is only valid as long as there's no texture management,
|
||||
// organizing partially used textures together!
|
||||
pBaseTex = sfcSource->pMainSfc->texture.get();
|
||||
}
|
||||
|
||||
C4TexRef* pNormalTex = NULL;
|
||||
if (sfcSource->pNormalSfc)
|
||||
pNormalTex = sfcSource->pNormalSfc->texture.get();
|
||||
|
||||
// ClrByOwner is always fully opaque
|
||||
const DWORD dwOverlayClrMod = 0xff000000 | sfcSource->ClrByOwnerClr;
|
||||
PerformMultiTris(sfcTarget, vertices, 6, pTransform, pBaseTex, fBaseSfc ? pTex : NULL, pNormalTex, dwOverlayClrMod, NULL);
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
@ -578,8 +542,7 @@ bool C4Draw::BlitSurfaceTile(C4Surface * sfcSurface, C4Surface * sfcTarget, floa
|
|||
{
|
||||
// Only direct rendering from single, tileable, texture
|
||||
if (!sfcTarget->IsRenderTarget()) return false;
|
||||
if (!sfcSurface->IsSingleSurface()) return false;
|
||||
if ((sfcSurface->textures[0].iFlags & C4SF_Tileable) == 0) return false;
|
||||
if ((sfcSurface->texture->iFlags & C4SF_Tileable) == 0) return false;
|
||||
|
||||
// source surface dimensions
|
||||
const float sourceWdt = sfcSurface->Wdt;
|
||||
|
@ -603,7 +566,7 @@ bool C4Draw::BlitSurfaceTile(C4Surface * sfcSurface, C4Surface * sfcTarget, floa
|
|||
vertices[4] = vertices[0]; vertices[5] = vertices[2];
|
||||
|
||||
// Draw
|
||||
PerformMultiTris(sfcTarget, vertices, 6, NULL, &sfcSurface->textures[0], NULL, NULL, 0, shader_call);
|
||||
PerformMultiTris(sfcTarget, vertices, 6, NULL, sfcSurface->texture.get(), NULL, NULL, 0, shader_call);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,6 @@ void C4Surface::Default()
|
|||
Locked=0;
|
||||
Attached=false;
|
||||
fPrimary=false;
|
||||
textures.clear();
|
||||
pMainSfc=NULL;
|
||||
pNormalSfc=NULL;
|
||||
#ifndef USE_CONSOLE
|
||||
|
@ -94,7 +93,7 @@ void C4Surface::Default()
|
|||
#endif
|
||||
pWindow=NULL;
|
||||
ClrByOwnerClr=0;
|
||||
iTexSize=iTexX=iTexY=0;
|
||||
iTexSize=0;
|
||||
fIsBackground=false;
|
||||
#ifdef _DEBUG
|
||||
dbg_idx = 0;
|
||||
|
@ -120,13 +119,11 @@ void C4Surface::MoveFrom(C4Surface *psfcFrom)
|
|||
Locked=psfcFrom->Locked;
|
||||
Attached=psfcFrom->Attached;
|
||||
fPrimary=psfcFrom->fPrimary; // shouldn't be true!
|
||||
textures.swap(psfcFrom->textures);
|
||||
psfcFrom->textures.clear();
|
||||
texture = std::move(psfcFrom->texture);
|
||||
pMainSfc=psfcFrom->pMainSfc;
|
||||
pNormalSfc=psfcFrom->pNormalSfc;
|
||||
ClrByOwnerClr=psfcFrom->ClrByOwnerClr;
|
||||
iTexSize=psfcFrom->iTexSize;
|
||||
iTexX=psfcFrom->iTexX; iTexY=psfcFrom->iTexY;
|
||||
#ifndef USE_CONSOLE
|
||||
Format=psfcFrom->Format;
|
||||
#endif
|
||||
|
@ -147,7 +144,7 @@ void C4Surface::Clear()
|
|||
pCtx = 0;
|
||||
}
|
||||
#endif
|
||||
FreeTextures();
|
||||
texture.reset();
|
||||
#ifdef _DEBUG
|
||||
dbg_idx = 0;
|
||||
#endif
|
||||
|
@ -184,8 +181,9 @@ bool C4Surface::Create(int iWdt, int iHgt, int iFlags)
|
|||
#ifndef USE_CONSOLE
|
||||
Format=pGL->sfcFmt;
|
||||
#endif
|
||||
// create textures
|
||||
if (!CreateTextures(iFlags)) { Clear(); return false; }
|
||||
// create texture
|
||||
iTexSize = std::max(iWdt, iHgt);
|
||||
texture = std::make_unique<C4TexRef>(iWdt, iHgt, iFlags);
|
||||
// update clipping
|
||||
NoClip();
|
||||
// success
|
||||
|
@ -207,45 +205,6 @@ bool C4Surface::Copy(C4Surface &fromSfc)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4Surface::CreateTextures(int Flags)
|
||||
{
|
||||
// free previous
|
||||
FreeTextures();
|
||||
iTexSize=std::min(std::max(Wdt, Hgt), pDraw->MaxTexSize);
|
||||
// get the number of textures needed for this size
|
||||
iTexX=(Wdt-1)/iTexSize +1;
|
||||
iTexY=(Hgt-1)/iTexSize +1;
|
||||
// get mem for texture array
|
||||
textures.reserve(iTexX * iTexY);
|
||||
// create textures
|
||||
for (int y = 0; y < iTexY; ++y)
|
||||
{
|
||||
for(int x = 0; x < iTexX; ++x)
|
||||
{
|
||||
int sizeX = iTexSize;
|
||||
int sizeY = iTexSize;
|
||||
if(x == iTexX-1) sizeX = (Wdt - 1) % iTexSize + 1;
|
||||
if(y == iTexY-1) sizeY = (Hgt - 1) % iTexSize + 1;
|
||||
|
||||
textures.emplace_back(sizeX, sizeY, Flags);
|
||||
|
||||
if (fIsBackground) textures.rbegin()->FillBlack();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
static unsigned int dbg_counter = 0;
|
||||
dbg_idx = ++dbg_counter;
|
||||
#endif
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
||||
void C4Surface::FreeTextures()
|
||||
{
|
||||
textures.clear();
|
||||
}
|
||||
|
||||
#define RANGE 255
|
||||
#define HLSMAX RANGE
|
||||
#define RGBMAX 255
|
||||
|
@ -306,7 +265,7 @@ bool C4Surface::CreateColorByOwner(C4Surface *pBySurface)
|
|||
{
|
||||
// safety
|
||||
if (!pBySurface) return false;
|
||||
if (pBySurface->textures.empty()) return false;
|
||||
if (!pBySurface->texture) return false;
|
||||
// create in same size
|
||||
if (!Create(pBySurface->Wdt, pBySurface->Hgt)) return false;
|
||||
// copy scale
|
||||
|
@ -505,7 +464,7 @@ bool C4Surface::Lock()
|
|||
// lock main sfc
|
||||
if (pMainSfc) if (!pMainSfc->Lock()) return false;
|
||||
// lock texture
|
||||
if (!Locked && !fPrimary && textures.empty())
|
||||
if (!Locked && !fPrimary && !texture)
|
||||
return false;
|
||||
// count lock
|
||||
Locked++; return true;
|
||||
|
@ -531,47 +490,13 @@ bool C4Surface::Unlock()
|
|||
else
|
||||
{
|
||||
// non-primary unlock: unlock all texture surfaces (if locked)
|
||||
for (auto &texture : textures)
|
||||
texture.Unlock();
|
||||
if (texture)
|
||||
texture->Unlock();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4Surface::GetTexAtImpl(C4TexRef **ppTexRef, int &rX, int &rY)
|
||||
{
|
||||
// get pos
|
||||
int iX=rX/iTexSize;
|
||||
int iY=rY/iTexSize;
|
||||
// get texture by pos
|
||||
*ppTexRef = &textures[iY*iTexX + iX];
|
||||
// adjust pos
|
||||
rX-=iX*iTexSize;
|
||||
rY-=iY*iTexSize;
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4Surface::GetLockTexAt(C4TexRef **ppTexRef, int &rX, int &rY)
|
||||
{
|
||||
// texture present?
|
||||
if (!GetTexAt(ppTexRef, rX, rY)) return false;
|
||||
// Already partially locked
|
||||
if ((*ppTexRef)->texLock.pBits)
|
||||
{
|
||||
// But not for the requested pixel
|
||||
C4Rect & r = (*ppTexRef)->LockSize;
|
||||
if (r.x > rX || r.y > rY || (r.x + r.Wdt) < rX || (r.y + r.Hgt) < rY)
|
||||
// Unlock, then relock the whole thing
|
||||
(*ppTexRef)->Unlock();
|
||||
else return true;
|
||||
}
|
||||
// ensure it's locked
|
||||
if (!(*ppTexRef)->Lock()) return false;
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
||||
DWORD C4Surface::GetPixDw(int iX, int iY, bool fApplyModulation)
|
||||
{
|
||||
BYTE *pBuf = NULL; int iPitch = 0; // TODO: are those initialised to something sensible?
|
||||
|
@ -594,11 +519,10 @@ DWORD C4Surface::GetPixDw(int iX, int iY, bool fApplyModulation)
|
|||
else
|
||||
{
|
||||
// get+lock affected texture
|
||||
if (textures.empty()) return 0;
|
||||
C4TexRef *pTexRef;
|
||||
if (!GetLockTexAt(&pTexRef, iX, iY)) return 0;
|
||||
pBuf=(BYTE *) pTexRef->texLock.pBits;
|
||||
iPitch=pTexRef->texLock.Pitch;
|
||||
if (!texture) return 0;
|
||||
texture->Lock();
|
||||
pBuf=(BYTE *) texture->texLock.pBits;
|
||||
iPitch=texture->texLock.Pitch;
|
||||
}
|
||||
// get pix of surface
|
||||
DWORD dwPix;
|
||||
|
@ -663,43 +587,12 @@ bool C4Surface::SetPixDw(int iX, int iY, DWORD dwClr)
|
|||
// clip
|
||||
if ((iX<ClipX) || (iX>ClipX2) || (iY<ClipY) || (iY>ClipY2)) return true;
|
||||
// get+lock affected texture
|
||||
if (textures.empty()) return false;
|
||||
if (!texture) return false;
|
||||
texture->Lock();
|
||||
// if color is fully transparent, ensure it's black
|
||||
if (dwClr>>24 == 0x00) dwClr=0x00000000;
|
||||
C4TexRef *pTexRef;
|
||||
#ifndef USE_CONSOLE
|
||||
// openGL: use glTexSubImage2D
|
||||
// This optimization was moved to LockForUpdate, as it only slows down mass updates here
|
||||
// Keep this code in case there is a need for fast single pixel updates again
|
||||
if (0 && pGL->pCurrCtx)
|
||||
{
|
||||
if (!GetTexAt(&pTexRef, iX, iY))
|
||||
return false;
|
||||
// If the texture is not copied into system memory, modify it directly in the video memory
|
||||
if (!pTexRef->texLock.pBits)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, pTexRef->texName);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, iX, iY, 1, 1, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &dwClr);
|
||||
const bool fMipMap = (pTexRef->iFlags & C4SF_MipMap) != 0;
|
||||
if (fMipMap) glGenerateMipmap(GL_TEXTURE_2D);
|
||||
return true;
|
||||
}
|
||||
// Otherwise, make sure that the texlock covers the new pixel
|
||||
C4Rect & r = pTexRef->LockSize;
|
||||
if (r.x > iX || r.y > iY || (r.x + r.Wdt) < iX || (r.y + r.Hgt) < iY)
|
||||
{
|
||||
// Unlock, then relock the whole thing
|
||||
pTexRef->Unlock();
|
||||
if (!pTexRef->Lock()) return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!GetLockTexAt(&pTexRef, iX, iY)) return false;
|
||||
}
|
||||
// ...and set in actual surface
|
||||
pTexRef->SetPix(iX, iY, dwClr);
|
||||
texture->SetPix(iX, iY, dwClr);
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
@ -707,9 +600,9 @@ bool C4Surface::SetPixDw(int iX, int iY, DWORD dwClr)
|
|||
bool C4Surface::BltPix(int iX, int iY, C4Surface *sfcSource, int iSrcX, int iSrcY, bool fTransparency)
|
||||
{
|
||||
// 32bit-blit. lock target
|
||||
C4TexRef *pTexRef;
|
||||
if (!GetLockTexAt(&pTexRef, iX, iY)) return false;
|
||||
DWORD *pPix32=(DWORD *) (((BYTE *) pTexRef->texLock.pBits)+iY*pTexRef->texLock.Pitch+iX*4);
|
||||
if (!texture) return false;
|
||||
texture->Lock();
|
||||
DWORD *pPix32 = (DWORD *)(((BYTE *)texture->texLock.pBits) + iY*texture->texLock.Pitch + iX * 4);
|
||||
// get source pix as dword
|
||||
DWORD srcPix=sfcSource->GetPixDw(iSrcX, iSrcY, true);
|
||||
// merge
|
||||
|
@ -739,39 +632,15 @@ void C4Surface::ClearBoxDw(int iX, int iY, int iWdt, int iHgt)
|
|||
int iOver;
|
||||
iOver=Wdt-(iX+iWdt); if (iOver<0) iWdt+=iOver;
|
||||
iOver=Hgt-(iY+iHgt); if (iOver<0) iHgt+=iOver;
|
||||
// get textures involved
|
||||
int iTexX1=iX/iTexSize;
|
||||
int iTexY1=iY/iTexSize;
|
||||
int iTexX2=std::min((iX+iWdt-1)/iTexSize +1, iTexX);
|
||||
int iTexY2=std::min((iY+iHgt-1)/iTexSize +1, iTexY);
|
||||
// clear basesfc?
|
||||
bool fBaseSfc=false;
|
||||
if (pMainSfc) if (!pMainSfc->textures.empty()) fBaseSfc = true;
|
||||
// clear all these textures
|
||||
for (int y=iTexY1; y<iTexY2; ++y)
|
||||
C4Rect rtClear{ iX, iY, iWdt, iHgt };
|
||||
if (pMainSfc && pMainSfc->texture)
|
||||
{
|
||||
for (int x=iTexX1; x<iTexX2; ++x)
|
||||
{
|
||||
C4TexRef *pTex = &textures[y * iTexX + x];
|
||||
// get current offset in texture
|
||||
int iBlitX=iTexSize*x;
|
||||
int iBlitY=iTexSize*y;
|
||||
// get clearing bounds in texture
|
||||
C4Rect rtClear = C4Rect(0, 0, pTex->iSizeX, pTex->iSizeY);
|
||||
rtClear.Intersect(C4Rect(iX - iBlitX, iY - iBlitY, iWdt, iHgt));
|
||||
// is there a base-surface to be cleared first?
|
||||
if (fBaseSfc)
|
||||
{
|
||||
// then get this surface as same offset as from other surface
|
||||
// assuming this is only valid as long as there's no texture management,
|
||||
// organizing partially used textures together!
|
||||
C4TexRef *pBaseTex = &pMainSfc->textures[y * iTexX + x];
|
||||
pBaseTex->ClearRect(rtClear);
|
||||
}
|
||||
// clear this texture
|
||||
pTex->ClearRect(rtClear);
|
||||
}
|
||||
// assuming this is only valid as long as there's no texture management,
|
||||
// organizing partially used textures together!
|
||||
pMainSfc->texture->ClearRect(rtClear);
|
||||
}
|
||||
// clear this texture
|
||||
texture->ClearRect(rtClear);
|
||||
}
|
||||
|
||||
C4TexRef::C4TexRef(int iSizeX, int iSizeY, int iFlags)
|
||||
|
|
|
@ -67,7 +67,6 @@ public:
|
|||
int Scale; // scale of image; divide coordinates by this value to get the "original" image size
|
||||
int PrimarySurfaceLockPitch; BYTE *PrimarySurfaceLockBits; // lock data if primary surface is locked
|
||||
int iTexSize; // size of textures
|
||||
int iTexX, iTexY; // number of textures in x/y-direction
|
||||
int ClipX,ClipY,ClipX2,ClipY2;
|
||||
bool fIsBackground; // background surfaces fill unused pixels with black, rather than transparency - must be set prior to loading
|
||||
#ifdef _DEBUG
|
||||
|
@ -77,7 +76,7 @@ public:
|
|||
unsigned int Format; // used color format in textures
|
||||
CStdGLCtx * pCtx;
|
||||
#endif
|
||||
std::vector<C4TexRef> textures; // textures
|
||||
std::unique_ptr<C4TexRef> texture;
|
||||
C4Surface *pMainSfc; // main surface for simple ColorByOwner-surfaces
|
||||
C4Surface *pNormalSfc; // normal map; can be NULL
|
||||
DWORD ClrByOwnerClr; // current color to be used for ColorByOwner-blits
|
||||
|
@ -90,8 +89,6 @@ protected:
|
|||
bool Attached;
|
||||
bool fPrimary;
|
||||
|
||||
bool IsSingleSurface() const { return iTexX*iTexY==1; } // return whether surface is not split
|
||||
|
||||
public:
|
||||
void SetBackground() { fIsBackground = true; }
|
||||
int IsLocked() const { return Locked; }
|
||||
|
@ -99,18 +96,6 @@ public:
|
|||
void ClearBoxDw(int iX, int iY, int iWdt, int iHgt);
|
||||
bool Unlock();
|
||||
bool Lock();
|
||||
bool GetTexAt(C4TexRef **ppTexRef, int &rX, int &rY) // get texture and adjust x/y
|
||||
{
|
||||
if (textures.empty()) return false;
|
||||
if (rX < 0 || rY < 0 || rX >= Wdt || rY >= Hgt) return false;
|
||||
if (IsSingleSurface())
|
||||
{
|
||||
*ppTexRef = &textures[0];
|
||||
return true;
|
||||
}
|
||||
return GetTexAtImpl(ppTexRef, rX, rY);
|
||||
}
|
||||
bool GetLockTexAt(C4TexRef **ppTexRef, int &rX, int &rY); // get texture; ensure it's locked and adjust x/y
|
||||
DWORD GetPixDw(int iX, int iY, bool fApplyModulation); // get 32bit-px
|
||||
bool IsPixTransparent(int iX, int iY); // is pixel's alpha value <= 0x7f?
|
||||
bool SetPixDw(int iX, int iY, DWORD dwCol); // set pix in surface only
|
||||
|
@ -150,11 +135,7 @@ public:
|
|||
private:
|
||||
void MapBytes(BYTE *bpMap);
|
||||
bool ReadBytes(BYTE **lpbpData, void *bpTarget, int iSize);
|
||||
bool CreateTextures(int iFlags); // create ppTex-array
|
||||
void FreeTextures(); // free ppTex-array if existant
|
||||
|
||||
bool GetTexAtImpl(C4TexRef **ppTexRef, int &rX, int &rY);
|
||||
|
||||
friend class C4Draw;
|
||||
friend class C4Pattern;
|
||||
friend class CStdGL;
|
||||
|
@ -183,15 +164,15 @@ public:
|
|||
C4TexRef(int iSizeX, int iSizeY, int iFlags); // create texture with given size
|
||||
~C4TexRef(); // release texture
|
||||
bool Lock(); // lock texture
|
||||
// Lock a part of the rect, discarding the content
|
||||
// Note: Calling Lock afterwards without an Unlock first is undefined
|
||||
// Lock a part of the rect, discarding the content
|
||||
// Note: Calling Lock afterwards without an Unlock first is undefined
|
||||
bool LockForUpdate(C4Rect &rtUpdate);
|
||||
void Unlock(); // unlock texture
|
||||
bool ClearRect(C4Rect &rtClear); // clear rect in texture to transparent
|
||||
bool FillBlack(); // fill complete texture in black
|
||||
void SetPix(int iX, int iY, DWORD v)
|
||||
{
|
||||
*((DWORD *) (((BYTE *) texLock.pBits) + (iY - LockSize.y) * texLock.Pitch + (iX - LockSize.x) * 4)) = v;
|
||||
*((DWORD *)(((BYTE *)texLock.pBits) + (iY - LockSize.y) * texLock.Pitch + (iX - LockSize.x) * 4)) = v;
|
||||
}
|
||||
private:
|
||||
void CreateTexture();
|
||||
|
|
|
@ -166,52 +166,46 @@ bool C4Surface::ReadPNG(CStdStream &hGroup, int iFlags)
|
|||
if (!Create(png.iWdt, png.iHgt, iFlags)) return false;
|
||||
// lock for writing data
|
||||
if (!Lock()) return false;
|
||||
if (textures.empty())
|
||||
if (!texture)
|
||||
{
|
||||
Unlock();
|
||||
return false;
|
||||
}
|
||||
// write pixels
|
||||
for (int tY = 0; tY * iTexSize < Hgt; ++tY) for (int tX = 0; tX * iTexSize < Wdt; ++tX)
|
||||
{
|
||||
assert (tX>=0 && tY>=0 && tX<iTexX && tY<iTexY);
|
||||
// Get Texture and lock it
|
||||
C4TexRef *pTexRef = &textures[tY*iTexX + tX];
|
||||
if (!pTexRef->Lock()) continue;
|
||||
// At the edges, not the whole texture is used
|
||||
int maxY = std::min(iTexSize, Hgt - tY * iTexSize), maxX = std::min(iTexSize, Wdt - tX * iTexSize);
|
||||
for (int iY = 0; iY < maxY; ++iY)
|
||||
{
|
||||
// The global, not texture-relative position
|
||||
int rY = iY + tY * iTexSize;
|
||||
// Get Texture and lock it
|
||||
if (!texture->Lock()) return false;
|
||||
int maxX = std::min(Wdt, iTexSize);
|
||||
int maxY = std::min(Hgt, iTexSize);
|
||||
for (int iY = 0; iY < maxY; ++iY)
|
||||
{
|
||||
#ifndef __BIG_ENDIAN__
|
||||
if (png.iClrType == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
// Optimize the easy case of a png in the same format as the display
|
||||
// 32 bit
|
||||
DWORD *pPix=(DWORD *) (((char *) pTexRef->texLock.pBits) + iY * pTexRef->texLock.Pitch);
|
||||
memcpy (pPix, png.GetRow(rY) + tX * iTexSize, maxX * 4);
|
||||
int iX = maxX;
|
||||
while (iX--) { if (((BYTE *)pPix)[3] == 0x00) *pPix = 0x00000000; ++pPix; }
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Loop through every pixel and convert
|
||||
for (int iX = 0; iX < maxX; ++iX)
|
||||
{
|
||||
uint32_t dwCol = png.GetPix(iX + tX * iTexSize, rY);
|
||||
// if color is fully transparent, ensure it's black
|
||||
if (dwCol>>24 == 0x00) dwCol=0x00000000;
|
||||
// set pix in surface
|
||||
DWORD *pPix=(DWORD *) (((char *) pTexRef->texLock.pBits) + iY * pTexRef->texLock.Pitch + iX * 4);
|
||||
*pPix=dwCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
pTexRef->Unlock();
|
||||
if (png.iClrType == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
// Optimize the easy case of a png in the same format as the display
|
||||
// 32 bit
|
||||
DWORD *pPix=(DWORD *) (((char *) texture->texLock.pBits) + iY * texture->texLock.Pitch);
|
||||
memcpy (pPix, png.GetRow(iY), maxX * sizeof(*pPix));
|
||||
int iX = maxX;
|
||||
while (iX--) { if (((BYTE *)pPix)[3] == 0x00) *pPix = 0x00000000; ++pPix; }
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Loop through every pixel and convert
|
||||
for (int iX = 0; iX < maxX; ++iX)
|
||||
{
|
||||
uint32_t dwCol = png.GetPix(iX, iY);
|
||||
// if color is fully transparent, ensure it's black
|
||||
if (dwCol>>24 == 0x00) dwCol=0x00000000;
|
||||
// set pix in surface
|
||||
DWORD *pPix=(DWORD *) (((char *) texture->texLock.pBits) + iY * texture->texLock.Pitch + iX * 4);
|
||||
*pPix=dwCol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unlock
|
||||
texture->Unlock();
|
||||
Unlock();
|
||||
// return if successful
|
||||
return fSuccess;
|
||||
|
|
|
@ -254,26 +254,21 @@ bool C4LandscapeRenderGL::InitMaterialTexture(C4TextureMap *pTexs)
|
|||
*texdata++ = RGBA((iTex & 48), (iTex & 3) * 16, (i & 12) * 4, 255);
|
||||
continue;
|
||||
#else
|
||||
if(pSurface->iTexX != 1 || pSurface->iTexY != 1)
|
||||
Log(" gl: Halp! Material texture is fragmented!");
|
||||
else
|
||||
{
|
||||
// Size recheck. It's fine if this texture's size is a divisor
|
||||
// of the maximum texture size, because then we can just tile
|
||||
// the smaller texture.
|
||||
if(pSurface->Wdt != iTexWdt || pSurface->Hgt != iTexHgt)
|
||||
if (iTexWdt % pSurface->Wdt != 0 || iTexHgt % pSurface->Hgt != 0)
|
||||
LogF(" gl: texture %s size mismatch (%dx%d vs %dx%d)!", Texture.getData(), pSurface->Wdt, pSurface->Hgt, iTexWdt, iTexHgt);
|
||||
// Size recheck. It's fine if this texture's size is a divisor
|
||||
// of the maximum texture size, because then we can just tile
|
||||
// the smaller texture.
|
||||
if(pSurface->Wdt != iTexWdt || pSurface->Hgt != iTexHgt)
|
||||
if (iTexWdt % pSurface->Wdt != 0 || iTexHgt % pSurface->Hgt != 0)
|
||||
LogF(" gl: texture %s size mismatch (%dx%d vs %dx%d)!", Texture.getData(), pSurface->Wdt, pSurface->Hgt, iTexWdt, iTexHgt);
|
||||
|
||||
// Copy bytes
|
||||
DWORD *texdata = reinterpret_cast<DWORD *>(p);
|
||||
pSurface->Lock();
|
||||
for (int y = 0; y < iTexHgt; ++y)
|
||||
for (int x = 0; x < iTexWdt; ++x)
|
||||
*texdata++ = pSurface->GetPixDw(x % pSurface->Wdt, y % pSurface->Hgt, false);
|
||||
pSurface->Unlock();
|
||||
continue;
|
||||
}
|
||||
// Copy bytes
|
||||
DWORD *texdata = reinterpret_cast<DWORD *>(p);
|
||||
pSurface->Lock();
|
||||
for (int y = 0; y < iTexHgt; ++y)
|
||||
for (int x = 0; x < iTexWdt; ++x)
|
||||
*texdata++ = pSurface->GetPixDw(x % pSurface->Wdt, y % pSurface->Hgt, false);
|
||||
pSurface->Unlock();
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
// Seperator texture?
|
||||
|
@ -393,7 +388,7 @@ void C4LandscapeRenderGL::Update(C4Rect To, C4Landscape *pSource)
|
|||
C4TexRef *texture[C4LR_SurfaceCount];
|
||||
x = y = 0;
|
||||
for(int i = 0; i < C4LR_SurfaceCount; i++)
|
||||
Surfaces[i]->GetTexAt(&texture[i], x, y);
|
||||
texture[i] = Surfaces[i]->texture.get();
|
||||
|
||||
// Go through it from top to bottom
|
||||
for(y = 0; y < To.Hgt; y++)
|
||||
|
@ -976,7 +971,7 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion *Ligh
|
|||
for(int i = 0; i < C4LR_SurfaceCount; i++)
|
||||
{
|
||||
iLandscapeUnits[i] = ShaderCall.AllocTexUnit(-1) - GL_TEXTURE0;
|
||||
glBindTexture(GL_TEXTURE_2D, Surfaces[i]->textures[0].texName);
|
||||
glBindTexture(GL_TEXTURE_2D, Surfaces[i]->texture->texName);
|
||||
if (pGL->Zoom != 1.0)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
@ -1002,7 +997,7 @@ void C4LandscapeRenderGL::Draw(const C4TargetFacet &cgo, const C4FoWRegion *Ligh
|
|||
}
|
||||
if(ShaderCall.AllocTexUnit(C4LRU_ScalerTex))
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, fctScaler.Surface->textures[0].texName);
|
||||
glBindTexture(GL_TEXTURE_2D, fctScaler.Surface->texture->texName);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
|
|
@ -355,7 +355,7 @@ void C4PXSSystem::Draw(C4TargetFacet &cgo)
|
|||
for(std::map<int, std::vector<C4BltVertex> >::const_iterator iter = bltVtx.begin(); iter != bltVtx.end(); ++iter)
|
||||
{
|
||||
C4Material *pMat = &::MaterialMap.Map[iter->first];
|
||||
pDraw->PerformMultiTris(cgo.Surface, &iter->second[0], iter->second.size(), NULL, &pMat->PXSFace.Surface->textures[0], NULL, NULL, 0, NULL);
|
||||
pDraw->PerformMultiTris(cgo.Surface, &iter->second[0], iter->second.size(), NULL, pMat->PXSFace.Surface->texture.get(), NULL, NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -972,7 +972,7 @@ void C4ParticleChunk::Draw(C4TargetFacet cgo, C4Object *obj, C4ShaderCall& call,
|
|||
if (particleCount == 0) return;
|
||||
const int stride = sizeof(C4Particle::DrawingData::Vertex);
|
||||
assert(sourceDefinition && "No source definition assigned to particle chunk.");
|
||||
C4TexRef *textureRef = &sourceDefinition->Gfx.GetFace().textures[0];
|
||||
C4TexRef *textureRef = sourceDefinition->Gfx.GetFace().texture.get();
|
||||
assert(textureRef != 0 && "Particle definition had no texture assigned.");
|
||||
|
||||
// use a relative offset?
|
||||
|
|
|
@ -137,11 +137,11 @@ bool C4FoWRegion::BindFramebuf()
|
|||
glBindFramebuffer(GL_READ_FRAMEBUFFER, hFrameBufRead);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
pSurface->textures[0].texName, 0);
|
||||
if (!pBackSurface->textures.empty())
|
||||
pSurface->texture->texName, 0);
|
||||
if (pBackSurface->texture)
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
pBackSurface->textures[0].texName, 0);
|
||||
pBackSurface->texture->texName, 0);
|
||||
|
||||
// Check status, unbind if something was amiss
|
||||
GLenum status1 = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER),
|
||||
|
@ -171,10 +171,10 @@ int32_t C4FoWRegion::getSurfaceWidth() const
|
|||
#ifndef USE_CONSOLE
|
||||
GLuint C4FoWRegion::getSurfaceName() const
|
||||
{
|
||||
assert(!pSurface->textures.empty());
|
||||
if (pSurface->textures.empty())
|
||||
assert(pSurface->texture);
|
||||
if (!pSurface->texture)
|
||||
return 0;
|
||||
return pSurface->textures[0].texName;
|
||||
return pSurface->texture->texName;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -301,7 +301,7 @@ bool C4FoWRegion::Render(const C4TargetFacet *pOnScreen)
|
|||
C4ShaderCall Call(pShader);
|
||||
Call.Start();
|
||||
if (Call.AllocTexUnit(C4FoWFSU_Texture))
|
||||
glBindTexture(GL_TEXTURE_2D, pBackSurface->textures[0].texName);
|
||||
glBindTexture(GL_TEXTURE_2D, pBackSurface->texture->texName);
|
||||
Call.SetUniformMatrix4x4(C4FoWFSU_ProjectionMatrix, projectionMatrix);
|
||||
glBlendFunc(GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR);
|
||||
float normalBlend = 1.0f / 4.0f, // Normals change quickly
|
||||
|
|
|
@ -968,9 +968,8 @@ double StdMeshMaterialTextureUnit::Transformation::GetWaveXForm(double t) const
|
|||
}
|
||||
|
||||
StdMeshMaterialTextureUnit::Tex::Tex(C4Surface* Surface)
|
||||
: RefCount(1), Surf(Surface), Texture(Surface->textures[0])
|
||||
: RefCount(1), Surf(Surface), Texture(*Surface->texture)
|
||||
{
|
||||
assert(!Surface->textures.empty());
|
||||
}
|
||||
|
||||
StdMeshMaterialTextureUnit::Tex::~Tex()
|
||||
|
@ -1029,8 +1028,6 @@ void StdMeshMaterialTextureUnit::LoadTexture(StdMeshMaterialParserCtx& ctx, cons
|
|||
|
||||
if (surface->Wdt != surface->Hgt)
|
||||
ctx.Error(StdCopyStrBuf("Texture '") + texname + "' is not quadratic");
|
||||
if (surface->iTexX > 1 || surface->iTexY > 1)
|
||||
ctx.Error(StdCopyStrBuf("Texture '") + texname + "' is too large");
|
||||
|
||||
Textures.push_back(TexPtr(surface.release()));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue