improve video initialization, use more compatible and common format

This commit is contained in:
Ondrej Novak 2025-05-04 13:36:17 +02:00
parent c7b575821c
commit 5643814710
5 changed files with 196 additions and 38 deletions

View file

@ -47,9 +47,9 @@ std::string exception_to_string(const std::exception& e) {
try { try {
std::rethrow_if_nested(e); std::rethrow_if_nested(e);
} catch (const std::exception& nested) { } catch (const std::exception& nested) {
oss << " Reason: " << exception_to_string(nested); oss << "\n\n Reason: " << exception_to_string(nested);
} catch (...) { } catch (...) {
oss << " Reason: unknown exception of crash"; oss << "\n\n Reason: unknown exception of crash";
} }
return std::move(oss).str(); return std::move(oss).str();

View file

@ -41,7 +41,6 @@ char game_display_init(const INI_CONFIG_SECTION *display_section, const char *ti
else cfg.crt_filter = SDLContext::CrtFilterType::autoselect; else cfg.crt_filter = SDLContext::CrtFilterType::autoselect;
cfg.cursor_size = ini_get_int(display_section, "cursor_size", 100)*0.01f; cfg.cursor_size = ini_get_int(display_section, "cursor_size", 100)*0.01f;
cfg.hint_renderer = ini_get_string(display_section, "sdl_renderer_driver", NULL);
screen_pitch = 640; screen_pitch = 640;
get_sdl_global_context().init_video(cfg, title); get_sdl_global_context().init_video(cfg, title);

View file

@ -4,6 +4,7 @@
#include <atomic> #include <atomic>
#include <cassert> #include <cassert>
#include "../platform.h" #include "../platform.h"
#include "../error.h"
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
@ -34,6 +35,9 @@ void SDLContext::SDL_Deleter::operator ()(SDL_Surface* surface) {
void SDLContext::SDL_Deleter::operator ()(SDL_Texture* texture) { void SDLContext::SDL_Deleter::operator ()(SDL_Texture* texture) {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
} }
void SDLContext::SDL_Deleter::operator ()(SDL_PixelFormat* f) {
SDL_FreeFormat(f);
}
void SDLContext::SDL_Audio_Deleter::operator()(SDL_AudioDeviceID x) { void SDLContext::SDL_Audio_Deleter::operator()(SDL_AudioDeviceID x) {
SDL_CloseAudioDevice(x); SDL_CloseAudioDevice(x);
@ -78,6 +82,20 @@ void handle_sdl_error(const char *msg) {
throw std::runtime_error(buff); throw std::runtime_error(buff);
} }
bool isFormatSupported(SDL_Renderer *renderer, Uint32 pixel_format) {
SDL_RendererInfo info;
if (SDL_GetRendererInfo(renderer, &info) != 0) {
handle_sdl_error("Failed to get renderer info");
return false;
}
for (Uint32 i = 0; i < info.num_texture_formats; ++i) {
if (info.texture_formats[i] == pixel_format) {
return true;
}
}
return false;
}
void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** texture, int width, int height, CrtFilterType type) { void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** texture, int width, int height, CrtFilterType type) {
@ -95,6 +113,8 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
default: break; default: break;
} }
if (type == CrtFilterType::scanlines || type == CrtFilterType::scanlines_2) { if (type == CrtFilterType::scanlines || type == CrtFilterType::scanlines_2) {
width = 32; width = 32;
} else { } else {
@ -105,8 +125,11 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
unsigned int mult_of_base = std::max<unsigned int>((height+240)/480,interfer); unsigned int mult_of_base = std::max<unsigned int>((height+240)/480,interfer);
height = height * interfer / mult_of_base; height = height * interfer / mult_of_base;
} }
// Vytvoř novou texturu ve správné velikosti // Vytvoř novou texturu ve správné velikosti
*texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height); *texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!*texture) { if (!*texture) {
type = CrtFilterType::none; type = CrtFilterType::none;
return; //crt filter failed to create, do not use filter return; //crt filter failed to create, do not use filter
@ -126,10 +149,12 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
Uint32* pixelArray = (Uint32*)pixels; Uint32* pixelArray = (Uint32*)pixels;
if (type == CrtFilterType::scanlines) { if (type == CrtFilterType::scanlines) {
Uint32 darkPixel = 0xA0A0A0FF;
Uint32 transparentPixel = 0xFFFFFFC0; Uint32 darkPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xA0, 0xA0, 0xA0, 0xFF);
Uint32 transparentPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0xFF, 0xFF, 0xC0);
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
Uint32 color = ((y & 1)== 0) ? darkPixel : transparentPixel; Uint32 color = ((y & 1)== 0) ? darkPixel : transparentPixel;
@ -141,8 +166,8 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
else if (type == CrtFilterType::scanlines_2) { else if (type == CrtFilterType::scanlines_2) {
Uint32 darkPixel = 0x808080FF; Uint32 darkPixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0x80, 0x80, 0xFF);
Uint32 transparentPixel = 0xFFFFFFE0; Uint32 transparentPixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0xFF, 0xFF, 0xE0);
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
Uint32 color = (y % 3== 2) ? darkPixel : transparentPixel; Uint32 color = (y % 3== 2) ? darkPixel : transparentPixel;
@ -152,10 +177,10 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
} }
} else { } else {
static Uint32 red_pixel = 0xFF8080A0; static Uint32 red_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0xFF, 0x80, 0x80, 0xA0);
static Uint32 green_pixel = 0x80FF80A0; static Uint32 green_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0xFF, 0x80, 0xA0);
static Uint32 blue_pixel = 0x8080FFA0; static Uint32 blue_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x80, 0x80, 0xFF, 0xA0);
static Uint32 dark_pixel = 0x000000C0; static Uint32 dark_pixel = SDL_MapRGBA(_main_pixel_format.get(), 0x0, 0x0, 0x00, 0xA0);
for (int y = 2; y < height; y++) { for (int y = 2; y < height; y++) {
if (type == CrtFilterType::rgb_matrix_2) { if (type == CrtFilterType::rgb_matrix_2) {
for (int x = 2; x < width; x+=3) { for (int x = 2; x < width; x+=3) {
@ -199,6 +224,30 @@ static void crash_sdl_exception() {
abort(); abort();
} }
static int select_best_rendered_driver(int max_texture_width, int max_texture_height, Uint32 texture_format, bool force_software) {
int best_index = -1;
int num_drivers = SDL_GetNumRenderDrivers();
for (int i = 0; i < num_drivers; ++i) {
SDL_RendererInfo info;
if (SDL_GetRenderDriverInfo(i, &info) == 0) {
bool found_format = std::find(info.texture_formats, info.texture_formats + info.num_texture_formats, texture_format) != info.texture_formats + info.num_texture_formats;
if (found_format) {
if (force_software && (info.flags & SDL_RENDERER_SOFTWARE)) {
best_index = i;
break;
}
if (!force_software && (info.flags & SDL_RENDERER_ACCELERATED)) {
if (info.max_texture_width >= max_texture_width &&
info.max_texture_height >= max_texture_height) {
best_index = i;
break;
}
}
}
}
}
return best_index;
}
void SDLContext::init_video(const VideoConfig &config, const char *title) { void SDLContext::init_video(const VideoConfig &config, const char *title) {
static Uint32 update_request_event = SDL_RegisterEvents(1); static Uint32 update_request_event = SDL_RegisterEvents(1);
@ -219,18 +268,16 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
_enable_crt = false; _enable_crt = false;
} }
if (config.hint_renderer) {
SDL_SetHint(SDL_HINT_RENDER_DRIVER, config.hint_renderer);
}
_fullscreen_mode = config.fullscreen; _fullscreen_mode = config.fullscreen;
_mouse_size = config.cursor_size; _mouse_size = config.cursor_size;
std::atomic<bool> done = false; std::atomic<bool> done = false;
std::exception_ptr e; std::exception_ptr e;
std::string_view stage;
_render_thread = std::jthread([&](std::stop_token stp){ _render_thread = std::jthread([&](std::stop_token stp){
bool err = false; bool err = false;
try { try {
stage = "window";
SDL_Window *window = SDL_CreateWindow(title, SDL_Window *window = SDL_CreateWindow(title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0));
@ -239,12 +286,42 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
handle_sdl_error("SDL Error create window"); handle_sdl_error("SDL Error create window");
} }
stage = "renderer";
int rindex = -1;
if (rindex == -1) {
_texture_render_format = SDL_PIXELFORMAT_RGBA8888;
rindex = select_best_rendered_driver(640,480, _texture_render_format, config.composer & SDL_RENDERER_SOFTWARE);
}
if (rindex == -1) {
_texture_render_format = SDL_PIXELFORMAT_ARGB8888;
rindex = select_best_rendered_driver(640,480, _texture_render_format, config.composer & SDL_RENDERER_SOFTWARE);
}
if (rindex == -1){
_texture_render_format = SDL_PIXELFORMAT_ARGB8888;
rindex = select_best_rendered_driver(640,480, _texture_render_format, true);
}
if (rindex == -1){
_texture_render_format = SDL_PIXELFORMAT_RGBA8888;
rindex = select_best_rendered_driver(640,480, _texture_render_format, true);
}
if (rindex == -1) {
throw std::runtime_error("Unsupported graphic driver, (software fallback also failed)");
}
_window.reset(window); _window.reset(window);
SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, config.composer); SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), rindex, config.composer);
if (!renderer) { if (!renderer) {
handle_sdl_error("Failed to create composer"); handle_sdl_error("Failed to create composer");
} }
stage = "pixel format";
_main_pixel_format.reset(SDL_AllocFormat(_texture_render_format));
if (!_main_pixel_format) {
handle_sdl_error("Failed to create texture format");
}
SDL_RendererInfo rinfo; SDL_RendererInfo rinfo;
SDL_GetRendererInfo(renderer, &rinfo); SDL_GetRendererInfo(renderer, &rinfo);
@ -256,20 +333,31 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality);
} }
_renderer.reset(renderer); _renderer.reset(renderer);
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STREAMING, 640, 480);
stage = "main render target";
SDL_Texture *texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480);
if (!texture) { if (!texture) {
handle_sdl_error("Failed to create render target"); handle_sdl_error("Failed to create render target");
} }
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
_texture.reset(texture); _texture.reset(texture);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STREAMING, 640, 480);
stage = "secondary render target";
texture = SDL_CreateTexture(renderer, _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480);
if (!texture) { if (!texture) {
handle_sdl_error("Failed to create second render target"); handle_sdl_error("Failed to create second render target");
} }
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
_texture2.reset(texture); _texture2.reset(texture);
stage = "all done";
_visible_texture = _texture.get(); _visible_texture = _texture.get();
_hidden_texture = _texture2.get(); _hidden_texture = _texture2.get();
} catch (...) { } catch (...) {
@ -301,10 +389,11 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
std::rethrow_exception(e); std::rethrow_exception(e);
} catch (...) { } catch (...) {
std::throw_with_nested( std::throw_with_nested(
std::runtime_error("Oops! The app couldn't start properly (problem during SDL initialization). " std::runtime_error(std::string("Oops! The application couldn't start properly (problem during SDL initialization). Stage: [")
.append(stage).append("]\n\n"
"This may be caused by outdated or missing graphics or audio drivers." "This may be caused by outdated or missing graphics or audio drivers."
"To fix this, please try the following: Restart your computer and try again/" "To fix this, please try the following:\n- Restart your computer and try again\n- "
"Make sure your graphics and sound drivers are up to date.")); "Make sure your graphics and sound drivers are up to date.")));
} }
} }
@ -346,6 +435,75 @@ int SDLContext::adjust_deadzone(int v, short deadzone) {
return 0; return 0;
} }
void SDLContext::update_texture_with_conversion(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
{
SDL_Rect r;
if (rect) {
r = *rect;
} else {
SDL_QueryTexture(texture, nullptr, nullptr, &r.w, &r.h);
r.x = 0;
r.y = 0;
}
converted_pixels.clear();
converted_pixels.resize(r.w * r.h);
switch (_texture_render_format) {
case SDL_PIXELFORMAT_RGBA8888: {
const Uint16* src = static_cast<const Uint16*>(pixels);
auto trg = converted_pixels.data();
for (int y = 0; y < r.h; ++y) {
for (int x = 0; x < r.w; ++x) {
Uint16 pixel = src[x];
Uint32 a = (pixel & 0x8000) ? 0 : 0xFF;
Uint32 r = ((pixel >> 10) & 0x1F);
Uint32 g = ((pixel >> 5) & 0x1F);
Uint32 b = (pixel & 0x1F);
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
if constexpr (std::endian::native == std::endian::little) {
trg[x] = (r << 24) | (g << 16) | (b << 8) | a;
} else {
trg[x] = (r) | (g << 8) | (b << 16) | (a << 24);
}
}
trg += r.w;
src = src + pitch/2;
}
}
break;
case SDL_PIXELFORMAT_ARGB8888: {
const Uint16* src = static_cast<const Uint16*>(pixels);
auto trg = converted_pixels.data();
for (int y = 0; y < r.h; ++y) {
for (int x = 0; x < r.w; ++x) {
Uint16 pixel = src[x];
Uint32 a = (pixel & 0x8000) ? 0 : 0xFF;
Uint32 r = ((pixel >> 10) & 0x1F);
Uint32 g = ((pixel >> 5) & 0x1F);
Uint32 b = (pixel & 0x1F);
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
if constexpr (std::endian::native == std::endian::little) {
trg[x] = (a << 24) | (r << 16) | (g << 8) | b;
} else {
trg[x] = (a) | (r << 8) | (g << 16) | (b << 24);
}
}
trg += r.w;
src = src + pitch/2;
}
}
break;
}
if (SDL_UpdateTexture(texture, &r, converted_pixels.data(), r.w * 4) < 0) {
handle_sdl_error("Failed to update texture");
}
}
static int axis_dynamic(int c) { static int axis_dynamic(int c) {
double f = std::floor(std::pow(std::abs(c)*0.001,2)*0.025); double f = std::floor(std::pow(std::abs(c)*0.001,2)*0.025);
@ -709,19 +867,19 @@ void SDLContext::update_screen(bool force_refresh) {
SDL_Rect r; SDL_Rect r;
pop_item(iter, r); pop_item(iter, r);
std::string_view data = pop_data(iter, r.w*r.h*2); std::string_view data = pop_data(iter, r.w*r.h*2);
if (SDL_UpdateTexture(_texture.get(), &r, data.data(), r.w*2)<0) handle_sdl_error("Update of render target failed"); update_texture_with_conversion(_texture.get(), &r, data.data(), r.w*2);
} }
break; break;
case DisplayRequest::show_mouse_cursor: { case DisplayRequest::show_mouse_cursor: {
SDL_Rect r; SDL_Rect r;
pop_item(iter, r); pop_item(iter, r);
std::string_view data = pop_data(iter, r.w*r.h*2); std::string_view data = pop_data(iter, r.w*r.h*2);
_mouse.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_ARGB1555,SDL_TEXTUREACCESS_STATIC, r.w, r.h)); _mouse.reset(SDL_CreateTexture(_renderer.get(), _texture_render_format,SDL_TEXTUREACCESS_STATIC, r.w, r.h));
if (!_mouse) handle_sdl_error("Failed to create surface for mouse cursor"); if (!_mouse) handle_sdl_error("Failed to create surface for mouse cursor");
SDL_SetTextureBlendMode(_mouse.get(), SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(_mouse.get(), SDL_BLENDMODE_BLEND);
_mouse_rect.w = r.w; _mouse_rect.w = r.w;
_mouse_rect.h = r.h; _mouse_rect.h = r.h;
if (SDL_UpdateTexture(_mouse.get(), NULL, data.data(), r.w*2)<0) handle_sdl_error("Update of mouse cursor failed"); update_texture_with_conversion(_mouse.get(), NULL, data.data(), r.w*2);
} }
break; break;
case DisplayRequest::hide_mouse_cursor: { case DisplayRequest::hide_mouse_cursor: {
@ -758,10 +916,10 @@ void SDLContext::update_screen(bool force_refresh) {
if (iter == _sprites.end()) { if (iter == _sprites.end()) {
iter = _sprites.insert(iter,{id}); iter = _sprites.insert(iter,{id});
} }
iter->_txtr.reset(SDL_CreateTexture(_renderer.get(), SDL_PIXELFORMAT_ARGB1555, SDL_TEXTUREACCESS_STATIC,r.w, r.h)); iter->_txtr.reset(SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STATIC,r.w, r.h));
if (!iter->_txtr) handle_sdl_error("Failed to create compositor sprite"); if (!iter->_txtr) handle_sdl_error("Failed to create compositor sprite");
SDL_SetTextureBlendMode(iter->_txtr.get(), SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(iter->_txtr.get(), SDL_BLENDMODE_BLEND);
if (SDL_UpdateTexture(iter->_txtr.get(), NULL, data.data(), r.w*2)<0) handle_sdl_error("Update of sprite failed"); update_texture_with_conversion(iter->_txtr.get(), NULL, data.data(), r.w*2);
iter->_rect = r; iter->_rect = r;
update_zindex(); update_zindex();
} break; } break;
@ -862,10 +1020,8 @@ void SDLContext::push_update_msg(const SDL_Rect &rc, const uint16_t *data, int p
_display_update_queue.resize(sz+rc.w*rc.h*2); _display_update_queue.resize(sz+rc.w*rc.h*2);
short *trg = reinterpret_cast<short *>(_display_update_queue.data()+sz); short *trg = reinterpret_cast<short *>(_display_update_queue.data()+sz);
for (int yp = 0; yp < rc.h; ++yp) { for (int yp = 0; yp < rc.h; ++yp) {
for (int xp = 0; xp < rc.w; ++xp) { std::copy(data, data+rc.w, trg);
*trg = data[xp] ^ 0x8000; trg += rc.w;
++trg;
}
data += pitch; data += pitch;
} }
} }
@ -1020,7 +1176,7 @@ void put_picture_ex(unsigned short x,unsigned short y,const void *p, unsigned sh
} }
void SDLContext::push_hi_image(const unsigned short *image) { void SDLContext::push_hi_image(const unsigned short *image) {
SDL_Rect rc; SDL_Rect rc = {};
rc.w= image[0]; rc.w= image[0];
rc.h =image[1]; rc.h =image[1];
push_item(rc); push_item(rc);
@ -1030,7 +1186,6 @@ void SDLContext::push_hi_image(const unsigned short *image) {
unsigned short *trg = reinterpret_cast<unsigned short *>(_display_update_queue.data()+sz); unsigned short *trg = reinterpret_cast<unsigned short *>(_display_update_queue.data()+sz);
std::fill(trg, trg+imgsz, 0x8000); std::fill(trg, trg+imgsz, 0x8000);
put_picture_ex(0, 0, image, trg, rc.w); put_picture_ex(0, 0, image, trg, rc.w);
std::transform(trg, trg+imgsz, trg, [](unsigned short &x)->unsigned short {return x ^ 0x8000;});
} }
void SDLContext::show_mouse_cursor(const unsigned short *ms_hi_format, SDL_Point finger) { void SDLContext::show_mouse_cursor(const unsigned short *ms_hi_format, SDL_Point finger) {

View file

@ -33,7 +33,6 @@ public:
CrtFilterType crt_filter; CrtFilterType crt_filter;
int composer; int composer;
const char *scale_quality; const char *scale_quality;
const char *hint_renderer;
bool fullscreen; bool fullscreen;
int aspect_x; int aspect_x;
int aspect_y; int aspect_y;
@ -171,6 +170,7 @@ protected:
void operator()(SDL_Renderer *); void operator()(SDL_Renderer *);
void operator()(SDL_Surface *); void operator()(SDL_Surface *);
void operator()(SDL_Texture *); void operator()(SDL_Texture *);
void operator()(SDL_PixelFormat* f);
}; };
struct BlendTransitionReq { struct BlendTransitionReq {
@ -238,13 +238,16 @@ protected:
std::unique_ptr<SDL_Texture, SDL_Deleter> _texture2; std::unique_ptr<SDL_Texture, SDL_Deleter> _texture2;
std::unique_ptr<SDL_Texture, SDL_Deleter> _crt_effect; std::unique_ptr<SDL_Texture, SDL_Deleter> _crt_effect;
std::unique_ptr<SDL_Texture, SDL_Deleter> _mouse; std::unique_ptr<SDL_Texture, SDL_Deleter> _mouse;
std::unique_ptr<SDL_PixelFormat, SDL_Deleter> _main_pixel_format;
unique_value<SDL_AudioDeviceID, SDL_Audio_Deleter> _audio; unique_value<SDL_AudioDeviceID, SDL_Audio_Deleter> _audio;
SDL_Texture *_visible_texture = nullptr; SDL_Texture *_visible_texture = nullptr;
SDL_Texture *_hidden_texture = nullptr; SDL_Texture *_hidden_texture = nullptr;
uint32_t _texture_render_format = SDL_PIXELFORMAT_ARGB1555;
bool _fullscreen_mode = false; bool _fullscreen_mode = false;
bool _present = false; bool _present = false;
bool _convert_format = false;
std::atomic<bool> _key_control = false; std::atomic<bool> _key_control = false;
std::atomic<bool> _key_shift = false; std::atomic<bool> _key_shift = false;
std::atomic<bool> _key_capslock = false; std::atomic<bool> _key_capslock = false;
@ -253,6 +256,7 @@ protected:
std::vector<char> _display_update_queue; std::vector<char> _display_update_queue;
std::vector<uint32_t> converted_pixels;
using QueueIter = const char *; using QueueIter = const char *;
std::queue<uint16_t> _keyboard_queue; std::queue<uint16_t> _keyboard_queue;
SDL_Rect _mouse_rect; SDL_Rect _mouse_rect;
@ -308,4 +312,8 @@ protected:
void generate_j_event(int button, char up); void generate_j_event(int button, char up);
static int adjust_deadzone(int v, short deadzone); static int adjust_deadzone(int v, short deadzone);
void update_texture_with_conversion(SDL_Texture * texture,
const SDL_Rect * rect,
const void *pixels, int pitch);
}; };

View file

@ -33,10 +33,6 @@
# composer = auto - choose best supported driver # composer = auto - choose best supported driver
# hardware,hw - use hardware for composition # hardware,hw - use hardware for composition
# software,sw - use software for composition # software,sw - use software for composition
# sdl_renderer_driver - help SDL to choose optimal rederer
# direct3d,direct3d11,direct3d12
# opengl,opengles2,opengles
# metal,software
# scale_quality = auto - best for hardware composer, nearest for software comporser # scale_quality = auto - best for hardware composer, nearest for software comporser
# best - best scale quality (SDL = linear) # best - best scale quality (SDL = linear)
# linear - use linear filtering (Direct3D and OpenGL) # linear - use linear filtering (Direct3D and OpenGL)