rnd-20131228-1-src
[rocksndiamonds.git] / src / libgame / sdl.c
index 65057b61ba0cd221c273ab4283ed6110ef6eb696..a72bdcc0cc80e5c52df9c2267c70f36802e714a5 100644 (file)
 
 /* SDL internal variables */
 #if defined(TARGET_SDL2)
-// static SDL_Window *sdl_window = NULL;
-SDL_Window *sdl_window = NULL;
-// static SDL_Renderer *sdl_renderer = NULL;
+static SDL_Window *sdl_window = NULL;
+static SDL_Renderer *sdl_renderer = NULL;
+static SDL_Texture *sdl_texture = NULL;
+
+#define USE_RENDERER   1
 #endif
 
 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
@@ -42,6 +44,41 @@ static int video_yoffset;
 /* functions from SGE library */
 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
 
+#if defined(TARGET_SDL2)
+static void UpdateScreen(SDL_Rect *rect)
+{
+#if USE_RENDERER
+  SDL_Surface *screen = backbuffer->surface;
+
+#if 1
+  if (rect)
+  {
+    int bytes_x = screen->pitch / video.width;
+    int bytes_y = screen->pitch;
+
+    SDL_UpdateTexture(sdl_texture, rect,
+                     screen->pixels + rect->x * bytes_x + rect->y * bytes_y,
+                     screen->pitch);
+  }
+  else
+  {
+    SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
+  }
+#else
+  SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
+#endif
+  SDL_RenderClear(sdl_renderer);
+  SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
+  SDL_RenderPresent(sdl_renderer);
+#else
+  if (rect)
+    SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
+  else
+    SDL_UpdateWindowSurface(sdl_window);
+#endif
+}
+#endif
+
 static void setFullscreenParameters(char *fullscreen_mode_string)
 {
   struct ScreenModeInfo *fullscreen_mode;
@@ -244,13 +281,21 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
     }
   }
 
+#if 0
   /* set window icon */
   SDLSetWindowIcon(program.sdl_icon_filename);
+#endif
 
   /* open SDL video output device (window or fullscreen mode) */
   if (!SDLSetVideoMode(backbuffer, fullscreen))
     Error(ERR_EXIT, "setting video mode failed");
 
+#if 1
+  /* !!! SDL2 can only set the window icon if the window already exists !!! */
+  /* set window icon */
+  SDLSetWindowIcon(program.sdl_icon_filename);
+#endif
+
   /* set window and icon title */
 #if defined(TARGET_SDL2)
   SDL_SetWindowTitle(sdl_window, program.window_title);
@@ -283,7 +328,8 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
 {
   boolean success = TRUE;
 #if defined(TARGET_SDL2)
-  int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
+  // int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
+  int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
   int surface_flags_window = SURFACE_FLAGS;
 #else
   int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
@@ -316,7 +362,8 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
     {
       new_surface = SDL_GetWindowSurface(sdl_window);
 
-      SDL_UpdateWindowSurface(sdl_window);     // immediately map window
+      // SDL_UpdateWindowSurface(sdl_window);  // immediately map window
+      // UpdateScreen(NULL);   // immediately map window
     }
 #else
     new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
@@ -351,17 +398,88 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
 
     /* switch display to window mode */
 #if defined(TARGET_SDL2)
+
+#if USE_RENDERER
+    float scale_factor = 1.2;
+    int test_fullscreen = 0;
+    int surface_flags = (test_fullscreen ? surface_flags_fullscreen :
+                        surface_flags_window);
+
+    sdl_window = SDL_CreateWindow(program.window_title,
+                                 SDL_WINDOWPOS_CENTERED,
+                                 SDL_WINDOWPOS_CENTERED,
+                                 (int)(scale_factor * video.width),
+                                 (int)(scale_factor * video.height),
+                                 surface_flags);
+
+    if (sdl_window != NULL)
+    {
+      sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
+
+      if (sdl_renderer != NULL)
+      {
+       SDL_RenderSetLogicalSize(sdl_renderer, video.width, video.height);
+       SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+
+       sdl_texture = SDL_CreateTexture(sdl_renderer,
+                                       SDL_PIXELFORMAT_ARGB8888,
+                                       SDL_TEXTUREACCESS_STREAMING,
+                                       video.width, video.height);
+
+       if (sdl_texture != NULL)
+       {
+#if 1
+         // (do not use alpha channel)
+         new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
+                                            0x00FF0000,
+                                            0x0000FF00,
+                                            0x000000FF,
+                                            0x00000000);
+#else
+         // (this uses an alpha channel, which we don't want here)
+         new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
+                                            0x00FF0000,
+                                            0x0000FF00,
+                                            0x000000FF,
+                                            0xFF000000);
+#endif
+
+         printf("::: pitch == %d\n", new_surface->pitch);
+
+         if (new_surface == NULL)
+           Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
+                 SDL_GetError());
+       }
+       else
+       {
+         Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
+       }
+      }
+      else
+      {
+       Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
+      }
+    }
+    else
+    {
+      Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
+    }
+#else
     sdl_window = SDL_CreateWindow(program.window_title,
                                  SDL_WINDOWPOS_CENTERED,
                                  SDL_WINDOWPOS_CENTERED,
                                  video.width, video.height,
                                  surface_flags_window);
+
     if (sdl_window != NULL)
     {
       new_surface = SDL_GetWindowSurface(sdl_window);
 
-      SDL_UpdateWindowSurface(sdl_window);     // immediately map window
+      // SDL_UpdateWindowSurface(sdl_window);  // immediately map window
+      // UpdateScreen(NULL);           // immediately map window
     }
+#endif
+
 #else
     new_surface = SDL_SetVideoMode(video.width, video.height,
                                   video.depth, surface_flags_window);
@@ -384,6 +502,10 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
     }
   }
 
+#if defined(TARGET_SDL2)
+  UpdateScreen(NULL);          // map window
+#endif
+
 #if 1
   SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
 
@@ -463,14 +585,19 @@ void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
   dst_rect.w = width;
   dst_rect.h = height;
 
-  if (src_bitmap != backbuffer || dst_bitmap != window)
+  // if (src_bitmap != backbuffer || dst_bitmap != window)
+  if (!(src_bitmap == backbuffer && dst_bitmap == window))
     SDL_BlitSurface((mask_mode == BLIT_MASKED ?
                     src_bitmap->surface_masked : src_bitmap->surface),
                    &src_rect, real_dst_bitmap->surface, &dst_rect);
 
 #if defined(TARGET_SDL2)
   if (dst_bitmap == window)
-    SDL_UpdateWindowSurface(sdl_window);
+  {
+    // SDL_UpdateWindowSurface(sdl_window);
+    // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
+    UpdateScreen(&dst_rect);
+  }
 #else
   if (dst_bitmap == window)
     SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
@@ -498,7 +625,11 @@ void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
 
 #if defined(TARGET_SDL2)
   if (dst_bitmap == window)
-    SDL_UpdateWindowSurface(sdl_window);
+  {
+    // SDL_UpdateWindowSurface(sdl_window);
+    // SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1);
+    UpdateScreen(&rect);
+  }
 #else
   if (dst_bitmap == window)
     SDL_UpdateRect(backbuffer->surface, x, y, width, height);
@@ -516,6 +647,9 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
   SDL_Surface *surface_screen = backbuffer->surface;
   SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
   SDL_Rect src_rect, dst_rect;
+#if defined(TARGET_SDL2)
+  SDL_Rect dst_rect2;
+#endif
   int src_x = x, src_y = y;
   int dst_x = x, dst_y = y;
   unsigned int time_last, time_current;
@@ -544,6 +678,10 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
   dst_rect.w = width;          /* (ignored) */
   dst_rect.h = height;         /* (ignored) */
 
+#if defined(TARGET_SDL2)
+  dst_rect2 = dst_rect;
+#endif
+
   if (initialization_needed)
   {
 #if defined(TARGET_SDL2)
@@ -739,7 +877,9 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
          draw_border_function();
 
 #if defined(TARGET_SDL2)
-       SDL_UpdateWindowSurface(sdl_window);
+       // SDL_UpdateWindowSurface(sdl_window);
+       // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1);
+       UpdateScreen(&dst_rect2);
 #else
        SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
 #endif
@@ -776,7 +916,9 @@ void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
 #if 1
       /* only update the region of the screen that is affected from fading */
 #if defined(TARGET_SDL2)
-      SDL_UpdateWindowSurface(sdl_window);
+      // SDL_UpdateWindowSurface(sdl_window);
+      // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
+      UpdateScreen(&dst_rect);
 #else
       SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
 #endif