changeset 1557:5e5f75b45f8d

Initial port to SDL2. Many things will not work now.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 13 May 2018 06:00:50 +0300
parents 8f06c23e197d
children 48dcde220a2e
files Makefile Makefile.cross-mingw Makefile.gen README.txt src/dmengine.c src/dmengine.h src/dmimage.c src/dmimage.h src/dmlib.h src/dmmutex.h src/dmsimple.c src/dmtext_bm.c tools/64vw.c tools/fontconv.c tools/ppl.c
diffstat 15 files changed, 179 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun May 13 05:59:42 2018 +0300
+++ b/Makefile	Sun May 13 06:00:50 2018 +0300
@@ -10,11 +10,11 @@
 INSTALL ?= install
 RANLIB ?= ranlib
 
-SDL_CFLAGS ?= $(shell pkg-config --cflags sdl)
-SDL_LDFLAGS ?= $(shell pkg-config --libs sdl)
+SDL_CFLAGS ?= $(shell pkg-config --cflags sdl2)
+SDL_LDFLAGS ?= $(shell pkg-config --libs sdl2)
 
-SDL_TTF_CFLAGS ?= $(shell pkg-config --cflags SDL_ttf)
-SDL_TTF_LDFLAGS ?= $(shell pkg-config --libs SDL_ttf)
+SDL_TTF_CFLAGS ?= $(shell pkg-config --cflags SDL2_ttf)
+SDL_TTF_LDFLAGS ?= $(shell pkg-config --libs SDL2_ttf)
 
 TREMOR_CFLAGS ?= $(shell pkg-config --cflags ogg)
 TREMOR_LDFLAGS ?= /usr/lib/libvorbisidec.a $(shell pkg-config --variable=libdir ogg)/libogg.a
--- a/Makefile.cross-mingw	Sun May 13 05:59:42 2018 +0300
+++ b/Makefile.cross-mingw	Sun May 13 06:00:50 2018 +0300
@@ -16,11 +16,11 @@
 RANLIB = $(MINGW_PREFIX)ranlib
 RM ?= rm
 
-SDL_CFLAGS ?= $(shell $(MINGW_PATH)/bin/sdl-config --cflags)
-SDL_LDFLAGS ?= $(shell $(MINGW_PATH)/bin/sdl-config --libs)
+SDL_CFLAGS ?= $(shell $(MINGW_PATH)/bin/sdl2-config --cflags)
+SDL_LDFLAGS ?= $(shell $(MINGW_PATH)/bin/sdl2-config --libs)
 
 SDL_TTF_CFLAGS ?=
-SDL_TTF_LDFLAGS ?= -lSDL_ttf
+SDL_TTF_LDFLAGS ?= -lSDL2_ttf
 
 TREMOR_CFLAGS ?= -I$(MINGW_PATH)/include/tremor
 TREMOR_LDFLAGS ?= $(MINGW_PATH)/lib/libvorbisidec.a $(MINGW_PATH)/lib/libogg.a
--- a/Makefile.gen	Sun May 13 05:59:42 2018 +0300
+++ b/Makefile.gen	Sun May 13 06:00:50 2018 +0300
@@ -145,7 +145,7 @@
 ifeq ($(DM_BUILD_TESTS),yes)
 ifeq ($(DM_GFX_BLITS),yes)
 ifeq ($(DM_USE_STDIO),yes)
-TESTS_BINARIES += blittest
+#TESTS_BINARIES += blittest
 endif
 endif
 endif
--- a/README.txt	Sun May 13 05:59:42 2018 +0300
+++ b/README.txt	Sun May 13 06:00:50 2018 +0300
@@ -63,19 +63,18 @@
 
 You will also want these libraries:
 
- - libSDL 1.2, preferably the latest stable version.
+ - libSDL 2.0
  - zlib
  - libPNG 1.2 and development headers (more optional,
    only required for PNG write and read support by some
    utilities.)
- - SDL_ttf 2.0 and libfreetype2
+ - SDL_ttf for libSDL2 (optional, required for some things)
  - Tremor (integer-based Ogg Vorbis decoder) + libogg
 
 And the demo editor framework requires (but it is not yet
 usable anyway, so you may as well skip these):
 
- - Qt 4.x framework libraries (tested with 4.7 and 4.8.2)
- - qmake, moc
+ - Qt 5.x framework libraries (tested with 5.7)
 
 
 For Linux -> Win32/64 cross-compilation I have used the standard
--- a/src/dmengine.c	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmengine.c	Sun May 13 06:00:50 2018 +0300
@@ -542,7 +542,7 @@
         engine->audioSimBufSize = (engine->optAfmt.freq / 45) * engine->audioSampleSize;
         engine->audioSimBuf     = dmMalloc(engine->audioSimBufSize);
         engine->audioSimDone    = FALSE;
-        engine->audioSimThread  = SDL_CreateThread(engineAudioThreadFunc, engine);
+        engine->audioSimThread  = SDL_CreateThread(engineAudioThreadFunc, "DMLib Audio Simulation Thread", engine);
         if (engine->audioSimThread == NULL)
             return DMERR_INIT_FAIL;
     }
--- a/src/dmengine.h	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmengine.h	Sun May 13 06:00:50 2018 +0300
@@ -242,6 +242,8 @@
     BOOL pauseFlag, paused, exitFlag;
 
     // Rendering
+    SDL_Window *window;
+    SDL_Renderer *renderer;
     SDL_Surface *screen;
 
     // Events
--- a/src/dmimage.c	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmimage.c	Sun May 13 06:00:50 2018 +0300
@@ -51,14 +51,14 @@
     SDL_Surface
         *result = NULL,
         *pixtmp = SDL_CreateRGBSurface(
-            SDL_SWSURFACE | SDL_SRCALPHA,
+            SDL_SWSURFACE,
             16, 16, 32,
             dmXrmask, dmXgmask, dmXbmask, dmXamask);
 
     if (tmp != NULL && pixtmp != NULL)
     {
         // Convert surface
-        result = SDL_ConvertSurface(tmp, pixtmp->format, SDL_SWSURFACE | SDL_SRCALPHA);
+        result = SDL_ConvertSurface(tmp, pixtmp->format, SDL_SWSURFACE);
         SDL_FreeSurface(tmp);
     }
     if (pixtmp != NULL)
@@ -90,7 +90,6 @@
 }
 
 
-
 static int dmSTBIread(void *user, char *data, int size)
 {
     return dmfread(data, 1, size, (DMResource *) user);
@@ -176,3 +175,23 @@
 
     return result;
 }
+
+
+SDL_Texture *dmLoadImageToTexture(DMResource *file, SDL_Renderer *renderer)
+{
+    SDL_Surface *tmp;
+    SDL_Texture *texture;
+
+    // Sanity checks
+    if (renderer == NULL || file == NULL)
+        return NULL;
+
+    if ((tmp = dmLoadImage(file)) == NULL)
+        return NULL;
+
+    // Attempt to create the texture
+    texture = SDL_CreateTextureFromSurface(renderer, tmp);
+    SDL_FreeSurface(tmp);
+
+    return texture;
+}
--- a/src/dmimage.h	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmimage.h	Sun May 13 06:00:50 2018 +0300
@@ -18,6 +18,7 @@
 SDL_Surface *dmCreateRGBSurfaceFrom(void *data, const int width, const int height, const int depth, const int pitch, const int rmask, const int gmask, const int bmask, const int amask);
 SDL_Surface *dmCreatePaletteSurfaceFrom(void *data, const int width, const int height, const int pitch);
 SDL_Surface *dmLoadImage(DMResource *file);
+SDL_Texture *dmLoadImageToTexture(DMResource *file, SDL_Renderer *renderer);
 
 
 #ifdef __cplusplus
--- a/src/dmlib.h	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmlib.h	Sun May 13 06:00:50 2018 +0300
@@ -13,6 +13,7 @@
 #include <SDL_mutex.h>
 #include <SDL_thread.h>
 #include <SDL_video.h>
+#include <SDL_render.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
--- a/src/dmmutex.h	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmmutex.h	Sun May 13 06:00:50 2018 +0300
@@ -7,7 +7,7 @@
 #ifndef DMMUTEX_H
 #define DMMUTEX_H 1
 
-Uint32 SDL_ThreadID()
+SDL_threadID SDL_ThreadID()
 {
     return 0;
 }
--- a/src/dmsimple.c	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmsimple.c	Sun May 13 06:00:50 2018 +0300
@@ -153,16 +153,6 @@
     dmPrint(1, "Initializing SDL video %d x %d x %dbpp, flags=0x%08x\n",
         width, height, depth, flags);
 
-    SDL_FreeSurface(engine.screen);
-
-    engine.screen = SDL_SetVideoMode(width, height, depth, flags);
-    if (engine.screen == NULL)
-    {
-        dmError(DMERR_INIT_FAIL,
-            "Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
-        return FALSE;
-    }
-
     SDL_WM_SetCaption(dmProgDesc, dmProgName);
 
     return TRUE;
@@ -532,11 +522,6 @@
 
         // Draw frame
         engine.frameTime = SDL_GetTicks();
-        if (SDL_MUSTLOCK(engine.screen) && SDL_LockSurface(engine.screen) != 0)
-        {
-            dmError(DMERR_INTERNAL, "Can't lock surface.\n");
-            goto out;
-        }
 
         // Render the menu
         dmDirectBlitSurface(menuBgImage, engine.screen);
@@ -598,9 +583,6 @@
             menuStr);
 
         // Flip screen
-        if (SDL_MUSTLOCK(engine.screen))
-            SDL_UnlockSurface(engine.screen);
-
         SDL_Flip(engine.screen);
         SDL_Delay(25);
     }
@@ -914,12 +896,6 @@
             engine.startTime = engine.frameTime - engine.pauseTime;
         }
 
-        if (SDL_MUSTLOCK(engine.screen) && SDL_LockSurface(engine.screen) != 0)
-        {
-            dmError(DMERR_INTERNAL, "Can't lock surface.\n");
-            goto out;
-        }
-
         // Call main tick
         if (engine.demoRender != NULL)
         {
@@ -934,11 +910,6 @@
         }
 #endif
 
-        // Flip screen
-        if (SDL_MUSTLOCK(engine.screen))
-            SDL_UnlockSurface(engine.screen);
-
-        SDL_Flip(engine.screen);
         SDL_Delay(engine.paused ? 100 : 20);
 
         engine.frameCount++;
--- a/src/dmtext_bm.c	Sun May 13 05:59:42 2018 +0300
+++ b/src/dmtext_bm.c	Sun May 13 06:00:50 2018 +0300
@@ -113,7 +113,7 @@
         SDL_Surface *glyph = font->glyphs[i];
         if (glyph != NULL)
         {
-            SDL_SetColors(glyph, pal, start, size);
+            SDL_SetPaletteColors(glyph->format->palette, pal, start, size);
         }
     }
 
@@ -224,7 +224,7 @@
         for (n = 0; n < DMFONT_NPALETTE; n++)
         {
             pal[n].r = pal[n].g = pal[n].b = 0;
-            pal[n].unused = n > 0 ? 255 : 0;
+            pal[n].a = n > 0 ? 255 : 0;
         }
 
         if (tsfont)
@@ -272,15 +272,13 @@
             // Allocate bitmap
             font->glyphs[index] = glyph = SDL_CreateRGBSurface(
                 SDL_SWSURFACE, width, height,
-                BitsPerPixel, Rmask, Gmask,
-                Bmask,
-                Amask);
+                BitsPerPixel, Rmask, Gmask, Bmask, Amask);
 
             if (glyph == NULL)
                 return DMERR_MALLOC;
 
             if (BitsPerPixel == 8)
-                SDL_SetColors(glyph, pal, 0, DMFONT_NPALETTE);
+                SDL_SetPaletteColors(glyph->format->palette, pal, 0, DMFONT_NPALETTE);
 
             // Read pixel data
             pixels = glyph->pixels;
--- a/tools/64vw.c	Sun May 13 05:59:42 2018 +0300
+++ b/tools/64vw.c	Sun May 13 06:00:50 2018 +0300
@@ -12,7 +12,7 @@
 #include <SDL.h>
 
 
-int    optVFlags = SDL_SWSURFACE | SDL_HWPALETTE;
+int    optVFlags = 0;
 int    optScrWidth, optScrHeight;
 int    optForcedFormat = -1;
 BOOL   optProbeOnly = FALSE;
@@ -72,7 +72,7 @@
             break;
 
         case 2:
-            optVFlags |= SDL_FULLSCREEN;
+            optVFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
             break;
 
         case 3:
@@ -152,18 +152,6 @@
 }
 
 
-BOOL dmInitializeVideo(SDL_Surface **screen)
-{
-    *screen = SDL_SetVideoMode(optScrWidth, optScrHeight, 8, optVFlags | SDL_RESIZABLE);
-    if (*screen == NULL)
-    {
-        dmErrorMsg("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
-        return FALSE;
-    }
-    return TRUE;
-}
-
-
 int dmReadC64Image(const char *filename, const DMC64ImageFormat *forced, const DMC64ImageFormat **fmt, DMC64Image **cimage)
 {
     Uint8 *dataBuf = NULL;
@@ -203,7 +191,10 @@
 
 int main(int argc, char *argv[])
 {
-    SDL_Surface *screen = NULL, *surf = NULL;
+    SDL_Window *window = NULL;
+    SDL_Renderer *renderer = NULL;
+    SDL_Texture *texture = NULL;
+    SDL_Surface *surf = NULL;
     BOOL initSDL = FALSE, exitFlag, needRedraw;
     const DMC64ImageFormat *forced;
     size_t currIndex, prevIndex;
@@ -279,15 +270,26 @@
     }
     initSDL = TRUE;
 
-
-    // Open window/set video mode
-    screen = SDL_SetVideoMode(optScrWidth, optScrHeight, 8, optVFlags | SDL_RESIZABLE);
-    if (screen == NULL)
+    // Open window
+    if ((window = SDL_CreateWindow(dmProgName,
+        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+        optScrWidth, optScrHeight,
+        optVFlags | SDL_WINDOW_RESIZABLE
+        //| SDL_WINDOW_HIDDEN
+        )) == NULL)
     {
-        dmErrorMsg("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
+        dmErrorMsg("Can't create an SDL window: %s\n", SDL_GetError());
         goto exit;
     }
 
+    if ((renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL)
+    {
+        dmErrorMsg("Can't create an SDL renderer: %s\n", SDL_GetError());
+        goto exit;
+    }
+
+//    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
+
     // Start main loop
     currIndex = 0;
     prevIndex = 1;
@@ -342,17 +344,20 @@
                 needRedraw = TRUE;
                 break;
 
-            case SDL_VIDEORESIZE:
-                optScrWidth  = event.resize.w;
-                optScrHeight = event.resize.h;
-                if (!dmInitializeVideo(&screen))
-                    goto exit;
+            case SDL_WINDOWEVENT:
+                switch (event.window.event)
+                {
+                    case SDL_WINDOWEVENT_EXPOSED:
+                        needRedraw = TRUE;
+                        break;
 
-                needRedraw = TRUE;
-                break;
+                    case SDL_WINDOWEVENT_RESIZED:
+                        optScrWidth  = event.window.data1;
+                        optScrHeight = event.window.data2;
 
-            case SDL_VIDEOEXPOSE:
-                needRedraw = TRUE;
+                        needRedraw = TRUE;
+                        break;
+                }
                 break;
 
             case SDL_QUIT:
@@ -415,6 +420,17 @@
                 goto exit;
             }
 
+            SDL_SetPaletteColors(surf->format->palette, (SDL_Color *)dmDefaultC64Palette, 0, C64_NCOLORS);
+
+            if (texture != NULL)
+                SDL_DestroyTexture(texture);
+
+            if ((texture = SDL_CreateTextureFromSurface(renderer, surf)) == NULL)
+            {
+                dmErrorMsg("Could not create texture from surface: %s\n", SDL_GetError());
+                goto exit;
+            }
+
             if (title == NULL)
             {
                 title = dm_strdup_printf("%s - %s [%d / %d]",
@@ -422,7 +438,7 @@
                     currIndex + 1, noptFilenames2);
             }
 
-            SDL_WM_SetCaption(title, dmProgName);
+            SDL_SetWindowTitle(window, title);
             dmFree(title);
 
             needRedraw = TRUE;
@@ -431,23 +447,10 @@
 
         if (needRedraw)
         {
-            float aspect = (float) surf->h / (float) surf->w;
-            int sheight = optScrHeight / aspect;
-            int ypos = (optScrHeight - sheight) / 2;
-
-            if (SDL_MUSTLOCK(screen) != 0 && SDL_LockSurface(screen) != 0)
-            {
-                dmErrorMsg("Can't lock surface.\n");
-                goto exit;
-            }
-
-            dmScaledBlitSurface8to8(surf, 0, ypos, optScrWidth, sheight, screen);
-            SDL_SetColors(screen, (SDL_Color *)dmDefaultC64Palette, 0, C64_NCOLORS);
-
-            if (SDL_MUSTLOCK(screen) != 0)
-                SDL_UnlockSurface(screen);
-
-            SDL_Flip(screen);
+            //SDL_RenderSetLogicalSize(renderer, surf->w, surf->h);
+            SDL_RenderClear(renderer);
+            SDL_RenderCopy(renderer, texture, NULL, NULL);
+            SDL_RenderPresent(renderer);
             needRedraw = FALSE;
         }
 
@@ -458,8 +461,11 @@
     // Cleanup
     dmFree(optFilenames);
 
-    if (screen != NULL)
-        SDL_FreeSurface(screen);
+    if (window != NULL)
+        SDL_DestroyWindow(window);
+
+    if (texture != NULL)
+        SDL_DestroyTexture(texture);
 
     if (surf != NULL)
         SDL_FreeSurface(surf);
--- a/tools/fontconv.c	Sun May 13 05:59:42 2018 +0300
+++ b/tools/fontconv.c	Sun May 13 06:00:50 2018 +0300
@@ -96,7 +96,7 @@
                 optColor.r = colR;
                 optColor.g = colG;
                 optColor.b = colB;
-                optColor.unused = colA;
+                optColor.a = colA;
             }
             break;
 
--- a/tools/ppl.c	Sun May 13 05:59:42 2018 +0300
+++ b/tools/ppl.c	Sun May 13 06:00:50 2018 +0300
@@ -6,6 +6,7 @@
  * Please read file 'COPYING' for information on license and distribution.
  */
 #include "dmlib.h"
+#include <SDL.h>
 #include "libgutil.h"
 
 #include "jss.h"
@@ -23,6 +24,10 @@
 struct
 {
     BOOL exitFlag;
+
+    SDL_Window *window;
+    SDL_Renderer *renderer;
+    SDL_Texture *texture;
     SDL_Surface *screen;
     SDL_Event event;
 
@@ -101,7 +106,7 @@
             break;
 
         case 2:
-            engine.optVFlags |= SDL_FULLSCREEN;
+            engine.optVFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
             break;
 
         case 3:
@@ -189,15 +194,22 @@
 
 BOOL dmInitializeVideo()
 {
+    SDL_DestroyTexture(engine.texture);
     SDL_FreeSurface(engine.screen);
 
-    engine.screen = SDL_SetVideoMode(
-        engine.optScrWidth, engine.optScrHeight, engine.optScrDepth,
-        engine.optVFlags | SDL_RESIZABLE | SDL_SWSURFACE | SDL_HWPALETTE);
+    if ((engine.texture = SDL_CreateTexture(engine.renderer,
+        SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
+        engine.optScrWidth, engine.optScrHeight)) == NULL)
+    {
+        dmErrorMsg("Could not create SDL texture.\n");
+        return FALSE;
+    }
 
-    if (engine.screen == NULL)
+    if ((engine.screen = SDL_CreateRGBSurface(0,
+        engine.optScrWidth, engine.optScrHeight,
+        32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff)) == NULL)
     {
-        dmErrorMsg("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
+        dmErrorMsg("Could not create SDL surface.\n");
         return FALSE;
     }
 
@@ -677,13 +689,31 @@
         muteState = TRUE;
     }
 
-    // Initialize video
+    // Open window
+    if ((engine.window = SDL_CreateWindow(dmProgName,
+        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+        engine.optScrWidth, engine.optScrHeight,
+        engine.optVFlags | SDL_WINDOW_RESIZABLE
+        //| SDL_WINDOW_HIDDEN
+        )) == NULL)
+    {
+        dmErrorMsg("Can't create an SDL window: %s\n", SDL_GetError());
+        goto error_exit;
+    }
+
+    SDL_SetWindowTitle(engine.window, dmProgDesc);
+
+    if ((engine.renderer = SDL_CreateRenderer(engine.window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL)
+    {
+        dmErrorMsg("Can't create an SDL renderer: %s\n", SDL_GetError());
+        goto error_exit;
+    }
+
     if (!dmInitializeVideo())
         goto error_exit;
 
-    SDL_WM_SetCaption(dmProgDesc, dmProgName);
-
-    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+//    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
+//    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
 
     // okay, main loop here ... "play" module and print out info
     SDL_LockAudio();
@@ -694,7 +724,8 @@
     while (!engine.exitFlag)
     {
         currTick = SDL_GetTicks();
-        BOOL force = (currTick - prevTick > 500), updated = FALSE;
+        BOOL force = (currTick - prevTick > 500),
+             updated = FALSE;
 
         while (SDL_PollEvent(&engine.event))
         switch (engine.event.type)
@@ -764,8 +795,8 @@
                         break;
 
                     case SDLK_f:
-                        engine.optVFlags ^= SDL_FULLSCREEN;
-                        if (!dmInitializeVideo())
+                        engine.optVFlags ^= SDL_WINDOW_FULLSCREEN_DESKTOP;
+                        if (SDL_SetWindowFullscreen(engine.window, engine.optVFlags) != 0)
                             goto error_exit;
                         force = TRUE;
                         break;
@@ -776,16 +807,22 @@
 
                 break;
 
-            case SDL_VIDEORESIZE:
-                engine.optScrWidth = engine.event.resize.w;
-                engine.optScrHeight = engine.event.resize.h;
+            case SDL_WINDOWEVENT:
+                switch (engine.event.window.event)
+                {
+                    case SDL_WINDOWEVENT_EXPOSED:
+                        force = TRUE;
+                        break;
 
-                if (!dmInitializeVideo())
-                    goto error_exit;
+                    case SDL_WINDOWEVENT_RESIZED:
+                        engine.optScrWidth  = engine.event.window.data1;
+                        engine.optScrHeight = engine.event.window.data2;
+                        if (!dmInitializeVideo())
+                            goto error_exit;
 
-                break;
-
-            case SDL_VIDEOEXPOSE:
+                        force = TRUE;
+                        break;
+                }
                 break;
 
             case SDL_QUIT:
@@ -809,12 +846,6 @@
         }
 
         // Draw frame
-        if (SDL_MUSTLOCK(engine.screen) != 0 && SDL_LockSurface(engine.screen) != 0)
-        {
-            dmErrorMsg("Can't lock surface.\n");
-            goto error_exit;
-        }
-
         if (force)
         {
             dmClearSurface(engine.screen, col.boxBg);
@@ -856,18 +887,34 @@
 
 #endif
         // Flip screen
-        if (SDL_MUSTLOCK(engine.screen) != 0)
-            SDL_UnlockSurface(engine.screen);
+        if (updated)
+        {
+            SDL_Surface dst;
+            SDL_LockTexture(engine.texture, NULL, &dst.pixels, &dst.pitch);
 
-        if (updated)
-            SDL_Flip(engine.screen);
+            for (int yc = 0; yc < engine.screen->h; yc++)
+            {
+                memcpy(dst.pixels + dst.pitch * yc,
+                    engine.screen->pixels + engine.screen->pitch * yc,
+                    dst.pitch);
+            }
+
+            SDL_UnlockTexture(engine.texture);
+
+            SDL_SetRenderDrawColor(engine.renderer, 0, 0, 0, 255);
+            SDL_RenderClear(engine.renderer);
+            SDL_RenderCopy(engine.renderer, engine.texture, NULL, NULL);
+            SDL_RenderPresent(engine.renderer);
+        }
 
         SDL_Delay(engine.pauseFlag ? 100 : 30);
     }
 
 error_exit:
-    if (engine.screen)
-        SDL_FreeSurface(engine.screen);
+    SDL_DestroyTexture(engine.texture);
+    SDL_DestroyRenderer(engine.renderer);
+    SDL_DestroyWindow(engine.window);
+    SDL_FreeSurface(engine.screen);
 
     dmMsg(0, "Audio shutdown.\n");
     if (audioInit)