20 SDL_DisplayMode currentMode;
21 if (SDL_GetCurrentDisplayMode(displayIndex, ¤tMode) != 0) {
26 Uint32 rmask, gmask, bmask, amask;
27 SDL_PixelFormatEnumToMasks(
28 currentMode.format, &bpp, &rmask, &gmask, &bmask, &amask);
31 amask = ~(rmask | gmask | bmask);
41 return {unsigned(
abs(size_[0])), unsigned(
abs(size_[1])), 32,
42 rmask, gmask, bmask, amask};
54 uint32_t r = (((rgba >> 24) & 0xFF) << 16) + 0x8000;
55 uint32_t
g = (((rgba >> 16) & 0xFF) << 16) + 0x8000;
56 uint32_t b = (((rgba >> 8) & 0xFF) << 16) + 0x8000;
57 uint32_t a = (((rgba >> 0) & 0xFF) << 16) + 0x8000;
69 auto [r0, g0, b0, a0] = unpackRGBA(rgba0);
71 return {r0, g0, b0, a0,
74 auto [r1, g1, b1, a1] = unpackRGBA(rgba1);
75 int32_t dr = int32_t(r1 - r0) / int32_t(
length - 1);
76 int32_t dg = int32_t(g1 - g0) / int32_t(
length - 1);
77 int32_t db = int32_t(b1 - b0) / int32_t(
length - 1);
78 int32_t da = int32_t(a1 - a0) / int32_t(
length - 1);
79 return {r0, g0, b0, a0,
104 uint32_t r0, uint32_t g0, uint32_t b0, uint32_t a0,
105 uint32_t r1, uint32_t g1, uint32_t b1, uint32_t a1,
110 uint32_t rb = ((r0 << 8) & 0xffff0000) |
111 ((b0 >> 8) & 0x0000ffff);
112 uint32_t ga = ((g0 << 8) & 0xffff0000) |
113 ((a0 >> 8) & 0x0000ffff);
115 return {rb, ga, 0, 0,
false,
false};
120 int32_t dr = int32_t(r1 - r0) / int32_t(
length - 1);
121 int32_t dg = int32_t(g1 - g0) / int32_t(
length - 1);
122 int32_t db = int32_t(b1 - b0) / int32_t(
length - 1);
123 int32_t da = int32_t(a1 - a0) / int32_t(
length - 1);
135 uint32_t drb = ((uint32_t(dr) << 8) & 0xffff0000) |
136 ((uint32_t(db) >> 8) & 0x0000ffff);
137 uint32_t dga = ((uint32_t(dg) << 8) & 0xffff0000) |
138 ((uint32_t(da) >> 8) & 0x0000ffff);
139 return {rb, ga, drb, dga, subRB, subGA};
143static constexpr uint32_t packRGBA(uint32_t rb, uint32_t ga)
145 return (rb & 0xff00ff00) | ((ga & 0xff00ff00) >> 8);
153static constexpr void gradient(std::span<const uint32_t, 4> rgba, SDL_Surface& surface,
int borderSize)
155 int width = surface.w - 2 * borderSize;
156 int height = surface.h - 2 * borderSize;
157 if ((width <= 0) || (height <= 0))
return;
159 auto [r0, g0, b0, a0, dr02, dg02, db02, da02] = setupInterp1(rgba[0], rgba[2], height);
160 auto [r1, g1, b1, a1, dr13, dg13, db13, da13] = setupInterp1(rgba[1], rgba[3], height);
162 auto* buffer =
static_cast<uint32_t*
>(surface.pixels);
163 buffer += borderSize;
164 buffer += borderSize * (surface.pitch /
sizeof(uint32_t));
165 repeat(height, [&, r0=r0, g0=g0, b0=b0, a0=a0, dr02=dr02, dg02=dg02, db02=db02, da02=da02,
166 r1=r1, g1=g1, b1=b1, a1=a1, dr13=dr13, dg13=dg13, db13=db13, da13=da13] ()
mutable {
167 auto [rb, ga, drb, dga, subRB, subGA] = setupInterp2(r0, g0, b0, a0, r1, g1, b1, a1, width);
174 for (
auto x :
xrange(width)) {
175 buffer[x] = packRGBA(rb, ga);
176 rb += drb; ga += dga;
179 for (
auto x :
xrange(width)) {
180 buffer[x] = packRGBA(rb, ga);
181 rb += drb; ga -= dga;
186 for (
auto x :
xrange(width)) {
187 buffer[x] = packRGBA(rb, ga);
188 rb -= drb; ga += dga;
191 for (
auto x :
xrange(width)) {
192 buffer[x] = packRGBA(rb, ga);
193 rb -= drb; ga -= dga;
198 r0 += dr02; g0 += dg02; b0 += db02; a0 += da02;
199 r1 += dr13; g1 += dg13; b1 += db13; a1 += da13;
200 buffer += (surface.pitch /
sizeof(uint32_t));
207 : texture(loadImage(output, filename))
208 , flipX(false), flipY(false)
215 : texture(loadImage(output, filename))
216 , flipX(scaleFactor < 0.0f), flipY(scaleFactor < 0.0f)
223 : texture(loadImage(output, filename))
224 , flipX(size_[0] < 0), flipY(size_[1] < 0)
230 : flipX(size_[0] < 0), flipY(size_[1] < 0)
232 initSolid(output, size_, rgba, 0, 0);
237 int borderSize, uint32_t borderRGBA)
238 : flipX(size_[0] < 0), flipY(size_[1] < 0)
240 if ((rgba[0] == rgba[1]) &&
241 (rgba[0] == rgba[2]) &&
242 (rgba[0] == rgba[3])) {
243 initSolid (output, size_, rgba[0], borderSize, borderRGBA);
245 initGradient(output, size_, rgba, borderSize, borderRGBA);
250 : texture(toTexture(output, *
image))
251 , flipX(false), flipY(false)
258 checked_cast<SDLOutputSurface&>(output).getSDLRenderer(), &surface));
259 SDL_SetTextureBlendMode(result.get(), SDL_BLENDMODE_BLEND);
260 SDL_QueryTexture(result.get(),
nullptr,
nullptr, &
size[0], &
size[1]);
264SDLTexturePtr SDLImage::loadImage(OutputSurface& output,
const std::string& filename)
266 bool want32bpp =
true;
267 return toTexture(output, *
PNG::load(filename, want32bpp));
271static uint32_t convertColor(
const SDL_PixelFormat& format, uint32_t rgba)
275 narrow_cast<Uint8>((rgba >> 24) & 0xff),
276 narrow_cast<Uint8>((rgba >> 16) & 0xff),
277 narrow_cast<Uint8>((rgba >> 8) & 0xff),
278 narrow_cast<Uint8>((rgba >> 0) & 0xff));
281static void drawBorder(SDL_Surface&
image,
int size, uint32_t rgba)
283 if (
size <= 0)
return;
285 uint32_t color = convertColor(*
image.format, rgba);
286 bool onlyBorder = ((2 *
size) >=
image.w) ||
289 SDL_FillRect(&
image,
nullptr, color);
305 SDL_FillRect(&
image, &rect, color);
308 SDL_FillRect(&
image, &rect, color);
313 SDL_FillRect(&
image, &rect, color);
316 SDL_FillRect(&
image, &rect, color);
320void SDLImage::initSolid(OutputSurface& output,
ivec2 size_, uint32_t rgba,
321 int borderSize, uint32_t borderRGBA)
324 if ((size_[0] == 0) || (size_[1] == 0)) {
332 SDL_FillRect(tmp32.
get(),
nullptr, convertColor(*tmp32->format, rgba));
334 drawBorder(*tmp32, borderSize, borderRGBA);
336 texture = toTexture(output, *tmp32);
339void SDLImage::initGradient(OutputSurface& output,
ivec2 size_, std::span<const uint32_t, 4> rgba_,
340 int borderSize, uint32_t borderRGBA)
343 if ((size_[0] == 0) || (size_[1] == 0)) {
347 std::array<uint32_t, 4> rgba;
360 for (
auto& c : rgba) {
361 c = convertColor(*tmp32->format, c);
363 gradient(rgba, *tmp32, borderSize);
364 drawBorder(*tmp32, borderSize, borderRGBA);
366 texture = toTexture(output, *tmp32);
371 assert(r == 255); (void)r;
372 assert(
g == 255); (void)
g;
373 assert(b == 255); (void)b;
375 if (!texture)
return;
382 auto* renderer = checked_cast<SDLOutputSurface&>(output).getSDLRenderer();
383 SDL_SetTextureAlphaMod(texture.get(), alpha);
384 SDL_Rect dst = {x, y, w, h};
385 SDL_RenderCopy(renderer, texture.get(),
nullptr, &dst);
std::unique_ptr< SDL_Texture, SDLDestroyTexture > SDLTexturePtr
Wrapper around a SDL_Surface.
static void checkSize(gl::ivec2 size)
Performs a sanity check on image size.
A frame buffer where pixels can be written to.
SDLImage(OutputSurface &output, const std::string &filename)
void draw(OutputSurface &output, gl::ivec2 pos, uint8_t r, uint8_t g, uint8_t b, uint8_t alpha) override
constexpr vecN< N, int > trunc(const vecN< N, T > &x)
T length(const vecN< N, T > &x)
SDLSurfacePtr load(const std::string &filename, bool want32bpp)
Load the given PNG file in a SDL_Surface.
This file implemented 3 utility functions:
auto copy(InputRange &&range, OutputIter out)
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
size_t size(std::string_view utf8)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto xrange(T e)