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

@ -31,11 +31,19 @@ Display::Display()
m_pbmBack = NULL;
m_pbmFront = NULL;
m_pbmClip = NULL;
m_gameDisplay = NULL;
m_gameSurfacePixels = NULL;
m_gameSurface = NULL;
m_window = NULL;
m_renderer = NULL;
m_texture = NULL;
m_gamePixels = NULL;
m_gamePixels32 = NULL;
memset(m_palette, 0, sizeof(m_palette));
m_pitch32 = 0;
m_pixelCount = 0;
m_density = 0;
m_fShouldRender = false;
}
Display::~Display()
@ -46,24 +54,23 @@ Display::~Display()
m_pbmFront = NULL;
delete m_pbmClip;
m_pbmClip = NULL;
delete m_gameDisplay;
m_gameDisplay = NULL;
m_pixelCount = 0;
m_gameSurfacePixels = NULL;
SDL_FreeSurface(m_gameSurface);
m_gameSurface = NULL;
SDL_DestroyWindow(window);
window = NULL;
SDL_DestroyTexture(texture);
texture = NULL;
SDL_DestroyWindow(m_window);
m_window = NULL;
SDL_DestroyRenderer(m_renderer);
m_renderer = NULL;
SDL_DestroyTexture(m_texture);
m_texture = NULL;
delete m_gamePixels;
m_gamePixels = NULL;
delete m_gamePixels32;
m_gamePixels32 = NULL;
}
bool Display::Init()
{
Uint32 videoflags;
int cxScreen, cyScreen;
dword videoflags;
/* Initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
@ -80,7 +87,7 @@ bool Display::Init()
SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight LandscapeLeft");
#endif
// The host wants to process mouse and touch events separately
// Android wants to process mouse and touch events separately
#if defined(__ANDROID__)
SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");
#endif
@ -88,27 +95,36 @@ bool Display::Init()
// Get surface properties
SurfaceProperties props;
HostHelpers::GetSurfaceProperties(&props);
cxScreen = props.cxWidth;
cyScreen = props.cyHeight;
m_cx = props.cxWidth;
m_cy = props.cyHeight;
m_density = props.density;
// Create window
if ((window = SDL_CreateWindow("Hostile Takeover", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, cxScreen, cyScreen, videoflags)) == NULL) {
LOG() << "Couldn't create window: " << cxScreen << "x" << cyScreen << " \nError: " << SDL_GetError();
if ((m_window = SDL_CreateWindow("Hostile Takeover", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_cx, m_cy, videoflags)) == NULL) {
LOG() << "Couldn't create window: " << m_cx << "x" << m_cy << " \nError: " << SDL_GetError();
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);
// Keep the screen size around
s_siz.cx = cxScreen;
s_siz.cy = cyScreen;
s_siz.cx = m_cx;
s_siz.cy = m_cy;
m_gameSurface = SDL_CreateRGBSurface(videoflags, cxScreen, cyScreen, 32, 0, 0, 0, 0);
m_pixelCount = cxScreen * cyScreen;
m_gameDisplay = (byte *)malloc(m_pixelCount);
m_gameSurfacePixels = (Uint32 *)m_gameSurface->pixels;
// Create texture
m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, m_cx, m_cy);
// 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;
@ -178,7 +194,7 @@ void Display::SetPalette(Palette *ppal)
}
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)
return false;
DibBitmap *pbmFront = CreateDibBitmap(m_gameDisplay, pmode->cx, pmode->cy);
DibBitmap *pbmFront = CreateDibBitmap(m_gamePixels, pmode->cx, pmode->cy);
if (pbmFront == NULL) {
delete pbmBack;
return NULL;
@ -269,38 +285,35 @@ void Display::FrameStart()
{
// surface->pixels can change every time the surface is locked.
// 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,
bool fScrolled)
{
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();
}
void Display::RenderGameSurface() {
if (!m_fshouldRender)
if (!m_fShouldRender)
return;
// Create the texture
texture = SDL_CreateTextureFromSurface(renderer, m_gameSurface);
// Update the texture
SDL_UpdateTexture(m_texture, NULL, m_gamePixels32, m_pitch32);
// Prepare the renderer
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
// Draw any sprites onto the texture
SDL_SetRenderTarget(m_renderer, m_texture);
s_psprm->DrawSprites(m_renderer, s_siz);
SDL_SetRenderTarget(m_renderer, NULL);
// Draw on any sprites
s_psprm->DrawSprites(renderer, s_siz);
// Present the renderer
SDL_RenderPresent(renderer);
// Free memory from the created texture
SDL_DestroyTexture(texture);
// Present the renderer to the screen
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
}
void Display::ResetScrollOffset()
@ -329,7 +342,7 @@ float Display::Density() {
}
void Display::SetShouldRender(bool fsr) {
m_fshouldRender = fsr;
m_fShouldRender = fsr;
}
} // namespace wi

View File

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

View File

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

View File

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

View File

@ -8,6 +8,8 @@ SdlSpriteManager::SdlSpriteManager() {
pcrit_ = new base::CriticalSection();
cpspr_ = 0;
fSpriteDirty_ = false;
memset(&rcClip1_, 0, sizeof(rcClip1_));
memset(&rcClip2_, 0, sizeof(rcClip2_));
}
SdlSpriteManager::~SdlSpriteManager() {
@ -64,8 +66,28 @@ void SdlSpriteManager::DrawSprites(SDL_Renderer *renderer, Size siz) {
}
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);
}
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();
virtual void SetClipRects(wi::Rect *prc1, wi::Rect *prc2) {
LOG() << "SdlSpriteManager::SetClipRects not implemented yet";
return;
}
virtual void SetClipRects(wi::Rect *prc1, wi::Rect *prc2);
virtual wi::AnimSprite *CreateAnimSprite() {
LOG() << "SdlSpriteManager::CreateAnimSprite not implemented yet";
return NULL;
@ -32,6 +29,8 @@ private:
int cpspr_;
wi::Sprite *apspr_[16];
bool fSpriteDirty_;
SDL_Rect rcClip1_;
SDL_Rect rcClip2_;
};
} // namespace wi