cleanup of unnecessarily convoluted function call
[rocksndiamonds.git] / src / libgame / sdl.c
index f586bd8baaf59cad189720185aa0b0853622c310..d664eecc01df267ae8a86aff5f04e29cb43abbdc 100644 (file)
@@ -62,13 +62,28 @@ static void FinalizeScreen(int draw_target)
   if (gfx.draw_global_anim_function != NULL)
     gfx.draw_global_anim_function(draw_target, DRAW_GLOBAL_ANIM_STAGE_2);
 
-  // copy tile selection cursor to render target buffer, if defined (above all)
+  // copy tile selection cursor to render target buffer, if defined (part 1)
   if (gfx.draw_tile_cursor_function != NULL)
-    gfx.draw_tile_cursor_function(draw_target);
+    gfx.draw_tile_cursor_function(draw_target, TRUE);
+
+  // copy envelope request to render target buffer, if needed (above all)
+  if (gfx.draw_envelope_request_function != NULL)
+    gfx.draw_envelope_request_function(draw_target);
+
+  // copy tile selection cursor to render target buffer, if defined (part 2)
+  if (gfx.draw_tile_cursor_function != NULL)
+    gfx.draw_tile_cursor_function(draw_target, FALSE);
+
+  // copy global animations to render target buffer, if defined (mouse pointer)
+  if (gfx.draw_global_anim_function != NULL)
+    gfx.draw_global_anim_function(draw_target, DRAW_GLOBAL_ANIM_STAGE_3);
 }
 
 static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay)
 {
+  if (program.headless)
+    return;
+
   static DelayCounter update_screen_delay = { 50 };    // (milliseconds)
   SDL_Surface *screen = backbuffer->surface;
 
@@ -340,7 +355,7 @@ static boolean SDLHasAlpha(SDL_Surface *surface)
   return (blend_mode == SDL_BLENDMODE_BLEND);
 }
 
-void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
+static void SDLSetSurfaceAlpha(SDL_Surface *surface, boolean set, int alpha)
 {
   SDL_BlendMode blend_mode = (set ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
 
@@ -348,6 +363,49 @@ void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
   SDL_SetSurfaceAlphaMod(surface, alpha);
 }
 
+static void SDLSetTextureAlpha(SDL_Texture *texture, boolean set, int alpha)
+{
+  SDL_BlendMode blend_mode = (set ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
+
+  SDL_SetTextureBlendMode(texture, blend_mode);
+  SDL_SetTextureAlphaMod(texture, alpha);
+}
+
+static void SDLSetBitmapAlpha(Bitmap *bitmap, boolean is_texture,
+                             boolean is_masked)
+{
+  int alpha_next_blit = bitmap->alpha_next_blit;
+
+  // alpha value must be requested every time before blitting, if needed
+  bitmap->alpha_next_blit = -1;
+
+  // nothing to do if requested alpha value is already set
+  if (bitmap->alpha[is_texture][is_masked] == alpha_next_blit)
+    return;
+
+  // store requested alpha value for masked/unmasked surface/texture
+  bitmap->alpha[is_texture][is_masked] = alpha_next_blit;
+
+  // set blend mode if bitmap is masked or if alpha value is defined
+  boolean set_blend_mode = (is_masked || alpha_next_blit != -1);
+
+  // if alpha value is undefined, use default (opaque) alpha value
+  if (alpha_next_blit == -1)
+    alpha_next_blit = SDL_ALPHA_OPAQUE;
+
+  if (is_texture)
+    SDLSetTextureAlpha(is_masked ? bitmap->texture_masked : bitmap->texture,
+                      set_blend_mode, alpha_next_blit);
+  else
+    SDLSetSurfaceAlpha(is_masked ? bitmap->surface_masked : bitmap->surface,
+                      set_blend_mode, alpha_next_blit);
+}
+
+void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
+{
+  SDLSetSurfaceAlpha(surface, set, alpha);
+}
+
 const char *SDLGetRendererName(void)
 {
   static SDL_RendererInfo renderer_info;
@@ -357,6 +415,25 @@ const char *SDLGetRendererName(void)
   return renderer_info.name;
 }
 
+static SDL_Surface *SDLGetOpaqueSurface(SDL_Surface *surface)
+{
+  SDL_Surface *new_surface;
+
+  if (surface == NULL)
+    return NULL;
+
+  if ((new_surface = SDLGetNativeSurface(surface)) == NULL)
+    Fail("SDLGetNativeSurface() failed");
+
+  // remove alpha channel from native non-transparent surface, if defined
+  SDLSetAlpha(new_surface, FALSE, 0);
+
+  // remove transparent color from native non-transparent surface, if defined
+  SDL_SetColorKey(new_surface, UNSET_TRANSPARENT_PIXEL, 0);
+
+  return new_surface;
+}
+
 SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
 {
   SDL_PixelFormat format;
@@ -410,6 +487,51 @@ boolean SDLSetNativeSurface(SDL_Surface **surface)
   return TRUE;
 }
 
+SDL_Surface *SDLCreateNativeSurface(int width, int height, int depth)
+{
+  if (program.headless)
+    return NULL;
+
+  SDL_Surface *surface = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0);
+
+  if (surface == NULL)
+    Fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+
+  SDLSetNativeSurface(&surface);
+
+  return surface;
+}
+
+Bitmap *SDLGetBitmapFromSurface_WithMaskedColor(SDL_Surface *surface, int r, int g, int b)
+{
+  int width  = surface->w;
+  int height = surface->h;
+  int depth  = video.default_depth;
+  Bitmap *bitmap = CreateBitmap(width, height, depth);
+
+  // free default surface (not needed anymore)
+  SDL_FreeSurface(bitmap->surface);
+
+  // get native, non-transparent surface from original surface
+  bitmap->surface = SDLGetOpaqueSurface(surface);
+
+  // get native, potentially transparent surface from original surface
+  bitmap->surface_masked = SDLGetNativeSurface(surface);
+
+  // set black pixel to transparent if no alpha channel / transparent color
+  if (!SDLHasAlpha(bitmap->surface_masked) &&
+      !SDLHasColorKey(bitmap->surface_masked))
+    SDL_SetColorKey(bitmap->surface_masked, SET_TRANSPARENT_PIXEL,
+                   SDL_MapRGB(bitmap->surface_masked->format, r, g, b));
+
+  return bitmap;
+}
+
+Bitmap *SDLGetBitmapFromSurface(SDL_Surface *surface)
+{
+  return SDLGetBitmapFromSurface_WithMaskedColor(surface, 0x00, 0x00, 0x00);
+}
+
 static SDL_Texture *SDLCreateTextureFromSurface(SDL_Surface *surface)
 {
   if (program.headless)
@@ -553,6 +675,7 @@ static boolean SDLCreateScreen(boolean fullscreen)
   int screen_height = video.screen_height;
   int surface_flags = (fullscreen ? surface_flags_fullscreen :
                       surface_flags_window);
+  int display_nr = options.display_nr;
 
   // default window size is unscaled
   video.window_width  = screen_width;
@@ -588,15 +711,14 @@ static boolean SDLCreateScreen(boolean fullscreen)
 
     if (sdl_window)
     {
-      SDL_DestroyWindow(sdl_window);
-      sdl_window = NULL;
+      SDL_SetWindowSize(sdl_window, video.window_width, video.window_height);
     }
   }
 
   if (sdl_window == NULL)
     sdl_window = SDL_CreateWindow(program.window_title,
-                                 SDL_WINDOWPOS_CENTERED,
-                                 SDL_WINDOWPOS_CENTERED,
+                                 SDL_WINDOWPOS_CENTERED_DISPLAY(display_nr),
+                                 SDL_WINDOWPOS_CENTERED_DISPLAY(display_nr),
                                  video.window_width,
                                  video.window_height,
                                  surface_flags);
@@ -796,7 +918,8 @@ void SDLSetWindowFullscreen(boolean fullscreen)
   {
     SDLSetWindowScaling(setup.window_scaling_percent);
     SDL_SetWindowPosition(sdl_window,
-                         SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+                         SDL_WINDOWPOS_CENTERED_DISPLAY(options.display_nr),
+                         SDL_WINDOWPOS_CENTERED_DISPLAY(options.display_nr));
 
     video.fullscreen_initial = FALSE;
   }
@@ -921,23 +1044,6 @@ void SDLRedrawWindow(void)
   UpdateScreen_WithoutFrameDelay(NULL);
 }
 
-void SDLCreateBitmapContent(Bitmap *bitmap, int width, int height,
-                           int depth)
-{
-  if (program.headless)
-    return;
-
-  SDL_Surface *surface =
-    SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0);
-
-  if (surface == NULL)
-    Fail("SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
-  SDLSetNativeSurface(&surface);
-
-  bitmap->surface = surface;
-}
-
 void SDLFreeBitmapPointers(Bitmap *bitmap)
 {
   if (bitmap->surface)
@@ -957,6 +1063,25 @@ void SDLFreeBitmapPointers(Bitmap *bitmap)
   bitmap->texture_masked = NULL;
 }
 
+void SDLBlitSurface(SDL_Surface *src_surface, SDL_Surface *dst_surface,
+                   int src_x, int src_y, int width, int height,
+                   int dst_x, int dst_y)
+{
+  SDL_Rect src_rect, dst_rect;
+
+  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_BlitSurface(src_surface, &src_rect, dst_surface, &dst_rect);
+}
+
 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
                 int src_x, int src_y, int width, int height,
                 int dst_x, int dst_y, int mask_mode)
@@ -974,6 +1099,8 @@ void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
   dst_rect.w = width;
   dst_rect.h = height;
 
+  SDLSetBitmapAlpha(src_bitmap, FALSE, mask_mode == BLIT_MASKED);
+
   // if (src_bitmap != backbuffer || dst_bitmap != window)
   if (!(src_bitmap == backbuffer && dst_bitmap == window))
     SDL_BlitSurface((mask_mode == BLIT_MASKED ?
@@ -1008,6 +1135,8 @@ void SDLBlitTexture(Bitmap *bitmap,
   dst_rect.w = width;
   dst_rect.h = height;
 
+  SDLSetBitmapAlpha(bitmap, TRUE, mask_mode == BLIT_MASKED);
+
   SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect);
 }
 
@@ -1381,7 +1510,7 @@ void SDLDrawLines(SDL_Surface *surface, struct XY *points,
          continue;
 
        sge_Line(surface, points[i].x + dx, points[i].y + dy,
-                points[i+1].x + dx, points[i+1].y + dy, color);
+                points[i + 1].x + dx, points[i + 1].y + dy, color);
       }
     }
   }
@@ -1450,14 +1579,14 @@ static void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
       case 1:
       {
        // Assuming 8-bpp
-       *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
+       *((Uint8 *)surface->pixels + y * surface->pitch + x) = color;
       }
       break;
 
       case 2:
       {
        // Probably 15-bpp or 16-bpp
-       *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
+       *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x) = color;
       }
       break;
 
@@ -1468,20 +1597,20 @@ static void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
        int shift;
 
        // Gack - slow, but endian correct
-       pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
+       pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
        shift = surface->format->Rshift;
-       *(pix+shift/8) = color>>shift;
+       *(pix + shift / 8) = color>>shift;
        shift = surface->format->Gshift;
-       *(pix+shift/8) = color>>shift;
+       *(pix + shift / 8) = color>>shift;
        shift = surface->format->Bshift;
-       *(pix+shift/8) = color>>shift;
+       *(pix + shift / 8) = color>>shift;
       }
       break;
 
       case 4:
       {
        // Probably 32-bpp
-       *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
+       *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x) = color;
       }
       break;
     }
@@ -1497,12 +1626,12 @@ static void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
 
 static void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
 {
-  *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
+  *((Uint8 *)surface->pixels + y * surface->pitch + x) = color;
 }
 
 static void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
 {
-  *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
+  *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x) = color;
 }
 
 static void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
@@ -1511,38 +1640,38 @@ static void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
   int shift;
 
   // Gack - slow, but endian correct
-  pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
+  pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
   shift = surface->format->Rshift;
-  *(pix+shift/8) = color>>shift;
+  *(pix + shift / 8) = color>>shift;
   shift = surface->format->Gshift;
-  *(pix+shift/8) = color>>shift;
+  *(pix + shift / 8) = color>>shift;
   shift = surface->format->Bshift;
-  *(pix+shift/8) = color>>shift;
+  *(pix + shift / 8) = color>>shift;
 }
 
 static void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
 {
-  *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
+  *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x) = color;
 }
 
-static void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
+static void _PutPixelX(SDL_Surface *dest, Sint16 x, Sint16 y, Uint32 color)
 {
   switch (dest->format->BytesPerPixel)
   {
     case 1:
-      *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
+      *((Uint8 *)dest->pixels + y * dest->pitch + x) = color;
       break;
 
     case 2:
-      *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
+      *((Uint16 *)dest->pixels + y * dest->pitch / 2 + x) = color;
       break;
 
     case 3:
-      _PutPixel24(dest,x,y,color);
+      _PutPixel24(dest, x, y, color);
       break;
 
     case 4:
-      *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
+      *((Uint32 *)dest->pixels + y * dest->pitch / 4 + x) = color;
       break;
   }
 }
@@ -1580,19 +1709,19 @@ static Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
     switch (dest->format->BytesPerPixel)
     {
       case 1:
-       return y*dest->pitch;
+       return y * dest->pitch;
        break;
 
       case 2:
-       return y*dest->pitch/2;
+       return y * dest->pitch / 2;
        break;
 
       case 3:
-       return y*dest->pitch;
+       return y * dest->pitch;
        break;
 
       case 4:
-       return y*dest->pitch/4;
+       return y * dest->pitch / 4;
        break;
     }
   }
@@ -1628,13 +1757,13 @@ static void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch,
        int shift;
 
        // Gack - slow, but endian correct
-       pix = (Uint8 *)surface->pixels + ypitch + x*3;
+       pix = (Uint8 *)surface->pixels + ypitch + x * 3;
        shift = surface->format->Rshift;
-       *(pix+shift/8) = color>>shift;
+       *(pix + shift / 8) = color>>shift;
        shift = surface->format->Gshift;
-       *(pix+shift/8) = color>>shift;
+       *(pix + shift / 8) = color>>shift;
        shift = surface->format->Bshift;
-       *(pix+shift/8) = color>>shift;
+       *(pix + shift / 8) = color>>shift;
       }
       break;
 
@@ -1902,22 +2031,6 @@ void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
 // quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
 // ----------------------------------------------------------------------------
 
-void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
-                  int width, int height, Uint32 color)
-{
-  int x, y;
-
-  for (y = src_y; y < src_y + height; y++)
-  {
-    for (x = src_x; x < src_x + width; x++)
-    {
-      Uint32 pixel = SDLGetPixel(bitmap, x, y);
-
-      SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
-    }
-  }
-}
-
 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
                          int src_x, int src_y, int width, int height,
                          int dst_x, int dst_y)
@@ -2169,7 +2282,7 @@ static int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
 }
 
 // ----------------------------------------------------------------------------
-// zoomSurface()
+// SDLZoomSurface()
 //
 // Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
 // 'zoomx' and 'zoomy' are scaling factors for width and height.
@@ -2177,7 +2290,7 @@ static int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
 // into a 32bit RGBA format on the fly.
 // ----------------------------------------------------------------------------
 
-static SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
+SDL_Surface *SDLZoomSurface(SDL_Surface *src, int dst_width, int dst_height)
 {
   SDL_Surface *zoom_src = NULL;
   SDL_Surface *zoom_dst = NULL;
@@ -2256,25 +2369,6 @@ static SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
   return zoom_dst;
 }
 
-static SDL_Surface *SDLGetOpaqueSurface(SDL_Surface *surface)
-{
-  SDL_Surface *new_surface;
-
-  if (surface == NULL)
-    return NULL;
-
-  if ((new_surface = SDLGetNativeSurface(surface)) == NULL)
-    Fail("SDLGetNativeSurface() failed");
-
-  // remove alpha channel from native non-transparent surface, if defined
-  SDLSetAlpha(new_surface, FALSE, 0);
-
-  // remove transparent color from native non-transparent surface, if defined
-  SDL_SetColorKey(new_surface, UNSET_TRANSPARENT_PIXEL, 0);
-
-  return new_surface;
-}
-
 Bitmap *SDLZoomBitmap(Bitmap *src_bitmap, int dst_width, int dst_height)
 {
   Bitmap *dst_bitmap = CreateBitmapStruct();
@@ -2288,7 +2382,7 @@ Bitmap *SDLZoomBitmap(Bitmap *src_bitmap, int dst_width, int dst_height)
   dst_bitmap->height = dst_height;
 
   // create zoomed temporary surface from source surface
-  dst_surface = zoomSurface(src_surface, dst_width, dst_height);
+  dst_surface = SDLZoomSurface(src_surface, dst_width, dst_height);
 
   // create native format destination surface from zoomed temporary surface
   SDLSetNativeSurface(&dst_surface);
@@ -2423,8 +2517,10 @@ void SDLOpenAudio(void)
     return;
   }
 
-  if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
-                   AUDIO_NUM_CHANNELS_STEREO,
+  // set audio sample rate for mixer
+  audio.sample_rate = (setup.audio_sample_rate_44100 ? 44100 : 22050);
+
+  if (Mix_OpenAudio(audio.sample_rate, MIX_DEFAULT_FORMAT, AUDIO_NUM_CHANNELS_STEREO,
                    setup.system.audio_fragment_size) < 0)
   {
     Warn("Mix_OpenAudio() failed: %s", SDL_GetError());
@@ -2454,6 +2550,12 @@ void SDLCloseAudio(void)
   SDL_QuitSubSystem(SDL_INIT_AUDIO);
 }
 
+void SDLReopenAudio(void)
+{
+  SDLCloseAudio();
+  SDLOpenAudio();
+}
+
 
 // ============================================================================
 // event functions