SDL display improvements

This commit is contained in:
Nathan Fulton 2016-08-25 15:54:09 -04:00
parent 3ae02f81eb
commit 4f2a0de55c
6 changed files with 110 additions and 73 deletions

View File

@ -32,10 +32,18 @@ Display::Display()
m_pbmFront = NULL; m_pbmFront = NULL;
m_pbmClip = NULL; m_pbmClip = NULL;
m_gameDisplay = NULL; m_window = NULL;
m_gameSurfacePixels = NULL; m_renderer = NULL;
m_gameSurface = NULL; m_texture = NULL;
m_gamePixels = NULL;
m_gamePixels32 = NULL;
memset(m_palette, 0, sizeof(m_palette));
m_pitch32 = 0;
m_pixelCount = 0; m_pixelCount = 0;
m_density = 0;
m_fShouldRender = false;
} }
Display::~Display() Display::~Display()
@ -47,23 +55,22 @@ Display::~Display()
delete m_pbmClip; delete m_pbmClip;
m_pbmClip = NULL; m_pbmClip = NULL;
delete m_gameDisplay; SDL_DestroyWindow(m_window);
m_gameDisplay = NULL; m_window = NULL;
SDL_DestroyRenderer(m_renderer);
m_renderer = NULL;
SDL_DestroyTexture(m_texture);
m_texture = NULL;
m_pixelCount = 0; delete m_gamePixels;
m_gameSurfacePixels = NULL; m_gamePixels = NULL;
SDL_FreeSurface(m_gameSurface); delete m_gamePixels32;
m_gameSurface = NULL; m_gamePixels32 = NULL;
SDL_DestroyWindow(window);
window = NULL;
SDL_DestroyTexture(texture);
texture = NULL;
} }
bool Display::Init() bool Display::Init()
{ {
Uint32 videoflags; dword videoflags;
int cxScreen, cyScreen;
/* Initialize SDL */ /* Initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0) { if (SDL_Init(SDL_INIT_VIDEO) < 0) {
@ -80,7 +87,7 @@ bool Display::Init()
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight LandscapeLeft"); SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight LandscapeLeft");
#endif #endif
// The host wants to process mouse and touch events separately // Android wants to process mouse and touch events separately
#if defined(__ANDROID__) #if defined(__ANDROID__)
SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1"); SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");
#endif #endif
@ -88,27 +95,36 @@ bool Display::Init()
// Get surface properties // Get surface properties
SurfaceProperties props; SurfaceProperties props;
HostHelpers::GetSurfaceProperties(&props); HostHelpers::GetSurfaceProperties(&props);
cxScreen = props.cxWidth; m_cx = props.cxWidth;
cyScreen = props.cyHeight; m_cy = props.cyHeight;
m_density = props.density; m_density = props.density;
// Create window // Create window
if ((window = SDL_CreateWindow("Hostile Takeover", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, cxScreen, cyScreen, videoflags)) == NULL) { if ((m_window = SDL_CreateWindow("Hostile Takeover", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_cx, m_cy, videoflags)) == NULL) {
LOG() << "Couldn't create window: " << cxScreen << "x" << cyScreen << " \nError: " << SDL_GetError(); LOG() << "Couldn't create window: " << m_cx << "x" << m_cy << " \nError: " << SDL_GetError();
return false; return false;
} }
renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_TARGETTEXTURE); // Create renderer
m_renderer = SDL_CreateRenderer(m_window, 0, SDL_RENDERER_TARGETTEXTURE);
this->SetShouldRender(true); this->SetShouldRender(true);
// Keep the screen size around // Keep the screen size around
s_siz.cx = cxScreen; s_siz.cx = m_cx;
s_siz.cy = cyScreen; s_siz.cy = m_cy;
m_gameSurface = SDL_CreateRGBSurface(videoflags, cxScreen, cyScreen, 32, 0, 0, 0, 0); // Create texture
m_pixelCount = cxScreen * cyScreen; m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, m_cx, m_cy);
m_gameDisplay = (byte *)malloc(m_pixelCount);
m_gameSurfacePixels = (Uint32 *)m_gameSurface->pixels; // Set pixel info
m_pixelCount = m_cx * m_cy;
m_gamePixels = (byte *)malloc(m_pixelCount);
m_gamePixels32 = (dword *)malloc(m_pixelCount * 4);
m_pitch32 = m_cx * sizeof(dword);
// Keep the screen size around
s_siz.cx = m_cx;
s_siz.cy = m_cy;
ModeInfo *pmode = m_amodeInfo; ModeInfo *pmode = m_amodeInfo;
@ -178,7 +194,7 @@ void Display::SetPalette(Palette *ppal)
} }
for (int i = 0; i < cEntries; i++) { for (int i = 0; i < cEntries; i++) {
m_32bppColors[i] = ((Uint8)aclr[i].r << 16) | ((Uint8)aclr[i].g << 8) | ((Uint8)aclr[i].b << 0); m_palette[i] = ((Uint8)aclr[i].r << 16) | ((Uint8)aclr[i].g << 8) | ((Uint8)aclr[i].b << 0);
} }
} }
@ -217,7 +233,7 @@ bool Display::SetMode(int imode)
if (pbmBack == NULL) if (pbmBack == NULL)
return false; return false;
DibBitmap *pbmFront = CreateDibBitmap(m_gameDisplay, pmode->cx, pmode->cy); DibBitmap *pbmFront = CreateDibBitmap(m_gamePixels, pmode->cx, pmode->cy);
if (pbmFront == NULL) { if (pbmFront == NULL) {
delete pbmBack; delete pbmBack;
return NULL; return NULL;
@ -269,38 +285,35 @@ void Display::FrameStart()
{ {
// surface->pixels can change every time the surface is locked. // surface->pixels can change every time the surface is locked.
// TODO(darrinm): problem for, e.g. scrolling optimizations? // TODO(darrinm): problem for, e.g. scrolling optimizations?
m_pbmFront->Init(m_gameDisplay, m_gameSurface->w, m_gameSurface->h); m_pbmFront->Init(m_gamePixels, m_cx, m_cy);
} }
void Display::FrameComplete(int cfrmm, UpdateMap **apupd, Rect *arc, void Display::FrameComplete(int cfrmm, UpdateMap **apupd, Rect *arc,
bool fScrolled) bool fScrolled)
{ {
for (int i = 0; i < m_pixelCount; i++) { for (int i = 0; i < m_pixelCount; i++) {
m_gameSurfacePixels[i] = m_32bppColors[m_gameDisplay[i]]; m_gamePixels32[i] = m_palette[m_gamePixels[i]];
} }
RenderGameSurface(); RenderGameSurface();
} }
void Display::RenderGameSurface() { void Display::RenderGameSurface() {
if (!m_fshouldRender) if (!m_fShouldRender)
return; return;
// Create the texture // Update the texture
texture = SDL_CreateTextureFromSurface(renderer, m_gameSurface); SDL_UpdateTexture(m_texture, NULL, m_gamePixels32, m_pitch32);
// Prepare the renderer // Draw any sprites onto the texture
SDL_RenderClear(renderer); SDL_SetRenderTarget(m_renderer, m_texture);
SDL_RenderCopy(renderer, texture, NULL, NULL); s_psprm->DrawSprites(m_renderer, s_siz);
SDL_SetRenderTarget(m_renderer, NULL);
// Draw on any sprites // Present the renderer to the screen
s_psprm->DrawSprites(renderer, s_siz); SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
// Present the renderer SDL_RenderPresent(m_renderer);
SDL_RenderPresent(renderer);
// Free memory from the created texture
SDL_DestroyTexture(texture);
} }
void Display::ResetScrollOffset() void Display::ResetScrollOffset()
@ -329,7 +342,7 @@ float Display::Density() {
} }
void Display::SetShouldRender(bool fsr) { void Display::SetShouldRender(bool fsr) {
m_fshouldRender = fsr; m_fShouldRender = fsr;
} }
} // namespace wi } // namespace wi

View File

@ -454,6 +454,11 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt)
pevt->eType = appStopEvent; pevt->eType = appStopEvent;
break; break;
case SDL_WINDOWEVENT:
gpmfrmm->DrawFrame(true);
gpdisp->RenderGameSurface();
break;
default: default:
return false; return false;
} }

View File

@ -137,17 +137,18 @@ private:
DibBitmap *m_pbmFront; DibBitmap *m_pbmFront;
DibBitmap *m_pbmClip; DibBitmap *m_pbmClip;
SDL_Window *window; SDL_Window *m_window;
SDL_Renderer *renderer; SDL_Renderer *m_renderer;
SDL_Texture *texture; SDL_Texture *m_texture;
byte *m_gameDisplay; byte *m_gamePixels;
SDL_Surface *m_gameSurface; Uint32 *m_gamePixels32;
Uint32 *m_gameSurfacePixels; Uint32 m_palette[256];
Uint32 m_32bppColors[256]; int m_pitch32;
int m_pixelCount; int m_pixelCount;
float m_density; float m_density;
bool m_fshouldRender; bool m_fShouldRender;
}; };
#define kfDtClearLine 1 #define kfDtClearLine 1

View File

@ -1,5 +1,8 @@
#include "game/sdl/sdlselectionsprite.h" #include "game/sdl/sdlselectionsprite.h"
#define GRABBIE_SIZE 10
#define GRABBIE_SIZE_HALF GRABBIE_SIZE/2
namespace wi { namespace wi {
SdlSelectionSprite::SdlSelectionSprite(SpriteManager *psprm) { SdlSelectionSprite::SdlSelectionSprite(SpriteManager *psprm) {
@ -41,27 +44,21 @@ void SdlSelectionSprite::Draw(void *pv, Size *psiz) {
DPoint apt[4]; DPoint apt[4];
drc_.GetPoints(apt); drc_.GetPoints(apt);
float density = gpdisp->Density();
#define renderer (SDL_Renderer *)pv #define renderer (SDL_Renderer *)pv
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
for (int i = 0; i < ARRAYSIZE(apt); i++) { for (int i = 0; i < ARRAYSIZE(apt); i++) {
int next = i + 1 == ARRAYSIZE(apt) ? 0 : i + 1; int next = i + 1 == ARRAYSIZE(apt) ? 0 : i + 1;
// x/y points for point a/b of the selection sprite line // x/y are swapped
int x1 = roundf(apt[i].y * density); Point pt1 = {apt[i].y, apt[i].x};
int y1 = roundf(apt[i].x * density); Point pt2 = {apt[next].y, apt[next].x};
int x2 = roundf(apt[next].y * density);
int y2 = roundf(apt[next].x * density);
// draw the selection sprite line // draw the selection sprite line
SDL_RenderDrawLine(renderer, x1, y1, x2, y2); SDL_RenderDrawLine(renderer, pt1.x, pt1.y, pt2.x, pt2.y);
int gs = 20; // grabbie size
int gsh = gs / 2; // grabbie size half
// create and draw a grabbie rect // create and draw a grabbie rect
SDL_Rect rect = {x1 - gsh, y1 - gsh , gs, gs}; SDL_Rect rect = {pt1.x - GRABBIE_SIZE_HALF, pt1.y - GRABBIE_SIZE_HALF,
GRABBIE_SIZE, GRABBIE_SIZE};
SDL_RenderFillRect(renderer, &rect); SDL_RenderFillRect(renderer, &rect);
} }

View File

@ -8,6 +8,8 @@ SdlSpriteManager::SdlSpriteManager() {
pcrit_ = new base::CriticalSection(); pcrit_ = new base::CriticalSection();
cpspr_ = 0; cpspr_ = 0;
fSpriteDirty_ = false; fSpriteDirty_ = false;
memset(&rcClip1_, 0, sizeof(rcClip1_));
memset(&rcClip2_, 0, sizeof(rcClip2_));
} }
SdlSpriteManager::~SdlSpriteManager() { SdlSpriteManager::~SdlSpriteManager() {
@ -64,8 +66,28 @@ void SdlSpriteManager::DrawSprites(SDL_Renderer *renderer, Size siz) {
} }
for (int i = 0; i < cpspr_; i++) { for (int i = 0; i < cpspr_; i++) {
// Draw clipped to rcClip1
SDL_RenderSetClipRect(renderer, &rcClip1_);
apspr_[i]->Draw(renderer, &siz);
// Draw clipped to rcClip2
SDL_RenderSetClipRect(renderer, &rcClip2_);
apspr_[i]->Draw(renderer, &siz); apspr_[i]->Draw(renderer, &siz);
} }
SDL_RenderSetClipRect(renderer, NULL);
}
void SdlSpriteManager::SetClipRects(wi::Rect *prc1, wi::Rect *prc2) {
rcClip1_.x = prc1->left;
rcClip1_.y = prc1->top;
rcClip1_.w = prc1->Width();
rcClip1_.h = prc1->Height();
rcClip2_.x = prc2->left;
rcClip2_.y = prc2->top;
rcClip2_.w = prc2->Width();
rcClip2_.h = prc2->Height();
} }

View File

@ -11,10 +11,7 @@ public:
SdlSpriteManager(); SdlSpriteManager();
~SdlSpriteManager(); ~SdlSpriteManager();
virtual void SetClipRects(wi::Rect *prc1, wi::Rect *prc2) { virtual void SetClipRects(wi::Rect *prc1, wi::Rect *prc2);
LOG() << "SdlSpriteManager::SetClipRects not implemented yet";
return;
}
virtual wi::AnimSprite *CreateAnimSprite() { virtual wi::AnimSprite *CreateAnimSprite() {
LOG() << "SdlSpriteManager::CreateAnimSprite not implemented yet"; LOG() << "SdlSpriteManager::CreateAnimSprite not implemented yet";
return NULL; return NULL;
@ -32,6 +29,8 @@ private:
int cpspr_; int cpspr_;
wi::Sprite *apspr_[16]; wi::Sprite *apspr_[16];
bool fSpriteDirty_; bool fSpriteDirty_;
SDL_Rect rcClip1_;
SDL_Rect rcClip2_;
}; };
} // namespace wi } // namespace wi