added re-initialization of textures after change of renderer
[rocksndiamonds.git] / src / libgame / sdl.c
index 3b0ccc070b7cb72bf050471b454d3f271dbe03de..0759b549fe643dc5ace17a427b8b38f77b6dbd0c 100644 (file)
@@ -98,10 +98,22 @@ 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);
+
+  // copy global animations to render target buffer, if defined
+  if (gfx.draw_global_anim_function != NULL)
+    gfx.draw_global_anim_function();
+
+  // show render target buffer on screen
   SDL_RenderPresent(sdl_renderer);
+
 #else
+
   if (rect)
     SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
   else
@@ -286,6 +298,35 @@ SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
 
 #endif
 
+#if defined(TARGET_SDL2)
+static SDL_Texture *SDLCreateTextureFromSurface(SDL_Surface *surface)
+{
+  SDL_Texture *texture = SDL_CreateTextureFromSurface(sdl_renderer, surface);
+
+  if (texture == NULL)
+    Error(ERR_EXIT, "SDL_CreateTextureFromSurface() failed: %s",
+         SDL_GetError());
+
+  return texture;
+}
+#endif
+
+void SDLCreateBitmapTextures(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        = SDLCreateTextureFromSurface(bitmap->surface);
+  bitmap->texture_masked = SDLCreateTextureFromSurface(bitmap->surface_masked);
+#endif
+}
+
 void SDLInitVideoDisplay(void)
 {
 #if !defined(TARGET_SDL2)
@@ -871,8 +912,19 @@ void SDLFreeBitmapPointers(Bitmap *bitmap)
     SDL_FreeSurface(bitmap->surface);
   if (bitmap->surface_masked)
     SDL_FreeSurface(bitmap->surface_masked);
+
   bitmap->surface = NULL;
   bitmap->surface_masked = NULL;
+
+#if defined(TARGET_SDL2)
+  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 SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
@@ -926,6 +978,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)
 {
@@ -1201,7 +1284,65 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
       }
     }
   }
-  else
+  else if (fade_mode == FADE_MODE_CURTAIN)
+  {
+    float xx;
+    int xx_final;
+    int xx_size = width / 2;
+
+    SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
+#if defined(TARGET_SDL2)
+    SDL_SetSurfaceBlendMode(surface_source, SDL_BLENDMODE_NONE);
+#else
+    SDL_SetAlpha(surface_source, 0, 0);                /* disable alpha blending */
+#endif
+
+    for (xx = 0; xx < xx_size;)
+    {
+      time_last = time_current;
+      time_current = SDL_GetTicks();
+      xx += xx_size * ((float)(time_current - time_last) / fade_delay);
+      xx_final = MIN(MAX(0, xx), xx_size);
+
+      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;
+
+      /* draw new (target) image to screen buffer */
+      SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
+
+      if (xx_final < xx_size)
+      {
+       src_rect.w = xx_size - xx_final;
+       src_rect.h = height;
+
+       /* draw old (source) image to screen buffer (left side) */
+
+       src_rect.x = src_x + xx_final;
+       dst_rect.x = dst_x;
+
+       SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+
+       /* draw old (source) image to screen buffer (right side) */
+
+       src_rect.x = src_x + xx_size;
+       dst_rect.x = dst_x + xx_size + xx_final;
+
+       SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
+      }
+
+      if (draw_border_function != NULL)
+       draw_border_function();
+
+      /* only update the region of the screen that is affected from fading */
+      UpdateScreen(&dst_rect2);
+    }
+  }
+  else         /* fading in, fading out or cross-fading */
   {
     float alpha;
     int alpha_final;