mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-10 08:00:05 +00:00
Codechange: [SDL2] Rework how palette is updated
It now follows more what the Win32 driver does, and has far less exceptions and special casing. MakePalette creates the Palette and prepares surface. UpdatePalette updates the Palette. CheckPaletteAnim checks if UpdatePalette needs to be called and marks the whole screen dirty so DrawSurfaceToScreen will do a full redraw.
This commit is contained in:
parent
eb80fefd1d
commit
30e69c518b
@ -73,7 +73,7 @@ void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height)
|
|||||||
_num_dirty_rects++;
|
_num_dirty_rects++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdatePalette(bool init = false)
|
static void UpdatePalette()
|
||||||
{
|
{
|
||||||
SDL_Color pal[256];
|
SDL_Color pal[256];
|
||||||
|
|
||||||
@ -86,8 +86,19 @@ static void UpdatePalette(bool init = false)
|
|||||||
|
|
||||||
SDL_SetPaletteColors(_sdl_palette, pal, _local_palette.first_dirty, _local_palette.count_dirty);
|
SDL_SetPaletteColors(_sdl_palette, pal, _local_palette.first_dirty, _local_palette.count_dirty);
|
||||||
SDL_SetSurfacePalette(_sdl_surface, _sdl_palette);
|
SDL_SetSurfacePalette(_sdl_surface, _sdl_palette);
|
||||||
|
}
|
||||||
|
|
||||||
if (_sdl_surface != _sdl_real_surface && init) {
|
static void MakePalette()
|
||||||
|
{
|
||||||
|
if (_sdl_palette == nullptr) {
|
||||||
|
_sdl_palette = SDL_AllocPalette(256);
|
||||||
|
if (_sdl_palette == nullptr) usererror("SDL2: Couldn't allocate palette: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
_local_palette = _cur_palette;
|
||||||
|
UpdatePalette();
|
||||||
|
|
||||||
|
if (_sdl_surface != _sdl_real_surface) {
|
||||||
/* When using a shadow surface, also set our palette on the real screen. This lets SDL
|
/* When using a shadow surface, also set our palette on the real screen. This lets SDL
|
||||||
* allocate as many colors (or approximations) as
|
* allocate as many colors (or approximations) as
|
||||||
* possible, instead of using only the default SDL
|
* possible, instead of using only the default SDL
|
||||||
@ -110,33 +121,22 @@ static void UpdatePalette(bool init = false)
|
|||||||
*/
|
*/
|
||||||
SDL_SetSurfacePalette(_sdl_real_surface, _sdl_palette);
|
SDL_SetSurfacePalette(_sdl_real_surface, _sdl_palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_sdl_surface != _sdl_real_surface && !init) {
|
|
||||||
/* We're not using real hardware palette, but are letting SDL
|
|
||||||
* approximate the palette during shadow -> screen copy. To
|
|
||||||
* change the palette, we need to recopy the entire screen.
|
|
||||||
*
|
|
||||||
* Note that this operation can slow down the rendering
|
|
||||||
* considerably, especially since changing the shadow
|
|
||||||
* palette will need the next blit to re-detect the
|
|
||||||
* best mapping of shadow palette colors to real palette
|
|
||||||
* colors from scratch.
|
|
||||||
*/
|
|
||||||
SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr);
|
|
||||||
SDL_UpdateWindowSurface(_sdl_window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitPalette()
|
void VideoDriver_SDL::CheckPaletteAnim()
|
||||||
{
|
{
|
||||||
_cur_palette.first_dirty = 0;
|
if (_cur_palette.count_dirty == 0) return;
|
||||||
_cur_palette.count_dirty = 256;
|
|
||||||
_local_palette = _cur_palette;
|
_local_palette = _cur_palette;
|
||||||
UpdatePalette(true);
|
this->MakeDirty(0, 0, _screen.width, _screen.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CheckPaletteAnim()
|
static void DrawSurfaceToScreen()
|
||||||
{
|
{
|
||||||
|
PerformanceMeasurer framerate(PFE_VIDEO);
|
||||||
|
|
||||||
|
if (_num_dirty_rects == 0) return;
|
||||||
|
|
||||||
if (_cur_palette.count_dirty != 0) {
|
if (_cur_palette.count_dirty != 0) {
|
||||||
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
||||||
|
|
||||||
@ -157,18 +157,8 @@ static void CheckPaletteAnim()
|
|||||||
}
|
}
|
||||||
_cur_palette.count_dirty = 0;
|
_cur_palette.count_dirty = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void DrawSurfaceToScreen()
|
if (_num_dirty_rects > MAX_DIRTY_RECTS) {
|
||||||
{
|
|
||||||
PerformanceMeasurer framerate(PFE_VIDEO);
|
|
||||||
|
|
||||||
int n = _num_dirty_rects;
|
|
||||||
if (n == 0) return;
|
|
||||||
|
|
||||||
_num_dirty_rects = 0;
|
|
||||||
|
|
||||||
if (n > MAX_DIRTY_RECTS) {
|
|
||||||
if (_sdl_surface != _sdl_real_surface) {
|
if (_sdl_surface != _sdl_real_surface) {
|
||||||
SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr);
|
SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr);
|
||||||
}
|
}
|
||||||
@ -176,13 +166,15 @@ static void DrawSurfaceToScreen()
|
|||||||
SDL_UpdateWindowSurface(_sdl_window);
|
SDL_UpdateWindowSurface(_sdl_window);
|
||||||
} else {
|
} else {
|
||||||
if (_sdl_surface != _sdl_real_surface) {
|
if (_sdl_surface != _sdl_real_surface) {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < _num_dirty_rects; i++) {
|
||||||
SDL_BlitSurface(_sdl_surface, &_dirty_rects[i], _sdl_real_surface, &_dirty_rects[i]);
|
SDL_BlitSurface(_sdl_surface, &_dirty_rects[i], _sdl_real_surface, &_dirty_rects[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UpdateWindowSurfaceRects(_sdl_window, _dirty_rects, n);
|
SDL_UpdateWindowSurfaceRects(_sdl_window, _dirty_rects, _num_dirty_rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_num_dirty_rects = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawSurfaceToScreenThread()
|
static void DrawSurfaceToScreenThread()
|
||||||
@ -195,7 +187,6 @@ static void DrawSurfaceToScreenThread()
|
|||||||
_draw_signal->wait(*_draw_mutex);
|
_draw_signal->wait(*_draw_mutex);
|
||||||
|
|
||||||
while (_draw_continue) {
|
while (_draw_continue) {
|
||||||
CheckPaletteAnim();
|
|
||||||
/* Then just draw and wait till we stop */
|
/* Then just draw and wait till we stop */
|
||||||
DrawSurfaceToScreen();
|
DrawSurfaceToScreen();
|
||||||
_draw_signal->wait(lock);
|
_draw_signal->wait(lock);
|
||||||
@ -362,14 +353,6 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
|
|||||||
_sdl_surface = _sdl_real_surface;
|
_sdl_surface = _sdl_real_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_sdl_palette == nullptr) {
|
|
||||||
_sdl_palette = SDL_AllocPalette(256);
|
|
||||||
if (_sdl_palette == nullptr) {
|
|
||||||
DEBUG(driver, 0, "SDL_AllocPalette() failed: %s", SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delay drawing for this cycle; the next cycle will redraw the whole screen */
|
/* Delay drawing for this cycle; the next cycle will redraw the whole screen */
|
||||||
_num_dirty_rects = 0;
|
_num_dirty_rects = 0;
|
||||||
|
|
||||||
@ -378,6 +361,8 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
|
|||||||
_screen.pitch = _sdl_surface->pitch / (bpp / 8);
|
_screen.pitch = _sdl_surface->pitch / (bpp / 8);
|
||||||
_screen.dst_ptr = _sdl_surface->pixels;
|
_screen.dst_ptr = _sdl_surface->pixels;
|
||||||
|
|
||||||
|
MakePalette();
|
||||||
|
|
||||||
/* When in full screen, we will always have the mouse cursor
|
/* When in full screen, we will always have the mouse cursor
|
||||||
* within the window, even though SDL does not give us the
|
* within the window, even though SDL does not give us the
|
||||||
* appropriate event to know this. */
|
* appropriate event to know this. */
|
||||||
@ -385,7 +370,6 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
|
|||||||
|
|
||||||
BlitterFactory::GetCurrentBlitter()->PostResize();
|
BlitterFactory::GetCurrentBlitter()->PostResize();
|
||||||
|
|
||||||
InitPalette();
|
|
||||||
GameSizeChanged();
|
GameSizeChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -813,7 +797,7 @@ void VideoDriver_SDL::LoopOnce()
|
|||||||
if (_draw_mutex != nullptr) draw_lock.lock();
|
if (_draw_mutex != nullptr) draw_lock.lock();
|
||||||
|
|
||||||
UpdateWindows();
|
UpdateWindows();
|
||||||
_local_palette = _cur_palette;
|
this->CheckPaletteAnim();
|
||||||
} else {
|
} else {
|
||||||
/* Release the thread while sleeping */
|
/* Release the thread while sleeping */
|
||||||
if (_draw_mutex != nullptr) {
|
if (_draw_mutex != nullptr) {
|
||||||
@ -837,7 +821,6 @@ void VideoDriver_SDL::LoopOnce()
|
|||||||
_draw_signal->notify_one();
|
_draw_signal->notify_one();
|
||||||
} else {
|
} else {
|
||||||
/* Oh, we didn't have threads, then just draw unthreaded */
|
/* Oh, we didn't have threads, then just draw unthreaded */
|
||||||
CheckPaletteAnim();
|
|
||||||
DrawSurfaceToScreen();
|
DrawSurfaceToScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -848,7 +831,7 @@ void VideoDriver_SDL::MainLoop()
|
|||||||
last_cur_ticks = cur_ticks;
|
last_cur_ticks = cur_ticks;
|
||||||
next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
||||||
|
|
||||||
CheckPaletteAnim();
|
this->CheckPaletteAnim();
|
||||||
|
|
||||||
if (_draw_threaded) {
|
if (_draw_threaded) {
|
||||||
/* Initialise the mutex first, because that's the thing we *need*
|
/* Initialise the mutex first, because that's the thing we *need*
|
||||||
|
@ -50,6 +50,7 @@ private:
|
|||||||
void MainLoopCleanup();
|
void MainLoopCleanup();
|
||||||
bool CreateMainSurface(uint w, uint h, bool resize);
|
bool CreateMainSurface(uint w, uint h, bool resize);
|
||||||
bool CreateMainWindow(uint w, uint h);
|
bool CreateMainWindow(uint w, uint h);
|
||||||
|
void CheckPaletteAnim();
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
/* Convert a constant pointer back to a non-constant pointer to a member function. */
|
/* Convert a constant pointer back to a non-constant pointer to a member function. */
|
||||||
|
Loading…
Reference in New Issue
Block a user