removed support for non-renderer graphics for SDL2 target
[rocksndiamonds.git] / src / libgame / sdl.c
index dc866db69ef25f0ab53bd9e74a05bf5c0aaef5ce..39920c8350fc739fb2a6a473348512ffce4209ff 100644 (file)
 
 /* SDL internal variables */
 #if defined(TARGET_SDL2)
+#define USE_TARGET_TEXTURE             TRUE
+#define USE_TARGET_TEXTURE_ONLY                FALSE
+
 static SDL_Window *sdl_window = NULL;
 static SDL_Renderer *sdl_renderer = NULL;
+#if USE_TARGET_TEXTURE
+static SDL_Texture *sdl_texture_stream = NULL;
+static SDL_Texture *sdl_texture_target = NULL;
+#else
 static SDL_Texture *sdl_texture = NULL;
+#endif
 static boolean fullscreen_enabled = FALSE;
-
-#define USE_RENDERER   TRUE
 #endif
 
 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
@@ -95,7 +101,7 @@ static void UpdateScreen(SDL_Rect *rect)
 
     // copy global masked border to render target buffer, if defined
     if (gfx.draw_global_border_function != NULL)
-      gfx.draw_global_border_function(REDRAW_ALL);
+      gfx.draw_global_border_function(DRAW_BORDER_TO_SCREEN);
 
     // copy global animations to render target buffer, if defined (above border)
     if (gfx.draw_global_anim_function != NULL)
@@ -108,8 +114,15 @@ static void UpdateScreen(SDL_Rect *rect)
   }
 #endif
 
+#if USE_TARGET_TEXTURE
+#if USE_TARGET_TEXTURE_ONLY
+  SDL_Texture *sdl_texture = sdl_texture_target;
+#else
+  SDL_Texture *sdl_texture = sdl_texture_stream;
+#endif
+#endif
+
 #if defined(TARGET_SDL2)
-#if USE_RENDERER
   if (rect)
   {
     int bytes_x = screen->pitch / video.width;
@@ -130,8 +143,16 @@ static void UpdateScreen(SDL_Rect *rect)
   // clear render target buffer
   SDL_RenderClear(sdl_renderer);
 
+#if USE_TARGET_TEXTURE
+  SDL_SetRenderTarget(sdl_renderer, sdl_texture_target);
+
+  // copy backbuffer to render target buffer
+  if (sdl_texture != sdl_texture_target)
+    SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
+#else
   // copy backbuffer to render target buffer
   SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
+#endif
 
 #if !USE_FINAL_SCREEN_BITMAP
   // copy global animations to render target buffer, if defined (below border)
@@ -140,24 +161,21 @@ static void UpdateScreen(SDL_Rect *rect)
 
   // copy global masked border to render target buffer, if defined
   if (gfx.draw_global_border_function != NULL)
-    gfx.draw_global_border_function(REDRAW_ALL);
+    gfx.draw_global_border_function(DRAW_BORDER_TO_SCREEN);
 
   // copy global animations to render target buffer, if defined (above border)
   if (gfx.draw_global_anim_function != NULL)
     gfx.draw_global_anim_function(DRAW_GLOBAL_ANIM_STAGE_2);
 #endif
 
+#if USE_TARGET_TEXTURE
+  SDL_SetRenderTarget(sdl_renderer, NULL);
+  SDL_RenderCopy(sdl_renderer, sdl_texture_target, NULL, NULL);
+#endif
+
   // show render target buffer on screen
   SDL_RenderPresent(sdl_renderer);
 
-#else
-
-  if (rect)
-    SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
-  else
-    SDL_UpdateWindowSurface(sdl_window);
-#endif
-
 #else  // TARGET_SDL
   if (rect)
     SDL_UpdateRects(screen, 1, rect);
@@ -278,15 +296,23 @@ boolean SDLSetNativeSurface(SDL_Surface **surface)
 
 SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
 {
+  SDL_PixelFormat format;
   SDL_Surface *new_surface;
 
   if (surface == NULL)
     return NULL;
 
   if (backbuffer && backbuffer->surface)
-    new_surface = SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
+  {
+    format = *backbuffer->surface->format;
+    format.Amask = surface->format->Amask;     // keep alpha channel
+  }
   else
-    new_surface = SDL_ConvertSurface(surface, surface->format, 0);
+  {
+    format = *surface->format;
+  }
+
+  new_surface = SDL_ConvertSurface(surface, &format, 0);
 
   if (new_surface == NULL)
     Error(ERR_EXIT, "SDL_ConvertSurface() failed: %s", SDL_GetError());
@@ -625,7 +651,6 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
   // store if initial screen mode is fullscreen mode when changing screen size
   video.fullscreen_initial = fullscreen;
 
-#if USE_RENDERER
   float window_scaling_factor = (float)setup.window_scaling_percent / 100;
 #if !USE_DESKTOP_FULLSCREEN
   float screen_scaling_factor = (fullscreen ? 1 : window_scaling_factor);
@@ -640,11 +665,25 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
     (*backbuffer)->surface = NULL;
   }
 
+#if USE_TARGET_TEXTURE
+  if (sdl_texture_stream)
+  {
+    SDL_DestroyTexture(sdl_texture_stream);
+    sdl_texture_stream = NULL;
+  }
+
+  if (sdl_texture_target)
+  {
+    SDL_DestroyTexture(sdl_texture_target);
+    sdl_texture_target = NULL;
+  }
+#else
   if (sdl_texture)
   {
     SDL_DestroyTexture(sdl_texture);
     sdl_texture = NULL;
   }
+#endif
 
   if (!(fullscreen && fullscreen_enabled))
   {
@@ -694,12 +733,29 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
       // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
       SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, setup.window_scaling_quality);
 
+#if USE_TARGET_TEXTURE
+      sdl_texture_stream = SDL_CreateTexture(sdl_renderer,
+                                            SDL_PIXELFORMAT_ARGB8888,
+                                            SDL_TEXTUREACCESS_STREAMING,
+                                            width, height);
+
+      sdl_texture_target = SDL_CreateTexture(sdl_renderer,
+                                            SDL_PIXELFORMAT_ARGB8888,
+                                            SDL_TEXTUREACCESS_TARGET,
+                                            width, height);
+#else
       sdl_texture = SDL_CreateTexture(sdl_renderer,
                                      SDL_PIXELFORMAT_ARGB8888,
                                      SDL_TEXTUREACCESS_STREAMING,
                                      width, height);
+#endif
 
+#if USE_TARGET_TEXTURE
+      if (sdl_texture_stream != NULL &&
+         sdl_texture_target != NULL)
+#else
       if (sdl_texture != NULL)
+#endif
       {
        // use SDL default values for RGB masks and no alpha channel
        new_surface = SDL_CreateRGBSurface(0, width, height, 32, 0,0,0, 0);
@@ -723,21 +779,6 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
     Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
   }
 
-#else
-
-  if (sdl_window)
-    SDL_DestroyWindow(sdl_window);
-
-  sdl_window = SDL_CreateWindow(program.window_title,
-                               SDL_WINDOWPOS_CENTERED,
-                               SDL_WINDOWPOS_CENTERED,
-                               width, height,
-                               surface_flags);
-
-  if (sdl_window != NULL)
-    new_surface = SDL_GetWindowSurface(sdl_window);
-#endif
-
 #else
   new_surface = SDL_SetVideoMode(width, height, video.depth, surface_flags);
 #endif
@@ -893,6 +934,42 @@ void SDLSetWindowScaling(int window_scaling_percent)
 
 void SDLSetWindowScalingQuality(char *window_scaling_quality)
 {
+#if USE_TARGET_TEXTURE
+  SDL_Texture *new_texture;
+
+  if (sdl_texture_stream == NULL ||
+      sdl_texture_target == NULL)
+    return;
+
+  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, window_scaling_quality);
+
+  new_texture = SDL_CreateTexture(sdl_renderer,
+                                 SDL_PIXELFORMAT_ARGB8888,
+                                 SDL_TEXTUREACCESS_STREAMING,
+                                 video.width, video.height);
+
+  if (new_texture != NULL)
+  {
+    SDL_DestroyTexture(sdl_texture_stream);
+
+    sdl_texture_stream = new_texture;
+  }
+
+  new_texture = SDL_CreateTexture(sdl_renderer,
+                                 SDL_PIXELFORMAT_ARGB8888,
+                                 SDL_TEXTUREACCESS_TARGET,
+                                 video.width, video.height);
+
+  if (new_texture != NULL)
+  {
+    SDL_DestroyTexture(sdl_texture_target);
+
+    sdl_texture_target = new_texture;
+  }
+
+  SDLRedrawWindow();
+
+#else
   if (sdl_texture == NULL)
     return;
 
@@ -911,6 +988,7 @@ void SDLSetWindowScalingQuality(char *window_scaling_quality)
 
     SDLRedrawWindow();
   }
+#endif
 
   video.window_scaling_quality = window_scaling_quality;
 }
@@ -1037,7 +1115,6 @@ void SDLBlitTexture(Bitmap *bitmap,
                    int dst_x, int dst_y, int mask_mode)
 {
 #if defined(TARGET_SDL2)
-#if USE_RENDERER
   SDL_Texture *texture;
   SDL_Rect src_rect;
   SDL_Rect dst_rect;
@@ -1060,7 +1137,6 @@ void SDLBlitTexture(Bitmap *bitmap,
 
   SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect);
 #endif
-#endif
 }
 
 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
@@ -1102,10 +1178,9 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
                      int fade_mode, int fade_delay, int post_delay,
                      void (*draw_border_function)(void))
 {
-  static boolean initialization_needed = TRUE;
-  static SDL_Surface *surface_source = NULL;
-  static SDL_Surface *surface_target = NULL;
-  static SDL_Surface *surface_black = NULL;
+  SDL_Surface *surface_source = gfx.fade_bitmap_source->surface;
+  SDL_Surface *surface_target = gfx.fade_bitmap_target->surface;
+  SDL_Surface *surface_black  = gfx.fade_bitmap_black->surface;
   SDL_Surface *surface_screen = backbuffer->surface;
   SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
   SDL_Rect src_rect, dst_rect;
@@ -1121,17 +1196,6 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
   if (draw_border_function == NULL)
     gfx.draw_global_border_function = NULL;
 
-  /* check if screen size has changed */
-  if (surface_source != NULL && (video.width  != surface_source->w ||
-                                video.height != surface_source->h))
-  {
-    SDL_FreeSurface(surface_source);
-    SDL_FreeSurface(surface_target);
-    SDL_FreeSurface(surface_black);
-
-    initialization_needed = TRUE;
-  }
-
   src_rect.x = src_x;
   src_rect.y = src_y;
   src_rect.w = width;
@@ -1147,78 +1211,28 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
 
   dst_rect2 = dst_rect;
 
-  if (initialization_needed)
-  {
-#if defined(TARGET_SDL2)
-    unsigned int flags = 0;
-#else
-    unsigned int flags = SDL_SRCALPHA;
-
-    /* use same surface type as screen surface */
-    if ((surface_screen->flags & SDL_HWSURFACE))
-      flags |= SDL_HWSURFACE;
-    else
-      flags |= SDL_SWSURFACE;
-#endif
-
-    /* create surface for temporary copy of screen buffer (source) */
-    if ((surface_source =
-        SDL_CreateRGBSurface(flags,
-                             video.width,
-                             video.height,
-                             surface_screen->format->BitsPerPixel,
-                             surface_screen->format->Rmask,
-                             surface_screen->format->Gmask,
-                             surface_screen->format->Bmask,
-                             surface_screen->format->Amask)) == NULL)
-      Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
-    /* create surface for cross-fading screen buffer (target) */
-    if ((surface_target =
-        SDL_CreateRGBSurface(flags,
-                             video.width,
-                             video.height,
-                             surface_screen->format->BitsPerPixel,
-                             surface_screen->format->Rmask,
-                             surface_screen->format->Gmask,
-                             surface_screen->format->Bmask,
-                             surface_screen->format->Amask)) == NULL)
-      Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
-    /* create black surface for fading from/to black */
-    if ((surface_black =
-        SDL_CreateRGBSurface(flags,
-                             video.width,
-                             video.height,
-                             surface_screen->format->BitsPerPixel,
-                             surface_screen->format->Rmask,
-                             surface_screen->format->Gmask,
-                             surface_screen->format->Bmask,
-                             surface_screen->format->Amask)) == NULL)
-      Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
-    /* completely fill the surface with black color pixels */
-    SDL_FillRect(surface_black, NULL,
-                SDL_MapRGB(surface_screen->format, 0, 0, 0));
-
-    initialization_needed = FALSE;
-  }
-
   /* copy source and target surfaces to temporary surfaces for fading */
   if (fade_mode & FADE_TYPE_TRANSFORM)
   {
     SDL_BlitSurface(surface_cross,  &src_rect, surface_source, &src_rect);
     SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
+
+    draw_global_border_function(DRAW_BORDER_TO_FADE_SOURCE);
+    draw_global_border_function(DRAW_BORDER_TO_FADE_TARGET);
   }
   else if (fade_mode & FADE_TYPE_FADE_IN)
   {
     SDL_BlitSurface(surface_black,  &src_rect, surface_source, &src_rect);
     SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
+
+    draw_global_border_function(DRAW_BORDER_TO_FADE_TARGET);
   }
   else         /* FADE_TYPE_FADE_OUT */
   {
     SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
     SDL_BlitSurface(surface_black,  &src_rect, surface_target, &src_rect);
+
+    draw_global_border_function(DRAW_BORDER_TO_FADE_SOURCE);
   }
 
   time_current = SDL_GetTicks();
@@ -2462,8 +2476,9 @@ Bitmap *SDLLoadImage(char *filename)
   UPDATE_BUSY_STATE();
 
   /* create native transparent surface for current image */
-  SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
-                 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
+  if (sdl_image_tmp->format->Amask == 0)
+    SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
+                   SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
 
   if ((new_bitmap->surface_masked = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
   {