From fd939bfff4d1170cfda9b7df6f81135acfab326f Mon Sep 17 00:00:00 2001
From: FunkyFr3sh <cc.red.alert.1@googlemail.com>
Date: Fri, 18 May 2018 16:18:34 +0200
Subject: [PATCH] choose best renderer automatically

---
 inc/main.h        |  1 +
 src/main.c        | 12 +++++++++---
 src/render.c      | 48 +++++++++++++++++++++++++++++++++--------------
 src/render_soft.c | 17 +++++++++--------
 4 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/inc/main.h b/inc/main.h
index da98fea..be838f6 100644
--- a/inc/main.h
+++ b/inc/main.h
@@ -91,6 +91,7 @@ typedef struct IDirectDrawImpl
     BOOL fakecursorpos;
     BOOL noactivateapp;
     char shader[MAX_PATH];
+    BOOL autorenderer;
     
 } IDirectDrawImpl;
 
diff --git a/src/main.c b/src/main.c
index 100f5cc..b7c7a1c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -978,8 +978,8 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk
             "adjmouse=false\n"
             "; enable C&C video resize hack, auto = auto-detect game, true = forced, false = disabled\n"
             "vhack=false\n"
-            "; switch between OpenGL (opengl) and software (gdi) renderers\n"
-            "renderer=gdi\n"
+            "; switch between OpenGL (opengl) and software (gdi) renderers, (auto) = try opengl, fallback = gdi\n"
+            "renderer=auto\n"
             "; force CPU0 affinity, avoids crashes with RA, *might* have a performance impact\n"
             "singlecpu=true\n"
             "; Window position, -1 = center to screen\n"
@@ -1131,7 +1131,7 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk
         This->vhack = 0;
     }
 
-    GetPrivateProfileStringA("ddraw", "renderer", "gdi", tmp, sizeof(tmp), SettingsIniPath);
+    GetPrivateProfileStringA("ddraw", "renderer", "auto", tmp, sizeof(tmp), SettingsIniPath);
     if(tolower(tmp[0]) == 'd' || tolower(tmp[0]) == 'd')
     {
         printf("DirectDrawCreate: Using dummy renderer\n");
@@ -1142,6 +1142,12 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk
         printf("DirectDrawCreate: Using software renderer\n");
         This->renderer = render_soft_main;
     }
+    else if (tolower(tmp[0]) == 'a')
+    {
+        printf("DirectDrawCreate: Using automatic renderer\n");
+        This->renderer = render_main;
+        This->autorenderer = TRUE;
+    }
     else
     {
         printf("DirectDrawCreate: Using OpenGL renderer\n");
diff --git a/src/render.c b/src/render.c
index d5119d9..b7722f7 100644
--- a/src/render.c
+++ b/src/render.c
@@ -46,13 +46,26 @@ const GLchar *PaletteFragShaderSrc =
 
 
 BOOL detect_cutscene();
+DWORD WINAPI render_soft_main(void);
 
 DWORD WINAPI render_main(void)
 {
     Sleep(500);
 
     HGLRC hRC = wglCreateContext(ddraw->render.hDC);
-    wglMakeCurrent(ddraw->render.hDC, hRC);
+    BOOL madeCurrent = hRC && wglMakeCurrent(ddraw->render.hDC, hRC);
+
+    if (!madeCurrent || (ddraw->autorenderer && glGetError() != GL_NO_ERROR))
+    {
+        if (madeCurrent)
+        {
+            wglMakeCurrent(NULL, NULL);
+            wglDeleteContext(hRC);
+        }
+
+        ddraw->renderer = render_soft_main;
+        return render_soft_main();
+    }
 
     OpenGL_Init();
 
@@ -71,18 +84,19 @@ DWORD WINAPI render_main(void)
     DWORD tick_start = 0;
     DWORD tick_end = 0;
     DWORD frame_len = 0;
+    int maxfps = ddraw->render.maxfps;
 
-    if (ddraw->render.maxfps < 0)
-        ddraw->render.maxfps = ddraw->mode.dmDisplayFrequency;
+    if (maxfps < 0)
+        maxfps = ddraw->mode.dmDisplayFrequency;
 
-    if (ddraw->render.maxfps == 0)
-        ddraw->render.maxfps = 125;
+    if (maxfps == 0)
+        maxfps = 125;
 
-    if (ddraw->render.maxfps >= 1000)
-        ddraw->render.maxfps = 0;
+    if (maxfps >= 1000)
+        maxfps = 0;
 
-    if (ddraw->render.maxfps > 0)
-        frame_len = 1000.0f / ddraw->render.maxfps;
+    if (maxfps > 0)
+        frame_len = 1000.0f / maxfps;
 
     int tex_width = 
         ddraw->width <= 1024 ? 1024 : ddraw->width <= 2048 ? 2048 : ddraw->width <= 4096 ? 4096 : ddraw->width;
@@ -247,11 +261,11 @@ DWORD WINAPI render_main(void)
     }
  
     glBindTexture(GL_TEXTURE_2D, 0);
-
-
     glEnable(GL_TEXTURE_2D);
 
-    while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED)
+    BOOL useOpenGL = !(ddraw->autorenderer && (!paletteConvProgram || glGetError() != GL_NO_ERROR));
+
+    while (useOpenGL && ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED)
     {
 #if _DEBUG
         static DWORD tick_fps = 0;
@@ -269,7 +283,7 @@ DWORD WINAPI render_main(void)
         float scale_w = (float)ddraw->width / tex_width;
         float scale_h = (float)ddraw->height / tex_height;
 
-        if (ddraw->render.maxfps > 0)
+        if (maxfps > 0)
             tick_start = timeGetTime();
 
         EnterCriticalSection(&ddraw->cs);
@@ -414,7 +428,7 @@ DWORD WINAPI render_main(void)
 
         SwapBuffers(ddraw->render.hDC);
 
-        if (ddraw->render.maxfps > 0)
+        if (maxfps > 0)
         {
             tick_end = timeGetTime();
 
@@ -453,5 +467,11 @@ DWORD WINAPI render_main(void)
     wglMakeCurrent(NULL, NULL);
     wglDeleteContext(hRC);
 
+    if (!useOpenGL)
+    {
+        ddraw->renderer = render_soft_main;
+        render_soft_main();
+    }
+
     return 0;
 }
diff --git a/src/render_soft.c b/src/render_soft.c
index fed76c1..7927f31 100644
--- a/src/render_soft.c
+++ b/src/render_soft.c
@@ -70,15 +70,16 @@ DWORD WINAPI render_soft_main(void)
     DWORD tick_start = 0;
     DWORD tick_end = 0;
     DWORD frame_len = 0;
+    int maxfps = ddraw->render.maxfps;
 
-    if(ddraw->render.maxfps < 0)
-        ddraw->render.maxfps = ddraw->mode.dmDisplayFrequency;
+    if(maxfps < 0)
+       maxfps = ddraw->mode.dmDisplayFrequency;
 
-    if (ddraw->render.maxfps >= 1000)
-        ddraw->render.maxfps = 0;
+    if (maxfps >= 1000)
+        maxfps = 0;
 
-    if(ddraw->render.maxfps > 0)
-        frame_len = 1000.0f / ddraw->render.maxfps;
+    if(maxfps > 0)
+        frame_len = 1000.0f / maxfps;
 
     while (ddraw->render.run && WaitForSingleObject(ddraw->render.sem, INFINITE) != WAIT_FAILED)
     {
@@ -95,7 +96,7 @@ DWORD WINAPI render_soft_main(void)
         frame_count++;
 #endif
 
-        if(ddraw->render.maxfps > 0)
+        if(maxfps > 0)
         {
             tick_start = timeGetTime();
         }
@@ -151,7 +152,7 @@ DWORD WINAPI render_soft_main(void)
 
         LeaveCriticalSection(&ddraw->cs);
 
-        if(ddraw->render.maxfps > 0)
+        if(maxfps > 0)
         {
             tick_end = timeGetTime();