diff --git a/game/SimUI.cpp b/game/SimUI.cpp index a159c95..b15ffd1 100644 --- a/game/SimUI.cpp +++ b/game/SimUI.cpp @@ -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 diff --git a/game/bitmap.cpp b/game/bitmap.cpp index c00d965..1215e60 100644 --- a/game/bitmap.cpp +++ b/game/bitmap.cpp @@ -3,12 +3,7 @@ #if defined(SDL) #include #include - -#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 diff --git a/game/formmgr.cpp b/game/formmgr.cpp index fa1ca27..d62a13f 100644 --- a/game/formmgr.cpp +++ b/game/formmgr.cpp @@ -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 diff --git a/game/game.cpp b/game/game.cpp index 0edba4e..d9344ce 100644 --- a/game/game.cpp +++ b/game/game.cpp @@ -2165,7 +2165,7 @@ bool Game::FilterEvent(Event *pevt) // Draw - gpmfrmm->DrawFrame(false); + gpmfrmm->DrawFrame(true); return true; case gameSuspendEvent: diff --git a/game/ht.h b/game/ht.h index 2ee3262..2f1eb58 100644 --- a/game/ht.h +++ b/game/ht.h @@ -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; diff --git a/game/sdl/display.cpp b/game/sdl/display.cpp index 1cc7308..fd46fda 100644 --- a/game/sdl/display.cpp +++ b/game/sdl/display.cpp @@ -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 diff --git a/game/sdl/host.cpp b/game/sdl/host.cpp index bafd283..302403f 100644 --- a/game/sdl/host.cpp +++ b/game/sdl/host.cpp @@ -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: diff --git a/game/sdl/htplatform.h b/game/sdl/htplatform.h index c9b924c..356bc74 100644 --- a/game/sdl/htplatform.h +++ b/game/sdl/htplatform.h @@ -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; }; diff --git a/game/sdl/sdlanimsprite.cpp b/game/sdl/sdlanimsprite.cpp index 5c66e89..eb7c404 100644 --- a/game/sdl/sdlanimsprite.cpp +++ b/game/sdl/sdlanimsprite.cpp @@ -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(); diff --git a/game/sdl/sdlanimsprite.h b/game/sdl/sdlanimsprite.h index 1c3ffc5..998c871 100644 --- a/game/sdl/sdlanimsprite.h +++ b/game/sdl/sdlanimsprite.h @@ -44,7 +44,7 @@ private: dword hash_; int cx_, cy_; int xOrigin_, yOrigin_; - DibBitmap *surface_; + DibBitmap *pbm_; SpriteManager *psprm_; float nScaleStart_, nScaleEnd_; long msAnimateStart_; diff --git a/game/tbitmap.cpp b/game/tbitmap.cpp index f06b309..17d33ae 100644 --- a/game/tbitmap.cpp +++ b/game/tbitmap.cpp @@ -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 diff --git a/game/tilemap.cpp b/game/tilemap.cpp index 3e04ed5..236bc6c 100644 --- a/game/tilemap.cpp +++ b/game/tilemap.cpp @@ -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;