Hardware rendering

- Use SDL_Texture and SDL_Render to for DibBitmap and Display operations
- SubBitmap class was created to handle suballocating dibs since the old method required direct pixel access
- Font buffer is no longer used. Back buffer is forced valid and drawn to the screen.
This commit is contained in:
Nathan Fulton 2017-07-06 18:09:30 -04:00
parent 8619337473
commit 24eba15f59
12 changed files with 330 additions and 390 deletions

View File

@ -2413,7 +2413,7 @@ bool MiniMapControl::Init(Form *pfrm, IniReader *pini, FindProp *pfind)
dword *pbtd = (dword *)(pmtseth + 1);
m_pbTileData = new dword[pmtseth->cTiles];
for (int i = 0; i < pmtseth->cTiles; i++, pbtd++) {
m_pbTileData[i] = BigDword(*pbtd);
m_pbTileData[i] = *pbtd;
}
// Calc powered radar flag
@ -2706,9 +2706,9 @@ void MiniMapControl::RedrawTRect(TRect *ptrc)
// Redraw this rect
dword *pbDst = m_pbm->GetBits() + (long)ptrc->top * m_cbRowBytes * m_nScale +
ptrc->left * m_nScale + (long)m_yOff * m_cbRowBytes + m_xOff;
int cbDstReturn = m_cbRowBytes - ptrc->Width() * m_nScale;
Rect rc;
rc.Set(m_xOff, m_yOff, ptrc->Width(), ptrc->Height());
DibBitmap *pbmDst = m_pbm->Suballoc(rc);
long offset = (long)ptrc->top * m_ctx + ptrc->left;
byte *pbFogMap = m_pbFogMap + offset;
word *pwTileMap = m_pwTileMap + offset;
@ -2716,138 +2716,62 @@ void MiniMapControl::RedrawTRect(TRect *ptrc)
int ctReturn = m_ctx - ptrc->Width();
#define HasWall(btt) ((btt) == kttWall)
for (TCoord ty = ptrc->top; ty < ptrc->bottom; ty++) {
for (TCoord tx = ptrc->left; tx < ptrc->right; tx++, pbFogMap++, pwTileMap++, pbTrMap++) {
// Fogged?
if (m_nScale == 1) {
for (TCoord ty = ptrc->top; ty < ptrc->bottom; ty++) {
for (TCoord tx = ptrc->left; tx < ptrc->right; tx++, pbFogMap++, pwTileMap++, pbTrMap++) {
// Fogged?
if (IsFogOpaque(*pbFogMap)) {
pbmDst->Fill(tx * m_nScale, ty * m_nScale, m_nScale, m_nScale, m_clrBlack);
continue;
}
if (IsFogOpaque(*pbFogMap)) {
*pbDst++ = m_clrBlack;
continue;
}
// Not fogged; remember to redraw the minimap to the screen next timer
// Not fogged; remember to redraw the minimap to the screen next timer
m_wfMm |= kfMmRedraw;
m_wfMm |= kfMmRedraw;
// Unit gob?
// Unit gob?
UnitGob *punt = ggobm.GetUnitGob(tx, ty);
if (punt != NULL) {
dword wf = punt->GetFlags();
if ((wf & (kfGobMobileUnit | kfGobActive)) != (kfGobMobileUnit)) {
Color clr;
if (wf & kfGobSelected) {
clr = m_clrWhite;
} else {
clr = m_aclrSide[punt->GetSide()];
}
UnitGob *punt = ggobm.GetUnitGob(tx, ty);
pbmDst->Fill(tx * m_nScale, ty * m_nScale, m_nScale, m_nScale, clr);
continue;
}
}
// don't show inactive munts
// Wall?
if (punt != NULL) {
dword wf = punt->GetFlags();
if ((wf & (kfGobMobileUnit | kfGobActive)) != (kfGobMobileUnit)) {
if (wf & kfGobSelected) {
*pbDst++ = m_clrWhite;
} else {
*pbDst++ = m_aclrSide[punt->GetSide()];
}
continue;
}
}
if (HasWall(*pbTrMap)) {
pbmDst->Fill(tx * m_nScale, ty * m_nScale, m_nScale, m_nScale, m_clrWall);
continue;
}
// Wall?
// Galaxite?
if (HasWall(*pbTrMap)) {
*pbDst++ = m_clrWall;
continue;
}
if (HasGalaxite(*pbFogMap)) {
pbmDst->Fill(tx * m_nScale, ty * m_nScale, m_nScale, m_nScale, m_clrGalaxite);
continue;
}
// Galaxite?
// Tile
if (HasGalaxite(*pbFogMap)) {
*pbDst++ = m_clrGalaxite;
continue;
}
// Tile
int nTile = (BigWord(*pwTileMap) & 0x7fc);
*pbDst++ = m_pbTileData[nTile >> 2];
continue;
}
pwTileMap += ctReturn;
pbFogMap += ctReturn;
pbTrMap += ctReturn;
pbDst += cbDstReturn;
}
} else if (m_nScale == 2) {
for (TCoord ty = ptrc->top; ty < ptrc->bottom; ty++) {
for (TCoord tx = ptrc->left; tx < ptrc->right; tx++, pbFogMap++, pwTileMap++, pbTrMap++) {
// Fogged?
if (IsFogOpaque(*pbFogMap)) {
*pbDst++ = m_clrBlack;
*pbDst++ = m_clrBlack;
*(pbDst + m_cbRowBytes - 2) = m_clrBlack;
*(pbDst + m_cbRowBytes - 1) = m_clrBlack;
continue;
}
// Not fogged; remember to redraw the minimap to the screen next timer
m_wfMm |= kfMmRedraw;
// Unit gob?
UnitGob *punt = ggobm.GetUnitGob(tx, ty);
if (punt != NULL) {
dword wf = punt->GetFlags();
if ((wf & (kfGobMobileUnit | kfGobActive)) != (kfGobMobileUnit)) {
dword clr;
if (wf & kfGobSelected) {
clr = m_clrWhite;
} else {
clr = m_aclrSide[punt->GetSide()];
}
*pbDst++ = clr;
*pbDst++ = clr;
*(pbDst + m_cbRowBytes - 2) = clr;
*(pbDst + m_cbRowBytes - 1) = clr;
continue;
}
}
// Wall?
if (HasWall(*pbTrMap)) {
*pbDst++ = m_clrWall;
*pbDst++ = m_clrWall;
*(pbDst + m_cbRowBytes - 2) = m_clrWall;
*(pbDst + m_cbRowBytes - 1) = m_clrWall;
continue;
}
// Galaxite?
if (HasGalaxite(*pbFogMap)) {
*pbDst++ = m_clrGalaxite;
*pbDst++ = m_clrGalaxite;
*(pbDst + m_cbRowBytes - 2) = m_clrGalaxite;
*(pbDst + m_cbRowBytes - 1) = m_clrGalaxite;
continue;
}
// Tile
int nTile = (BigWord(*pwTileMap) & 0x7fc);
dword pbSrc = m_pbTileData[nTile];
*pbDst++ = pbSrc;
*pbDst++ = pbSrc;
*(pbDst + m_cbRowBytes - 2) = pbSrc;
*(pbDst + m_cbRowBytes - 1) = pbSrc;
continue;
}
pwTileMap += ctReturn;
pbFogMap += ctReturn;
pbTrMap += ctReturn;
pbDst += cbDstReturn + m_cbRowBytes;
}
}
int nTile = (BigWord(*pwTileMap) & 0x7fc);
dword pbSrc = m_pbTileData[m_nScale == 1 ? nTile >> 2 : nTile];
pbmDst->Fill(tx * m_nScale, ty * m_nScale, m_nScale, m_nScale, pbSrc);
continue;
}
pwTileMap += ctReturn;
pbFogMap += ctReturn;
pbTrMap += ctReturn;
}
}
} // namespace wi

View File

@ -3,12 +3,7 @@
#if defined(SDL)
#include <SDL.h>
#include <SDL_image.h>
#define SURFACE_FLAGS 0
#define SURFACE_DEPTH 32
#define SURFACE_PITCH(x) x*4 // row length in bytes: x*sizeof(byte)*sizeof(dword)
#define SHADOW_ALPHA_MOD 100
#endif // defined(SDL)
#endif
namespace wi {
@ -16,21 +11,23 @@ namespace wi {
DibBitmap::DibBitmap()
{
m_surface = NULL;
m_texture = NULL;
m_ppfmt = NULL;
m_wf = 0;
m_pszFn = NULL;
m_renderer = NULL;
m_cx = 0;
m_cy = 0;
}
DibBitmap::~DibBitmap()
{
SDL_DestroyRenderer(m_renderer);
SDL_FreeSurface(m_surface);
if (m_wf & kfDibFreeMem)
free(m_surface->pixels);
m_surface = NULL;
if (m_pszFn != NULL)
delete[] m_pszFn;
if (m_texture) {
SDL_DestroyTexture(m_texture);
m_texture = NULL;
}
if (m_ppfmt && m_ppfmt->next) {
SDL_FreeFormat(m_ppfmt);
m_ppfmt = NULL;
}
}
DibBitmap *LoadDibBitmap(char *pszFn)
@ -46,26 +43,13 @@ DibBitmap *LoadDibBitmap(char *pszFn)
return pbm;
}
DibBitmap *CreateDibBitmap(dword *pb, int cx, int cy, bool alpha)
DibBitmap *CreateDibBitmap(dword *pb, int cx, int cy)
{
DibBitmap *pbm = new DibBitmap();
Assert(pbm != NULL, "out of memory!");
if (pbm == NULL)
return NULL;
if (!pbm->Init(pb, cx, cy, alpha, false)) {
delete pbm;
return NULL;
}
return pbm;
}
DibBitmap *CreateBigDibBitmap(dword *pb, int cx, int cy, bool alpha)
{
DibBitmap *pbm = new DibBitmap();
Assert(pbm != NULL, "out of memory!");
if (pbm == NULL)
return NULL;
if (!pbm->Init(pb, cx, cy, alpha, true)) {
if (!pbm->Init(pb, cx, cy)) {
delete pbm;
return NULL;
}
@ -74,94 +58,107 @@ DibBitmap *CreateBigDibBitmap(dword *pb, int cx, int cy, bool alpha)
bool DibBitmap::Init(char *pszFn)
{
// Read the file
// Open the file
File *pfil = gpakr.fopen(pszFn, "rb");
if (pfil == NULL)
if (!pfil)
return false;
byte *pb = new byte[pfil->cbTotal];
if (gpakr.fread(pb, pfil->cbTotal, 1, pfil) != 1)
if (!pb)
return false;
// Feed the bytes into an SDL surface
// Read the file
SDL_RWops *prwio = SDL_RWFromMem(pb, pfil->cbTotal);
m_surface = IMG_Load_RW(prwio, 0);
// Cleanup
SDL_FreeRW(prwio);
delete[] pb;
if (gpakr.fread(pb, pfil->cbTotal, 1, pfil) != 1) {
gpakr.fclose(pfil);
return false;
}
gpakr.fclose(pfil);
// Keep the name around
// Copy bytes into an SDL texture
m_pszFn = AllocString(pszFn);
SDL_RWops *prwio = SDL_RWFromMem(pb, pfil->cbTotal);
m_texture = IMG_LoadTexture_RW(gpdisp->Renderer(), prwio, 1);
if (!m_texture)
return false;
return m_surface != NULL;
// Bytes have been copied into the texture and can be deleted
delete[] pb;
// Query the texture and save prevalent information
dword fmt;
SDL_QueryTexture(m_texture, &fmt, NULL, &m_cx, &m_cy);
m_ppfmt = SDL_AllocFormat(fmt);
return true;
}
bool DibBitmap::Init(dword *pb, int cx, int cy, bool alpha, bool bigendian)
bool DibBitmap::Init(dword *pb, int cx, int cy)
{
Uint32 rmask, gmask, bmask, amask;
if (bigendian) {
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
} else {
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
}
if (!alpha)
amask = 0;
// Assume RGBA mask
Uint32 rmask = 0, gmask = 0, bmask = 0, amask = 0;
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
// Create the texture
SDL_Renderer *renderer = gpdisp->Renderer();
if (pb == NULL) {
m_surface = SDL_CreateRGBSurface(SURFACE_FLAGS, cx, cy, SURFACE_DEPTH,
rmask, gmask, bmask, amask);
m_texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, cx, cy);
} else {
m_surface = SDL_CreateRGBSurfaceFrom(pb, cx, cy, SURFACE_DEPTH, SURFACE_PITCH(cx),
rmask, gmask, bmask, amask);
// When using SDL_CreateRGBSurfaceFrom(), SDL does not manage the pixel data
// so it will need to be freed manually
// If creating with pb, copy bytes into SDL_Surface then create SDL_Texture from surface
m_wf |= kfDibFreeMem;
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(
pb, cx, cy, 32, cx * sizeof(dword), rmask, gmask, bmask, amask);
m_texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
surface = NULL;
}
#if 0
// This can be used to set the alpha color (only works if amask is 0)
// SDL_SetColorKey(m_surface, 1, SDL_MapRGB(m_surface->format, 255, 0, 255));
#endif
if (!m_texture)
return false;
return m_surface != NULL;
// Query the texture and save prevalent information
dword fmt;
SDL_QueryTexture(m_texture, &fmt, NULL, &m_cx, &m_cy);
m_ppfmt = SDL_AllocFormat(fmt);
if (!m_ppfmt)
return false;
return true;
}
SDL_Rect rcSrc;
SDL_Rect rcDst;
void DibBitmap::Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst)
{
if (prcSrc == NULL) {
SDL_Rect rcDst = { xDst, yDst, pbmSrc->GetSurface()->w, pbmSrc->GetSurface()->h };
SDL_BlitSurface(pbmSrc->GetSurface(), NULL, m_surface, &rcDst);
} else {
SDL_Rect rcSrc = { prcSrc->left, prcSrc->top, prcSrc->Width(), prcSrc->Height() };
SDL_Rect rcDst = { xDst, yDst, prcSrc->Width(), prcSrc->Height() };
SDL_BlitSurface(pbmSrc->GetSurface(), &rcSrc, m_surface, &rcDst);
SDL_Renderer *renderer = gpdisp->Renderer();
if (SDL_SetRenderTarget(renderer, m_texture) != 0) {
LOG() << "SDL Error: " << SDL_GetError();
return;
}
}
void DibBitmap::BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc)
{
if (prcSrc == NULL) {
SDL_Rect rcDst = { xDst, yDst, m_surface->w, m_surface->h };
SDL_BlitSurface(m_surface, NULL, pbmDst->GetSurface(), &rcDst);
} else {
SDL_Rect rcSrc = { prcSrc->left, prcSrc->top, prcSrc->Width(), prcSrc->Height() };
SDL_Rect rcDst = { xDst, yDst, prcSrc->Width(), prcSrc->Height() };
SDL_BlitSurface(m_surface, &rcSrc, pbmDst->GetSurface(), &rcDst);
if (prcSrc != NULL) {
rcSrc.x = prcSrc->left;
rcSrc.y = prcSrc->top;
rcSrc.w = prcSrc->Width();
rcSrc.h = prcSrc->Height();
}
rcDst.x = xDst;
rcDst.y = yDst;
rcDst.w = prcSrc ? prcSrc->Width() : pbmSrc->Width();
rcDst.h = prcSrc ? prcSrc->Height() : pbmSrc->Height();
SDL_RenderCopy(renderer, pbmSrc->Texture(), prcSrc != NULL ? &rcSrc : NULL, &rcDst);
}
void DibBitmap::BltTiles(DibBitmap *pbmSrc, UpdateMap *pupd, int yTopDst)
@ -176,24 +173,34 @@ void DibBitmap::BltTiles(DibBitmap *pbmSrc, UpdateMap *pupd, int yTopDst)
void DibBitmap::GetSize(Size *psiz)
{
psiz->cx = m_surface->w;
psiz->cy = m_surface->h;
}
dword *DibBitmap::GetBits()
{
return (dword *)m_surface->pixels;
}
int DibBitmap::GetPitch()
{
return m_surface->pitch;
psiz->cx = m_cx;
psiz->cy = m_cy;
}
void DibBitmap::Fill(int x, int y, int cx, int cy, Color clr)
{
SDL_Rect rc = { x, y, cx, cy };
SDL_FillRect(m_surface, &rc, SDL_MapRGB(m_surface->format, clr.r, clr.g, clr.b));
SDL_Renderer *renderer = gpdisp->Renderer();
SDL_SetRenderTarget(renderer, m_texture);
SDL_Rect rc;
rc.x = x;
rc.y = y;
rc.w = cx;
rc.h = cy;
SDL_SetRenderDrawColor(renderer, clr.r, clr.g, clr.b, 255);
SDL_RenderFillRect(renderer, &rc);
}
void DibBitmap::Fill(int x, int y, int cx, int cy, dword clr)
{
SDL_PixelFormat *pfmt = SDL_AllocFormat(SDL_PIXELFORMAT_RGBA8888);
if (pfmt) {
byte r, g, b;
SDL_GetRGB(clr, pfmt, &r, &g, &b);
Color c = { r, g, b };
Fill(x, y, cx, cy, c);
}
}
void DibBitmap::FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
@ -201,20 +208,20 @@ void DibBitmap::FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
{
Rect rcclp;
// For every y point that is disivible by m_surface->h
// For every y point that is disivible by cx
for (int y = 0; y < cyDst; y++) {
if (!(y % m_surface->h)) {
if (!(y % m_cy)) {
// For every x point that is disivible by m_surface->w
// For every x point that is disivible by cy
for (int x = 0; x < cxDst; x++) {
if (!(x % m_surface->w)) {
if (!(x % m_cx)) {
// Blt and clip appropriately
rcclp.Set(xDst + x, yDst + y, cxDst, cyDst);
pbmDst->Blt(this, NULL, xDst + x, yDst + y);
pbmDst->Blt(this, &rcclp, xDst + x, yDst + y);
}
}
}
@ -223,7 +230,7 @@ void DibBitmap::FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
void DibBitmap::Clear(Color clr)
{
Fill(0, 0, m_surface->w, m_surface->h, clr);
Fill(0, 0, m_cx, m_cy, clr);
}
void DibBitmap::Shadow(int x, int y, int cx, int cy)
@ -231,20 +238,21 @@ void DibBitmap::Shadow(int x, int y, int cx, int cy)
DibBitmap *pbm = CreateDibBitmap(NULL, cx, cy);
pbm->Clear(GetColor(kiclrBlack));
SDL_SetSurfaceBlendMode(pbm->GetSurface(), SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(pbm->GetSurface(), SHADOW_ALPHA_MOD);
SDL_SetTextureBlendMode(pbm->Texture(), SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(pbm->Texture(), 100);
pbm->BltTo(this, x, y);
Blt(pbm, NULL, x, y);
SDL_SetTextureBlendMode(pbm->Texture(), SDL_BLENDMODE_NONE);
}
void DibBitmap::DrawLine(short x1, short y1, short x2, short y2, Color clr)
{
if (m_renderer == NULL)
if ((m_renderer = SDL_CreateSoftwareRenderer(m_surface)) == NULL)
return;
SDL_Renderer *renderer = gpdisp->Renderer();
SDL_SetRenderTarget(renderer, m_texture);
SDL_SetRenderDrawColor(m_renderer, clr.r, clr.g, clr.b, 255);
SDL_RenderDrawLine(m_renderer, x1, y1, x2, y2);
SDL_SetRenderDrawColor(renderer, clr.r, clr.g, clr.b, 255);
SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
}
void DibBitmap::Scroll(Rect *prcSrc, int xDst, int yDst)
@ -255,26 +263,54 @@ void DibBitmap::Scroll(Rect *prcSrc, int xDst, int yDst)
Blt(this, prcSrc, xDst, yDst);
}
DibBitmap *DibBitmap::Suballoc(int yTop, int cy)
SubBitmap *DibBitmap::Suballoc(int yTop, int cy)
{
Assert(yTop < m_surface->h && yTop + cy <= m_surface->h);
dword *pb = (dword *)m_surface->pixels + (long)m_surface->w * yTop;
DibBitmap *pbm = CreateDibBitmap(pb, m_surface->w, cy);
Assert(yTop < m_cy && yTop + cy <= m_cy);
Rect rc;
rc.Set(0, yTop, m_cx, yTop + cy);
return Suballoc(rc);
}
// We don't want it to free memory since that will be taken care
// of by 'this'
if (pbm != NULL)
pbm->SetFlags(pbm->GetFlags() & ~kfDibFreeMem);
SubBitmap *DibBitmap::Suballoc(Rect rc)
{
Assert(rc.right <= m_cx && rc.top <= m_cy);
SubBitmap *pbm = new SubBitmap(rc);
if (!pbm) {
delete pbm;
return NULL;
}
pbm->m_texture = m_texture;
pbm->m_ppfmt = m_ppfmt;
pbm->m_cx = rc.Width();
pbm->m_cy = rc.Height();
return pbm;
}
dword DibBitmap::MapRGB(byte r, byte g, byte b)
{
return SDL_MapRGB(m_surface->format, r, g, b);
}
#endif // defined(SDL)
// SubBitmap
void SubBitmap::Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst)
{
DibBitmap::Blt(pbmSrc, prcSrc, xDst + m_rc.left, yDst + m_rc.top);
}
void SubBitmap::Fill(int x, int y, int cx, int cy, Color clr)
{
DibBitmap::Fill(x + m_rc.left, y + m_rc.top, cx, cy, clr);
}
void SubBitmap::Clear(Color clr)
{
DibBitmap::Fill(m_rc.left, m_rc.top, m_rc.Width(), m_rc.Height(), clr);
}
void SubBitmap::DrawLine(short x1, short y1, short x2, short y2, Color clr)
{
DibBitmap::DrawLine(x1 + m_rc.left, y1 + m_rc.top, x2 + m_rc.left, y2 + m_rc.top, clr);
}
} // namespace wi

View File

@ -937,10 +937,6 @@ void MultiFormMgr::DrawFrame(bool fForceBackBufferValid, bool fPaint)
bool fAnyScroll = fPaint ? Paint(fForceBackBufferValid) : false;
// Copy to front buffer
BltTo(gpdisp->GetFrontDib(), 0, fAnyScroll);
// Notify the display we've completed a frame. Pass in update maps
// so selective invalidation can occur

View File

@ -2165,7 +2165,7 @@ bool Game::FilterEvent(Event *pevt)
// Draw
gpmfrmm->DrawFrame(false);
gpmfrmm->DrawFrame(true);
return true;
case gameSuspendEvent:

View File

@ -1059,32 +1059,30 @@ struct TBitmapHeader // tbh
#define kfDibBackWindow 0x0002
#define kfDibWantScrolls 0x0004
class SubBitmap;
class DibBitmap
{
public:
DibBitmap() secDibBitmap;
~DibBitmap() secDibBitmap;
virtual ~DibBitmap() secDibBitmap;
bool Init(char *pszFn) secDibBitmap;
bool Init(dword *pb, int cx, int cy, bool alpha, bool bigendian) secDibBitmap;
virtual bool Init(char *pszFn) secDibBitmap;
virtual bool Init(dword *pb, int cx, int cy) secDibBitmap;
void Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst) secDibBitmap;
void BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Rect *prcSrc = NULL) secDibBitmap;
void BltTiles(DibBitmap *pbmSrc, UpdateMap *pupd, int yTopDst) secDibBitmap;
void GetSize(Size *psiz) secDibBitmap;
dword *GetBits() secDibBitmap;
int GetPitch() secDibBitmap;
void Fill(int x, int y, int cx, int cy, Color clr) secDibBitmap;
void FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
virtual void Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst) secDibBitmap;
virtual void BltTiles(DibBitmap *pbmSrc, UpdateMap *pupd, int yTopDst) secDibBitmap;
virtual void GetSize(Size *psiz) secDibBitmap;
virtual void Fill(int x, int y, int cx, int cy, Color clr) secDibBitmap;
virtual void Fill(int x, int y, int cx, int cy, dword clr) secDibBitmap;
virtual void FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
int cxDst, int cyDst, int xOrigin = 0, int yOrigin = 0) secDibBitmap;
void Clear(Color clr) secDibBitmap;
void Shadow(int x, int y, int cx, int cy) secDibBitmap;
void DrawLine(short x1, short y1, short x2, short y2, Color clr) secDibBitmap;
void Scroll(Rect *prcSrc, int xDst, int yDst) secDibBitmap;
virtual void Clear(Color clr) secDibBitmap;
virtual void Shadow(int x, int y, int cx, int cy) secDibBitmap;
virtual void DrawLine(short x1, short y1, short x2, short y2, Color clr) secDibBitmap;
virtual void Scroll(Rect *prcSrc, int xDst, int yDst) secDibBitmap;
DibBitmap *Suballoc(int yTop, int cy) secDibBitmap;
virtual SubBitmap *Suballoc(int yTop, int cy) secDibBitmap;
virtual SubBitmap *Suballoc(Rect rc) secDibBitmap;
word GetFlags() {
return m_wf;
@ -1092,31 +1090,40 @@ public:
void SetFlags(word wf) {
m_wf = wf;
}
int GetBaseline() {
return 0;
}
char *GetFileName() {
return m_pszFn;
}
#if defined(SDL)
int GetWidth() { return m_surface->w; }
int GetHeight() { return m_surface->h; }
dword MapRGB(byte r, byte g, byte b);
SDL_Surface *GetSurface() { return m_surface; }
SDL_Texture *Texture() { return m_texture; }
int Width() { return m_cx; }
int Height() { return m_cy; }
#endif
char *m_pszFn;
private:
#if defined(SDL)
SDL_Surface *m_surface;
SDL_Renderer *m_renderer;
SDL_Texture *m_texture;
SDL_PixelFormat *m_ppfmt;
#endif
word m_wf;
int m_cx;
int m_cy;
friend class TBitmap;
};
DibBitmap *LoadDibBitmap(char *pszFn) secDibBitmap;
DibBitmap *CreateDibBitmap(dword *pb, int cx, int cy, bool alpha = false) secDibBitmap;
DibBitmap *CreateBigDibBitmap(dword *pb, int cx, int cy, bool alpha = false) secDibBitmap;
DibBitmap *CreateDibBitmap(dword *pb, int cx, int cy) secDibBitmap;
class SubBitmap : public DibBitmap
{
public:
SubBitmap(Rect rc) : m_rc(rc) { }
~SubBitmap() {}
void Blt(DibBitmap *pbmSrc, Rect *prcSrc, int xDst, int yDst);
void Fill(int x, int y, int cx, int cy, Color clr);
void Clear(Color clr);
void DrawLine(short x1, short y1, short x2, short y2, Color clr);
private:
Rect m_rc;
};
// Texture bitmap
// Stores information about a bitmap in a texture atlas
@ -1150,7 +1157,7 @@ public:
int Height() { return m_cyOrig; }
private:
DibBitmap *SetLum(word lum, Side side = 1) secTBitmap;
DibBitmap *Flash() secTBitmap;
int m_x, m_y, m_cx, m_cy;
int m_cxOrig, m_cyOrig;

View File

@ -32,10 +32,8 @@ Display::Display()
m_window = NULL;
m_renderer = NULL;
m_texture = NULL;
m_display = NULL;
m_pbm = NULL;
m_density = 0;
m_fShouldRender = false;
}
@ -44,15 +42,13 @@ Display::~Display()
delete m_pbmClip;
m_pbmClip = NULL;
delete m_display;
m_display = NULL;
delete m_pbm;
m_pbm = NULL;
SDL_DestroyWindow(m_window);
m_window = NULL;
SDL_DestroyRenderer(m_renderer);
m_renderer = NULL;
SDL_DestroyTexture(m_texture);
m_texture = NULL;
}
bool Display::Init()
@ -68,6 +64,7 @@ bool Display::Init()
// Absolutely do not mess with SDL_FULLSCREEN if there is any chance the app
// will crash or stop at a breakpoint. If it does you will be lost in full
// screen mode! (ssh from another machine and kill the Xcode process)
videoflags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_SHOWN;
#if defined(__IPHONEOS__) || defined(__ANDROID__)
videoflags = videoflags | SDL_WINDOW_BORDERLESS;
@ -75,13 +72,14 @@ bool Display::Init()
#endif
// Get surface properties
SurfaceProperties props;
HostHelpers::GetSurfaceProperties(&props);
m_cx = props.cxWidth;
m_cy = props.cyHeight;
m_density = props.density;
// Set appropriate GL attributes
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
@ -94,19 +92,11 @@ bool Display::Init()
return false;
}
// Create renderer
m_renderer = SDL_CreateRenderer(m_window, 0, SDL_RENDERER_TARGETTEXTURE);
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_ACCELERATED);
this->SetShouldRender(true);
// Keep the screen size around
s_siz.cx = m_cx;
s_siz.cy = m_cy;
// Create texture and display
m_display = CreateDibBitmap(NULL, m_cx, m_cy);
m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, m_cx, m_cy);
// Keep the screen size around
s_siz.cx = m_cx;
s_siz.cy = m_cy;
@ -193,12 +183,12 @@ bool Display::SetMode(int imode)
ModeInfo *pmode = &m_amodeInfo[imode];
DibBitmap *pbmFront = CreateDibBitmap(NULL, m_cx, m_cy);
if (pbmFront == NULL) {
DibBitmap *pbm = CreateDibBitmap(NULL, m_cx, m_cy);
if (pbm == NULL) {
return NULL;
}
delete m_display;
m_display = pbmFront;
delete m_pbm;
m_pbm = pbm;
m_imode = imode;
return true;
@ -214,12 +204,12 @@ void Display::DrawFrameInclusive(Rect *prc)
DibBitmap *Display::GetBackDib()
{
return m_display;
return m_pbm;
}
DibBitmap *Display::GetFrontDib()
{
return m_display;
return m_pbm;
}
DibBitmap *Display::GetClippingDib()
@ -243,25 +233,18 @@ void Display::FrameStart()
void Display::FrameComplete(int cfrmm, UpdateMap **apupd, Rect *arc,
bool fScrolled)
{
RenderGameSurface();
}
void Display::RenderGameSurface() {
if (!m_fShouldRender)
return;
// Update the texture
SDL_UpdateTexture(m_texture, NULL, m_display->GetBits(), m_display->GetPitch());
// Draw any sprites onto the texture
SDL_SetRenderTarget(m_renderer, m_texture);
SDL_SetRenderTarget(m_renderer, m_pbm->Texture());
s_psprm->DrawSprites(m_renderer, s_siz);
SDL_SetRenderTarget(m_renderer, NULL);
// Present the renderer to the screen
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_SetRenderTarget(m_renderer, NULL);
SDL_RenderCopy(m_renderer, m_pbm->Texture(), NULL, NULL);
SDL_RenderPresent(m_renderer);
}
@ -286,12 +269,12 @@ void Display::SetFormMgrs(FormMgr *pfrmmSimUI, FormMgr *pfrmmInput)
#endif
}
float Display::Density() {
return m_density;
}
void Display::SetShouldRender(bool fsr) {
m_fShouldRender = fsr;
}
SDL_Renderer *Display::Renderer() {
return m_renderer;
}
} // namespace wi

View File

@ -425,9 +425,8 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt)
// SDL may have released its graphics context if the app was previously
// backgrounded. This leaves the screen black when the user returns.
// Hack: Draw dib and render
// Hack: Redraw
gpmfrmm->DrawFrame(true);
gpdisp->RenderGameSurface();
break;
case SDL_APP_DIDENTERBACKGROUND:
@ -465,7 +464,6 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt)
case SDL_WINDOWEVENT:
gpmfrmm->DrawFrame(true);
gpdisp->RenderGameSurface();
break;
default:

View File

@ -121,25 +121,19 @@ public:
void ResetScrollOffset();
SpriteManager *GetSpriteManager();
void SetFormMgrs(FormMgr *pfrmmSim, FormMgr *pfrmmInput);
void RenderGameSurface();
float Density();
void SetShouldRender(bool fsr);
SDL_Renderer *Renderer();
private:
int m_imode;
ModeInfo m_amodeInfo[kcmodesMax];
int m_cmodes;
int m_cx;
int m_cy;
DibBitmap *m_pbm;
DibBitmap *m_pbmClip;
SDL_Window *m_window;
SDL_Renderer *m_renderer;
SDL_Texture *m_texture;
DibBitmap *m_display;
float m_density;
bool m_fShouldRender;
};

View File

@ -11,7 +11,7 @@ SdlAnimSprite::SdlAnimSprite(SpriteManager *psprm) {
cy_ = 0;
xOrigin_ = 0;
yOrigin_ = 0;
surface_ = NULL;
pbm_ = NULL;
nScale_ = 1.0f;
x_ = 0;
y_ = 0;
@ -23,7 +23,9 @@ SdlAnimSprite::~SdlAnimSprite() {
psprm_->Remove(this);
crit_.Enter();
surface_ = NULL;
if (pbm_)
delete pbm_;
pbm_ = NULL;
crit_.Leave();
}
@ -74,10 +76,11 @@ bool SdlAnimSprite::CreateSurface(UnitGob *pgob) {
yOrigin_ = rcAni.top;
// Create the surface
surface_ = CreateDibBitmap(NULL, cx_, cy_, true);
if (surface_ == NULL)
pbm_ = CreateDibBitmap(NULL, cx_, cy_);
if (pbm_ == NULL)
return false;
pgob->DrawAnimation(surface_, -xOrigin_, -yOrigin_);
SDL_SetTextureBlendMode(pbm_->Texture(), SDL_BLENDMODE_BLEND);
pgob->DrawAnimation(pbm_, -xOrigin_, -yOrigin_);
return true;
}
@ -104,15 +107,8 @@ void SdlAnimSprite::Draw(void *pv, Size *psiz) {
rcBounds.Height()
};
if (surface_ != NULL) {
// Create a texture from the surface
SDL_Texture *texture = SDL_CreateTextureFromSurface((SDL_Renderer *)pv, surface_->GetSurface());
// Render the texture
SDL_RenderCopy((SDL_Renderer *)pv, texture, NULL, &rc);
// Destroy
SDL_DestroyTexture(texture);
if (pbm_ != NULL) {
SDL_RenderCopy((SDL_Renderer *)pv, pbm_->Texture(), NULL, &rc);
}
crit_.Leave();

View File

@ -44,7 +44,7 @@ private:
dword hash_;
int cx_, cy_;
int xOrigin_, yOrigin_;
DibBitmap *surface_;
DibBitmap *pbm_;
SpriteManager *psprm_;
float nScaleStart_, nScaleEnd_;
long msAnimateStart_;

View File

@ -55,7 +55,9 @@ void TBitmap::BltTo(class DibBitmap *pbmDst, int xDst, int yDst, Side side, Rect
// Flash unit?
if (side == (Side)-1) {
SetLum(32768)->BltTo(pbmDst, xDst, yDst, prcSrc);
DibBitmap *pbm = Flash();
pbmDst->Blt(pbm, prcSrc, xDst, yDst);
delete pbm;
return;
}
@ -118,40 +120,44 @@ void TBitmap::FillTo(class DibBitmap *pbmDst, int xDst, int yDst,
}
}
DibBitmap *TBitmap::SetLum(word lum, Side side) {
DibBitmap *TBitmap::Flash() {
// Returns a DibBitmap of this TBitmap where all
// the pixels have been changed to (255, 255, 255)
// while maintaining their original alpha value
// Copy pixels into an DibBitmap
#if defined(SDL)
DibBitmap *pbm = CreateDibBitmap(NULL, m_cxOrig, m_cyOrig, true);
BltTo(pbm, 0, 0, side);
Uint32 *i0p = (Uint32 *)pbm->GetBits();
// Blt from the texture atlas into a dib
DibBitmap *pbm = CreateDibBitmap(NULL, m_cxOrig, m_cyOrig);
BltTo(pbm, 0, 0, ksidmSide1);
// Read pixels from dib
int cpixels = m_cxOrig * m_cyOrig;
dword *pixels = new dword[cpixels];
int pitch = m_cxOrig * sizeof(dword);
SDL_Renderer *renderer = gpdisp->Renderer();
if (SDL_SetRenderTarget(renderer, pbm->Texture()) != 0)
return NULL;
// SDL_RenderReadPixels() is a slow operation
if (SDL_RenderReadPixels(renderer, NULL, 0, pixels, pitch) != 0)
return NULL;
// Loop through the pixels and convert to (255, 255, 255, a)
byte r, g, b, a;
word h, s, l;
// Loop helpers
int npixels = m_cxOrig * m_cyOrig;
dword *ppixels = pbm->GetBits();
dword *ppixel = ppixels;
dword *end = ppixels + npixels;
for (; ppixel < end; ppixel++, i0p++) {
SDL_GetRGBA(*i0p, pbm->GetSurface()->format, &r, &g, &b, &a);
RgbToHsl(r, g, b, &h, &s, &l);
if (lum > 32768)
lum = 32768;
if (lum < 0)
lum = 0;
// Change the pixel value
HslToRgb(h, s, lum, &r, &g, &b);
*ppixel = SDL_MapRGBA(pbm->GetSurface()->format, r, g, b, a);
for (int i = 0; i < cpixels; i++) {
SDL_GetRGBA(pixels[i], pbm->m_ppfmt, &r, &g, &b, &a);
pixels[i] = SDL_MapRGBA(pbm->m_ppfmt, 255, 255, 255, a);
}
return pbm;
delete pbm;
return CreateDibBitmap(pixels, m_cxOrig, m_cyOrig);
#endif // SDL
}
} // namespace wi

View File

@ -109,7 +109,7 @@ bool TileMap::Load(char *psz, Size *psizPlayfield)
return false;
for (int nTile = 0; nTile < m_cTiles; nTile++) {
m_tiles[nTile] = CreateBigDibBitmap(apbTileData[nTile], m_cxTile, m_cyTile);
m_tiles[nTile] = CreateDibBitmap(apbTileData[nTile], m_cxTile, m_cyTile);
}
delete[] apbTileData;