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
Nicolas Hake 2016-02-08 16:14:59 +01:00
parent 7b04914fc4
commit 64a5388d4d
9 changed files with 129 additions and 330 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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();

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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?

View File

@ -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

View File

@ -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()));
}