Browse Source

Merge pull request #595 from glebm/menu-convert

Blit: Fix scaled output handling
pull/597/head
Gleb Mazovetskiy 6 years ago committed by GitHub
parent
commit
8ad46a145b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      SourceS/sdl2_to_1_2_backports.h
  2. 4
      SourceX/DiabloUI/art.cpp
  3. 7
      SourceX/DiabloUI/art_draw.cpp
  4. 18
      SourceX/DiabloUI/credits.cpp
  5. 36
      SourceX/display.cpp
  6. 3
      SourceX/display.h
  7. 69
      SourceX/dx.cpp

8
SourceS/sdl2_to_1_2_backports.h

@ -215,6 +215,11 @@ SDL_FreePalette(SDL_Palette *palette)
SDL_free(palette);
}
inline bool SDL_HasColorKey(SDL_Surface *surface)
{
return (surface->flags & SDL_SRCCOLORKEY) != 0;
}
//= Pixel formats
#define SDL_PIXELFORMAT_INDEX8 1
@ -259,7 +264,8 @@ inline void SDLBackport_PixelformatToMask(int pixelformat, Uint32 *flags, Uint32
*/
inline bool SDLBackport_PixelFormatFormatEq(const SDL_PixelFormat *a, const SDL_PixelFormat *b)
{
return a->BitsPerPixel == b->BitsPerPixel && (a->palette != nullptr) == (b->palette != nullptr);
return a->BitsPerPixel == b->BitsPerPixel && (a->palette != nullptr) == (b->palette != nullptr)
&& a->Rmask == b->Rmask && a->Gmask == b->Gmask && a->Bmask == b->Bmask;
}
/**

4
SourceX/DiabloUI/art.cpp

@ -1,4 +1,5 @@
#include "DiabloUI/art.h"
#include "display.h"
namespace dvl {
@ -40,6 +41,8 @@ void LoadArt(const char *pszFile, Art *art, int frames, SDL_Color *pPalette)
art->surface = art_surface;
art->frame_height = height / frames;
ScaleSurfaceToOutput(&art->surface);
}
void LoadMaskedArt(const char *pszFile, Art *art, int frames, int mask)
@ -55,6 +58,7 @@ void LoadArt(Art *art, const BYTE *artData, int w, int h, int frames)
art->surface = SDL_CreateRGBSurfaceWithFormatFrom(
const_cast<BYTE *>(artData), w, h, 8, w, SDL_PIXELFORMAT_INDEX8);
art->frame_height = h / frames;
ScaleSurfaceToOutput(&art->surface);
}
} // namespace dvl

7
SourceX/DiabloUI/art_draw.cpp

@ -1,4 +1,5 @@
#include "DiabloUI/art_draw.h"
#include "display.h"
namespace dvl {
@ -18,11 +19,14 @@ void DrawArt(int screenX, int screenY, Art *art, int nFrame,
static_cast<decltype(SDL_Rect().w)>(art->w()),
static_cast<decltype(SDL_Rect().h)>(art->h())
};
ScaleOutputRect(&src_rect);
if (srcW && srcW < src_rect.w)
src_rect.w = srcW;
if (srcH && srcH < src_rect.h)
src_rect.h = srcH;
SDL_Rect dst_rect = { screenX, screenY, src_rect.w, src_rect.h };
ScaleOutputRect(&dst_rect);
if (art->surface->format->BitsPerPixel == 8 && art->palette_version != pal_surface_palette_version) {
if (SDLC_SetSurfaceColors(art->surface, pal_surface->format->palette) <= -1)
@ -30,7 +34,8 @@ void DrawArt(int screenX, int screenY, Art *art, int nFrame,
art->palette_version = pal_surface_palette_version;
}
Blit(art->surface, &src_rect, &dst_rect);
if (SDL_BlitSurface(art->surface, &src_rect, GetOutputSurface(), &dst_rect) < 0)
ErrSdl();
}
void DrawAnimatedArt(Art *art, int screenX, int screenY) {

18
SourceX/DiabloUI/credits.cpp

@ -95,6 +95,10 @@ CachedLine PrepareLine(std::size_t index)
if (SDL_BlitSurface(text.get(), nullptr, surface.get(), nullptr) <= -1)
ErrSdl();
SDL_Surface *surface_ptr = surface.release();
ScaleSurfaceToOutput(&surface_ptr);
surface.reset(surface_ptr);
}
return CachedLine(index, std::move(surface));
@ -224,7 +228,11 @@ void CreditsRenderer::Render()
while (lines_.back().index + 1 != lines_end)
lines_.push_back(PrepareLine(lines_.back().index + 1));
SDL_SetClipRect(GetOutputSurface(), &VIEWPORT);
SDL_Rect viewport = VIEWPORT;
ScaleOutputRect(&viewport);
SDL_SetClipRect(GetOutputSurface(), &viewport);
// We use unscaled coordinates for calculation throughout.
decltype(SDL_Rect().y) dest_y = VIEWPORT.y - (offset_y - lines_begin * LINE_H);
for (std::size_t i = 0; i < lines_.size(); ++i, dest_y += LINE_H) {
auto &line = lines_[i];
@ -239,8 +247,12 @@ void CreditsRenderer::Render()
if (CREDITS_LINES[line.index][0] == '\t')
dest_x += 40;
SDL_Rect dest_rect = { dest_x, dest_y, line.surface.get()->w, line.surface.get()->h };
Blit(line.surface.get(), nullptr, &dest_rect);
SDL_Rect dst_rect = { dest_x, dest_y, 0, 0 };
ScaleOutputRect(&dst_rect);
dst_rect.w = line.surface.get()->w;
dst_rect.h = line.surface.get()->h;
if (SDL_BlitSurface(line.surface.get(), nullptr, GetOutputSurface(), &dst_rect) < 0)
ErrSdl();
}
SDL_SetClipRect(GetOutputSurface(), nullptr);
}

36
SourceX/display.cpp

@ -171,4 +171,40 @@ void ScaleOutputRect(SDL_Rect *rect)
rect->h = rect->h * surface->h / SCREEN_HEIGHT;
}
#ifdef USE_SDL1
namespace {
SDL_Surface *CreateScaledSurface(SDL_Surface *src)
{
SDL_Rect stretched_rect = { 0, 0, static_cast<Uint16>(src->w), static_cast<Uint16>(src->h) };
ScaleOutputRect(&stretched_rect);
SDL_Surface *stretched = SDL_CreateRGBSurface(
SDL_SWSURFACE, stretched_rect.w, stretched_rect.h, src->format->BitsPerPixel,
src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
if (SDL_HasColorKey(src)) {
SDL_SetColorKey(stretched, SDL_SRCCOLORKEY, src->format->colorkey);
if (src->format->palette != nullptr)
SDL_SetPalette(stretched, SDL_LOGPAL, src->format->palette->colors, 0, src->format->palette->ncolors);
}
if (SDL_SoftStretch((src), nullptr, stretched, &stretched_rect) < 0) {
SDL_FreeSurface(stretched);
ErrSdl();
}
return stretched;
}
} // namespace
#endif // USE_SDL1
void ScaleSurfaceToOutput(SDL_Surface **surface)
{
#ifdef USE_SDL1
if (!OutputRequiresScaling())
return;
SDL_Surface *stretched = CreateScaledSurface(*surface);
SDL_FreeSurface((*surface));
*surface = stretched;
#endif
}
} // namespace dvl

3
SourceX/display.h

@ -28,6 +28,9 @@ bool OutputRequiresScaling();
// Scales rect if necessary.
void ScaleOutputRect(SDL_Rect *rect);
// If the output requires software scaling, replaces the given surface with a scaled one.
void ScaleSurfaceToOutput(SDL_Surface **surface);
// Convert from output coordinates to logical (resolution-independent) coordinates.
template <
typename T,

69
SourceX/dx.cpp

@ -173,40 +173,57 @@ void CreatePalette()
void BltFast(SDL_Rect *src_rect, SDL_Rect *dst_rect)
{
if (OutputRequiresScaling()) {
ScaleOutputRect(dst_rect);
// Convert from 8-bit to 32-bit
SDL_Surface *tmp = SDL_ConvertSurface(pal_surface, GetOutputSurface()->format, 0);
if (SDL_BlitScaled(tmp, src_rect, GetOutputSurface(), dst_rect) <= -1) {
SDL_FreeSurface(tmp);
ErrSdl();
}
SDL_FreeSurface(tmp);
} else {
// Convert from 8-bit to 32-bit
if (SDL_BlitSurface(pal_surface, src_rect, GetOutputSurface(), dst_rect) <= -1) {
ErrSdl();
}
}
Blit(pal_surface, src_rect, dst_rect);
}
void Blit(SDL_Surface *src, SDL_Rect *src_rect, SDL_Rect *dst_rect)
{
if (OutputRequiresScaling()) {
ScaleOutputRect(dst_rect);
// Convert from 8-bit to 32-bit
SDL_Surface *tmp = SDL_ConvertSurface(src, GetOutputSurface()->format, 0);
if (SDL_BlitScaled(tmp, src_rect, GetOutputSurface(), dst_rect) <= -1) {
SDL_FreeSurface(tmp);
SDL_Surface *dst = GetOutputSurface();
#ifndef USE_SDL1
if (SDL_BlitSurface(src, src_rect, dst, dst_rect) < 0)
ErrSdl();
}
SDL_FreeSurface(tmp);
} else {
// Convert from 8-bit to 32-bit
if (SDL_BlitSurface(src, src_rect, GetOutputSurface(), dst_rect) <= -1) {
return;
#else
if (!OutputRequiresScaling()) {
if (SDL_BlitSurface(src, src_rect, dst, dst_rect) < 0)
ErrSdl();
return;
}
if (dst_rect != nullptr) ScaleOutputRect(dst_rect);
// Same pixel format: We can call BlitScaled directly.
if (SDLBackport_PixelFormatFormatEq(src->format, dst->format)) {
if (SDL_BlitScaled(src, src_rect, dst, dst_rect) < 0)
ErrSdl();
return;
}
// If the surface has a color key, we must stretch first and can then call BlitSurface.
if (SDL_HasColorKey(src)) {
SDL_Surface *stretched = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_rect->w, dst_rect->h, src->format->BitsPerPixel,
src->format->Rmask, src->format->Gmask, src->format->BitsPerPixel, src->format->Amask);
SDL_SetColorKey(stretched, SDL_SRCCOLORKEY, src->format->colorkey);
if (src->format->palette != nullptr)
SDL_SetPalette(stretched, SDL_LOGPAL, src->format->palette->colors, 0, src->format->palette->ncolors);
SDL_Rect stretched_rect = { 0, 0, dst_rect->w, dst_rect->h };
if (SDL_SoftStretch(src, src_rect, stretched, &stretched_rect) < 0
|| SDL_BlitSurface(stretched, &stretched_rect, dst, dst_rect) < 0) {
SDL_FreeSurface(stretched);
ErrSdl();
}
SDL_FreeSurface(stretched);
return;
}
// A surface with a non-output pixel format but without a color key needs scaling.
// We can convert the format and then call BlitScaled.
SDL_Surface *converted = SDL_ConvertSurface(src, dst->format, 0);
if (SDL_BlitScaled(converted, src_rect, dst, dst_rect) < 0) {
SDL_FreeSurface(converted);
ErrSdl();
}
SDL_FreeSurface(converted);
#endif
}
/**

Loading…
Cancel
Save