fixed re-initialization of textures after change of renderer
[rocksndiamonds.git] / src / libgame / sdl.c
index 71f6cf171ec796583b48dd40e09ddf05728cdc20..d431aacf29c96c34d73b2a4db489d075608a5640 100644 (file)
@@ -54,6 +54,7 @@ static void UpdateScreen(SDL_Rect *rect)
 {
   static unsigned int update_screen_delay = 0;
   unsigned int update_screen_delay_value = 20;         /* (milliseconds) */
+  SDL_Surface *screen = backbuffer->surface;
 
   if (limit_screen_updates &&
       !DelayReached(&update_screen_delay, update_screen_delay_value))
@@ -78,10 +79,29 @@ static void UpdateScreen(SDL_Rect *rect)
   }
 #endif
 
+#if USE_FINAL_SCREEN_BITMAP
+  if (gfx.final_screen_bitmap != NULL) // may not be initialized yet
+  {
+    // !!! TEST !!!
+    // draw global animations using bitmaps instead of using textures
+    // to prevent texture scaling artefacts (this is potentially slower)
+
+    BlitBitmap(backbuffer, gfx.final_screen_bitmap, 0, 0,
+              gfx.win_xsize, gfx.win_ysize, 0, 0);
+
+    // copy global animations to render target buffer, if defined
+    if (gfx.draw_global_anim_function != NULL)
+      gfx.draw_global_anim_function();
+
+    screen = gfx.final_screen_bitmap->surface;
+
+    // force full window redraw
+    rect = NULL;
+  }
+#endif
+
 #if defined(TARGET_SDL2)
 #if USE_RENDERER
-  SDL_Surface *screen = backbuffer->surface;
-
   if (rect)
   {
     int bytes_x = screen->pitch / video.width;
@@ -98,10 +118,24 @@ static void UpdateScreen(SDL_Rect *rect)
   {
     SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
   }
+
+  // clear render target buffer
   SDL_RenderClear(sdl_renderer);
+
+  // copy backbuffer to render target buffer
   SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
+
+#if !USE_FINAL_SCREEN_BITMAP
+  // copy global animations to render target buffer, if defined
+  if (gfx.draw_global_anim_function != NULL)
+    gfx.draw_global_anim_function();
+#endif
+
+  // show render target buffer on screen
   SDL_RenderPresent(sdl_renderer);
+
 #else
+
   if (rect)
     SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
   else
@@ -110,9 +144,9 @@ static void UpdateScreen(SDL_Rect *rect)
 
 #else  // TARGET_SDL
   if (rect)
-    SDL_UpdateRects(backbuffer->surface, 1, rect);
+    SDL_UpdateRects(screen, 1, rect);
   else
-    SDL_UpdateRect(backbuffer->surface, 0, 0, 0, 0);
+    SDL_UpdateRect(screen, 0, 0, 0, 0);
 #endif
 }
 
@@ -305,11 +339,32 @@ void SDLCreateBitmapTextures(Bitmap *bitmap)
   if (bitmap == NULL)
     return;
 
+  if (bitmap->texture)
+    SDL_DestroyTexture(bitmap->texture);
+  if (bitmap->texture_masked)
+    SDL_DestroyTexture(bitmap->texture_masked);
+
   bitmap->texture        = SDLCreateTextureFromSurface(bitmap->surface);
   bitmap->texture_masked = SDLCreateTextureFromSurface(bitmap->surface_masked);
 #endif
 }
 
+void SDLFreeBitmapTextures(Bitmap *bitmap)
+{
+#if defined(TARGET_SDL2)
+  if (bitmap == NULL)
+    return;
+
+  if (bitmap->texture)
+    SDL_DestroyTexture(bitmap->texture);
+  if (bitmap->texture_masked)
+    SDL_DestroyTexture(bitmap->texture_masked);
+
+  bitmap->texture = NULL;
+  bitmap->texture_masked = NULL;
+#endif
+}
+
 void SDLInitVideoDisplay(void)
 {
 #if !defined(TARGET_SDL2)
@@ -961,6 +1016,37 @@ void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
 #endif
 }
 
+void SDLBlitTexture(Bitmap *bitmap,
+                   int src_x, int src_y, int width, int height,
+                   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;
+
+  texture =
+    (mask_mode == BLIT_MASKED ? bitmap->texture_masked : bitmap->texture);
+
+  if (texture == NULL)
+    return;
+
+  src_rect.x = src_x;
+  src_rect.y = src_y;
+  src_rect.w = width;
+  src_rect.h = height;
+
+  dst_rect.x = dst_x;
+  dst_rect.y = dst_y;
+  dst_rect.w = width;
+  dst_rect.h = height;
+
+  SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect);
+#endif
+#endif
+}
+
 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
                      Uint32 color)
 {
@@ -1326,7 +1412,24 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
     }
   }
 
-  Delay(post_delay);
+  if (post_delay > 0)
+  {
+    unsigned int time_post_delay;
+
+    time_current = SDL_GetTicks();
+    time_post_delay = time_current + post_delay;
+
+    while (time_current < time_post_delay)
+    {
+      // do not wait longer than 10 ms at a time to be able to ...
+      Delay(MIN(10, time_post_delay - time_current));
+
+      // ... continue drawing global animations during post delay
+      UpdateScreen(NULL);
+
+      time_current = SDL_GetTicks();
+    }
+  }
 }
 
 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,