X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsdl.c;h=4108b2b531c533825c092df0ceab9fb1fd596d90;hb=refs%2Fheads%2Fmaster-next-major-release;hp=f586bd8baaf59cad189720185aa0b0853622c310;hpb=e89a21e95b3cb84d1515c0fb3378ce902a48c1c8;p=rocksndiamonds.git diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index f586bd8b..d664eecc 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -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