diff options
Diffstat (limited to 'src/osd/modules/render/draw13.cpp')
-rw-r--r-- | src/osd/modules/render/draw13.cpp | 755 |
1 files changed, 485 insertions, 270 deletions
diff --git a/src/osd/modules/render/draw13.cpp b/src/osd/modules/render/draw13.cpp index f99ebf70601..a36ee8a8f52 100644 --- a/src/osd/modules/render/draw13.cpp +++ b/src/osd/modules/render/draw13.cpp @@ -2,7 +2,7 @@ // copyright-holders: Couriersud, Olivier Galibert, R. Belmont //============================================================ // -// draw13.c - SDL 2.0 drawing implementation +// draw13.cpp - SDL 2.0 drawing implementation // // SDLMAME by Olivier Galibert and R. Belmont // @@ -10,24 +10,202 @@ // //============================================================ -// standard C headers -#include <math.h> -#include <stdio.h> +#include "render_module.h" -// MAME headers -#include "emu.h" -#include "options.h" +#include "modules/osdmodule.h" + +#if defined(OSD_SDL) // OSD headers -#include "osdsdl.h" +#include "sdlopts.h" #include "window.h" -#include "draw13.h" +// lib/util +#include "options.h" + +// emu +#include "emucore.h" +#include "render.h" + +// standard SDL headers +#include <SDL2/SDL.h> + +// standard C headers +#include <algorithm> +#include <cmath> +#include <cstdio> +#include <iterator> +#include <list> + + +namespace osd { + +namespace { + +struct quad_setup_data +{ + quad_setup_data() = default; + + void compute(const render_primitive &prim, const int prescale); + + int32_t dudx = 0, dvdx = 0, dudy = 0, dvdy = 0; + int32_t startu = 0, startv = 0; + int32_t rotwidth = 0, rotheight = 0; +}; //============================================================ -// DEBUGGING +// Textures //============================================================ +class renderer_sdl2; +struct copy_info_t; + +/* texture_info holds information about a texture */ +class texture_info +{ +public: + texture_info(renderer_sdl2 *renderer, const render_texinfo &texsource, const quad_setup_data &setup, const uint32_t flags); + ~texture_info(); + + void set_data(const render_texinfo &texsource, const uint32_t flags); + void render_quad(const render_primitive &prim, const int x, const int y); + bool matches(const render_primitive &prim, const quad_setup_data &setup); + + copy_info_t const *compute_size_type(); + + void *m_pixels; // pixels for the texture + int m_pitch; + + copy_info_t const *m_copyinfo; + quad_setup_data m_setup; + + osd_ticks_t m_last_access; + + int raw_width() const { return m_texinfo.width; } + int raw_height() const { return m_texinfo.height; } + + const render_texinfo &texinfo() const { return m_texinfo; } + render_texinfo &texinfo() { return m_texinfo; } + + HashT hash() const { return m_hash; } + uint32_t flags() const { return m_flags; } + +private: + bool is_pixels_owned() const; + + void set_coloralphamode(SDL_Texture *texture_id, const render_color *color); + + Uint32 m_sdl_access; + renderer_sdl2 * m_renderer; + render_texinfo m_texinfo; // copy of the texture info + HashT m_hash; // hash value for the texture (must be >= pointer size) + uint32_t m_flags; // rendering flags + + SDL_Texture * m_texture_id; + bool m_is_rotated; + + int m_format; // texture format + SDL_BlendMode m_sdl_blendmode; +}; + +// inline functions and macros +#include "blit13.ipp" + +//============================================================ +// TEXCOPY FUNCS +//============================================================ + +enum SDL_TEXFORMAT_E +{ + SDL_TEXFORMAT_ARGB32 = 0, + SDL_TEXFORMAT_RGB32, + SDL_TEXFORMAT_RGB32_PALETTED, + SDL_TEXFORMAT_YUY16, + SDL_TEXFORMAT_YUY16_PALETTED, + SDL_TEXFORMAT_PALETTE16, + SDL_TEXFORMAT_RGB15, + SDL_TEXFORMAT_RGB15_PALETTED, + SDL_TEXFORMAT_PALETTE16A, + SDL_TEXFORMAT_PALETTE16_ARGB1555, + SDL_TEXFORMAT_RGB15_ARGB1555, + SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555, + SDL_TEXFORMAT_LAST = SDL_TEXFORMAT_RGB15_PALETTED_ARGB1555 +}; + +struct copy_info_t +{ + int src_fmt; + Uint32 dst_fmt; + const blit_base *blitter; + Uint32 bm_mask; + const char *srcname; + const char *dstname; + /* Statistics */ + mutable uint64_t pixel_count; + mutable int64_t time; + mutable int samples; + mutable int perf; + /* list */ + copy_info_t const *next; +}; + +/* renderer_sdl2 is the information about SDL for the current screen */ +class renderer_sdl2 : public osd_renderer +{ +public: + renderer_sdl2( + osd_window &window, + copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1]); + + virtual ~renderer_sdl2() + { + destroy_all_textures(); + SDL_DestroyRenderer(m_sdl_renderer); + m_sdl_renderer = nullptr; + } + + virtual int create() override; + virtual int draw(const int update) override; + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; + virtual render_primitive_list *get_primitives() override; + + int RendererSupportsFormat(Uint32 format, Uint32 access, const char *sformat); + + SDL_Renderer *m_sdl_renderer; + copy_info_t const *const (&m_blit_info)[SDL_TEXFORMAT_LAST + 1]; + +private: + void render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y); + + texture_info *texture_find(const render_primitive &prim, const quad_setup_data &setup); + texture_info *texture_update(const render_primitive &prim); + + void destroy_all_textures(); + + int32_t m_blittimer; + + std::list<texture_info> m_texlist; // list of active textures + + float m_last_hofs; + float m_last_vofs; + + int m_width; + int m_height; + + osd_dim m_blit_dim; + + struct + { + Uint32 format; + int status; + } fmt_support[30]; + + // Stats + int64_t m_last_blit_time; + int64_t m_last_blit_pixels; +}; + + //============================================================ // CONSTANTS //============================================================ @@ -60,9 +238,12 @@ static inline bool is_transparent(const float &a) // CONSTRUCTOR & DESTRUCTOR //============================================================ -renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags) - : osd_renderer(window, FLAG_NEEDS_OPENGL | extra_flags) +renderer_sdl2::renderer_sdl2( + osd_window &window, + copy_info_t const *const (&blit_info)[SDL_TEXFORMAT_LAST + 1]) + : osd_renderer(window) , m_sdl_renderer(nullptr) + , m_blit_info(blit_info) , m_blittimer(0) , m_last_hofs(0) , m_last_vofs(0) @@ -77,112 +258,8 @@ renderer_sdl2::renderer_sdl2(std::shared_ptr<osd_window> window, int extra_flags fmt_support[i].format = 0; fmt_support[i].status = 0; } - - if (!s_blit_info_initialized) - { - /* On OSX, calling this from drawsdl2_init will - * prohibit fullscreen toggling. It is than not possible - * to toggle from fullscreen to window mode. - */ - expand_copy_info(s_blit_info_default); - s_blit_info_initialized = true; - } } - -//============================================================ -// STATIC VARIABLES -//============================================================ - -#define BM_ALL (UINT32_MAX) -//( SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD) - -#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} -#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} -#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} - -const copy_info_t renderer_sdl2::s_blit_info_default[] = -{ - /* no rotation */ - ENTRY(ARGB32, ARGB8888, argb32_argb32), - ENTRY_LR(ARGB32, RGB888, argb32_rgb32), - /* Entry primarily for directfb */ - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), - ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), - - ENTRY(RGB32, ARGB8888, rgb32_argb32), - ENTRY(RGB32, RGB888, rgb32_rgb32), - - ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), - ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), - - ENTRY(YUY16, UYVY, yuv16_uyvy), - ENTRY(YUY16, YUY2, yuv16_yuy2), - ENTRY(YUY16, YVYU, yuv16_yvyu), - ENTRY(YUY16, ARGB8888, yuv16_argb32), - ENTRY(YUY16, RGB888, yuv16_argb32), - - ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), - ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), - ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), - ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), - ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), - - ENTRY(PALETTE16, ARGB8888, pal16_argb32), - ENTRY(PALETTE16, RGB888, pal16_argb32), - - ENTRY(RGB15, RGB555, rgb15_rgb555), - ENTRY(RGB15, ARGB1555, rgb15_argb1555), - ENTRY(RGB15, ARGB8888, rgb15_argb32), - ENTRY(RGB15, RGB888, rgb15_argb32), - - ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), - ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), - - ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), - ENTRY(PALETTE16A, RGB888, pal16a_rgb32), - - /* rotation */ - ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), - ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), - /* Entry primarily for directfb */ - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), - ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), - - ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), - ENTRY(RGB32, RGB888, rot_argb32_argb32), - - ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), - ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), - - ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), - ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), - - ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), - ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), - - ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), - ENTRY(PALETTE16, RGB888, rot_pal16_argb32), - - ENTRY(RGB15, RGB555, rot_rgb15_argb1555), - ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), - ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), - ENTRY(RGB15, RGB888, rot_rgb15_argb32), - - ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), - ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), - - ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), - ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), - -{ -1 }, -}; - -copy_info_t* renderer_sdl2::s_blit_info[SDL_TEXFORMAT_LAST+1] = { nullptr }; -bool renderer_sdl2::s_blit_info_initialized = false; - //============================================================ // INLINES //============================================================ @@ -277,7 +354,7 @@ void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &p if (texture) { - copy_info_t *copyinfo = texture->m_copyinfo; + copy_info_t const *copyinfo = texture->m_copyinfo; copyinfo->time -= osd_ticks(); texture->render_quad(prim, x, y); copyinfo->time += osd_ticks(); @@ -288,7 +365,7 @@ void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &p copyinfo->time += (m_last_blit_time * (int64_t) (texture->raw_width() * texture->raw_height())) / (int64_t) m_last_blit_pixels; } copyinfo->samples++; - copyinfo->perf = ( texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->m_copyinfo->time; + copyinfo->perf = (texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / std::max<int64_t>(texture->m_copyinfo->time, 1); } else { @@ -329,59 +406,6 @@ int renderer_sdl2::RendererSupportsFormat(Uint32 format, Uint32 access, const ch return 0; } -//============================================================ -// drawsdl_init -//============================================================ - -void renderer_sdl2::add_list(copy_info_t **head, const copy_info_t *element, Uint32 bm) -{ - copy_info_t *newci = global_alloc(copy_info_t); - *newci = *element; - - newci->bm_mask = bm; - newci->next = *head; - *head = newci; -} - -void renderer_sdl2::expand_copy_info(const copy_info_t *list) -{ - for (const copy_info_t *bi = list; bi->src_fmt != -1; bi++) - { - if (bi->bm_mask == BM_ALL) - { - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_NONE); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_ADD); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_MOD); - add_list(&s_blit_info[bi->src_fmt], bi, SDL_BLENDMODE_BLEND); - } - else - { - add_list(&s_blit_info[bi->src_fmt], bi, bi->bm_mask); - } - } -} - -// FIXME: machine only used to access options. -void renderer_sdl2::init(running_machine &machine) -{ - osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); - -#if USE_OPENGL - // Load the GL library now - else MT will fail - const char *stemp = downcast<sdl_options &>(machine.options()).gl_lib(); -#else - const char *stemp = nullptr; -#endif - if (stemp != nullptr && strcmp(stemp, OSDOPTVAL_AUTO) == 0) - stemp = nullptr; - - // No fatalerror here since not all video drivers support GL ! - if (SDL_GL_LoadLibrary(stemp) != 0) // Load library (default for e==nullptr - osd_printf_warning("Warning: Unable to load opengl library: %s\n", stemp ? stemp : "<default>"); - else - osd_printf_verbose("Loaded opengl shared library: %s\n", stemp ? stemp : "<default>"); -} - //============================================================ // sdl_info::create @@ -434,12 +458,10 @@ int renderer_sdl2::create() SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); } - auto win = assert_window(); - if (video_config.waitvsync) - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); else - m_sdl_renderer = SDL_CreateRenderer(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window(), -1, SDL_RENDERER_ACCELERATED); + m_sdl_renderer = SDL_CreateRenderer(dynamic_cast<sdl_window_info &>(window()).platform_window(), -1, SDL_RENDERER_ACCELERATED); if (!m_sdl_renderer) { @@ -483,18 +505,14 @@ int renderer_sdl2::xy_to_render_target(int x, int y, int *xt, int *yt) void renderer_sdl2::destroy_all_textures() { - auto win = assert_window(); - if (win == nullptr) - return; - - if(win->m_primlist) + if (window().m_primlist) { - win->m_primlist->acquire_lock(); - m_texlist.reset(); - win->m_primlist->release_lock(); + window().m_primlist->acquire_lock(); + m_texlist.clear(); + window().m_primlist->release_lock(); } else - m_texlist.reset(); + m_texlist.clear(); } //============================================================ @@ -507,13 +525,7 @@ int renderer_sdl2::draw(int update) float vofs, hofs; int blit_pixels = 0; - if (video_config.novideo) - { - return 0; - } - - auto win = assert_window(); - osd_dim wdim = win->get_size(); + osd_dim wdim = window().get_size(); if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) { @@ -560,10 +572,10 @@ int renderer_sdl2::draw(int update) m_last_hofs = hofs; m_last_vofs = vofs; - win->m_primlist->acquire_lock(); + window().m_primlist->acquire_lock(); // now draw - for (render_primitive &prim : *win->m_primlist) + for (render_primitive &prim : *window().m_primlist) { Uint8 sr, sg, sb, sa; @@ -593,7 +605,7 @@ int renderer_sdl2::draw(int update) } } - win->m_primlist->release_lock(); + window().m_primlist->release_lock(); m_last_blit_pixels = blit_pixels; m_last_blit_time = -osd_ticks(); @@ -612,22 +624,23 @@ int renderer_sdl2::draw(int update) // texture_compute_size and type //============================================================ -copy_info_t *texture_info::compute_size_type() +copy_info_t const *texture_info::compute_size_type() { - copy_info_t *result = nullptr; + copy_info_t const *result = nullptr; int maxperf = 0; - for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next) + for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next) { - if ((m_is_rotated == bi->blitter->m_is_rot) - && (m_sdl_blendmode == bi->bm_mask)) + if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask)) { if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname)) { - int perf = bi->perf; + int const perf = bi->perf; if (perf == 0) + { return bi; - else if (perf > (maxperf * 102) / 100) + } + else if (perf > ((maxperf * 102) / 100)) { result = bi; maxperf = perf; @@ -639,23 +652,21 @@ copy_info_t *texture_info::compute_size_type() if (result) return result; - /* try last resort handlers */ - for (copy_info_t *bi = renderer_sdl2::s_blit_info[m_format]; bi != nullptr; bi = bi->next) + // try last resort handlers + for (copy_info_t const *bi = m_renderer->m_blit_info[m_format]; bi != nullptr; bi = bi->next) { - if ((m_is_rotated == bi->blitter->m_is_rot) - && (m_sdl_blendmode == bi->bm_mask)) + if ((m_is_rotated == bi->blitter->m_is_rot) && (m_sdl_blendmode == bi->bm_mask)) if (m_renderer->RendererSupportsFormat(bi->dst_fmt, m_sdl_access, bi->dstname)) return bi; } - //FIXME: crash implement a -do nothing handler */ + //FIXME: crash implement a -do nothing handler return nullptr; } -// FIXME: bool texture_info::is_pixels_owned() const -{ // do we own / allocated it ? - return ((m_sdl_access == SDL_TEXTUREACCESS_STATIC) - && (m_copyinfo->blitter->m_is_passthrough)); +{ + // do we own / allocated it ? + return (m_sdl_access == SDL_TEXTUREACCESS_STATIC) && !m_copyinfo->blitter->m_is_passthrough; } //============================================================ @@ -745,12 +756,11 @@ texture_info::texture_info(renderer_sdl2 *renderer, const render_texinfo &texsou m_pixels = malloc(m_setup.rotwidth * m_setup.rotheight * m_copyinfo->blitter->m_dest_bpp); } m_last_access = osd_ticks(); - } texture_info::~texture_info() { - if ( is_pixels_owned() && (m_pixels != nullptr) ) + if (is_pixels_owned() && m_pixels) free(m_pixels); SDL_DestroyTexture(m_texture_id); } @@ -764,7 +774,7 @@ void texture_info::set_data(const render_texinfo &texsource, const uint32_t flag m_copyinfo->time -= osd_ticks(); if (m_sdl_access == SDL_TEXTUREACCESS_STATIC) { - if ( m_copyinfo->blitter->m_is_passthrough ) + if (m_copyinfo->blitter->m_is_passthrough) { m_pixels = texsource.base; m_pitch = m_texinfo.rowpixels * m_copyinfo->blitter->m_dest_bpp; @@ -778,11 +788,11 @@ void texture_info::set_data(const render_texinfo &texsource, const uint32_t flag } else { - SDL_LockTexture(m_texture_id, nullptr, (void **) &m_pixels, &m_pitch); + SDL_LockTexture(m_texture_id, nullptr, (void **)&m_pixels, &m_pitch); if ( m_copyinfo->blitter->m_is_passthrough ) { - uint8_t *src = (uint8_t *) texsource.base; - uint8_t *dst = (uint8_t *) m_pixels; + const uint8_t *src = (uint8_t *)texsource.base; + uint8_t *dst = (uint8_t *)m_pixels; int spitch = texsource.rowpixels * m_copyinfo->blitter->m_dest_bpp; int num = texsource.width * m_copyinfo->blitter->m_dest_bpp; int h = texsource.height; @@ -868,64 +878,38 @@ void quad_setup_data::compute(const render_primitive &prim, const int prescale) texture_info *renderer_sdl2::texture_find(const render_primitive &prim, const quad_setup_data &setup) { - HashT texhash = texture_compute_hash(prim.texture, prim.flags); - texture_info *texture; - osd_ticks_t now = osd_ticks(); + const HashT texhash = texture_compute_hash(prim.texture, prim.flags); + const osd_ticks_t now = osd_ticks(); // find a match - for (texture = m_texlist.first(); texture != nullptr; ) - if (texture->hash() == texhash && - texture->matches(prim, setup)) + for (auto texture = m_texlist.begin(); texture != m_texlist.end(); ) + { + if ((texture->hash() == texhash) && texture->matches(prim, setup)) { - /* would we choose another blitter based on performance ? */ + // would we choose another blitter based on performance? if ((texture->m_copyinfo->samples & 0x7f) == 0x7f) { if (texture->m_copyinfo != texture->compute_size_type()) return nullptr; } texture->m_last_access = now; - return texture; + return &*texture; } else { - /* free resources not needed any longer? */ - texture_info *expire = texture; - texture = texture->next(); - if (now - expire->m_last_access > osd_ticks_per_second()) - m_texlist.remove(*expire); + // free resources not needed any longer? + if ((now - texture->m_last_access) > osd_ticks_per_second()) + texture = m_texlist.erase(texture); + else + ++texture; } + } // nothing found return nullptr; } //============================================================ -// exit -//============================================================ - -void renderer_sdl2::exit() -{ - if (s_blit_info_initialized) - { - for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++) - { - for (copy_info_t *bi = s_blit_info[i]; bi != nullptr; ) - { - if (bi->pixel_count) - osd_printf_verbose("%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", bi->srcname, bi->dstname, - bi->blitter->m_is_rot ? "rot" : "norot", bi->bm_mask, bi->samples, - (int) bi->perf); - copy_info_t *freeme = bi; - bi = bi->next; - global_free(freeme); - } - s_blit_info[i] = nullptr; - } - s_blit_info_initialized = false; - } -} - -//============================================================ // texture_update //============================================================ @@ -934,22 +918,20 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim) quad_setup_data setup; texture_info *texture; - auto win = assert_window(); - setup.compute(prim, win->prescale()); + setup.compute(prim, window().prescale()); texture = texture_find(prim, setup); // if we didn't find one, create a new texture - if (texture == nullptr && prim.texture.base != nullptr) + if (!texture && prim.texture.base) { - texture = global_alloc(texture_info(this, prim.texture, setup, prim.flags)); - /* add us to the texture list */ - m_texlist.prepend(*texture); + // add us to the texture list + texture = &m_texlist.emplace_front(this, prim.texture, setup, prim.flags); } - if (texture != nullptr) + if (texture) { - if (prim.texture.base != nullptr && texture->texinfo().seqid != prim.texture.seqid) + if (prim.texture.base && (texture->texinfo().seqid != prim.texture.seqid)) { texture->texinfo().seqid = prim.texture.seqid; // if we found it, but with a different seqid, copy the data @@ -962,16 +944,249 @@ texture_info * renderer_sdl2::texture_update(const render_primitive &prim) render_primitive_list *renderer_sdl2::get_primitives() { - auto win = assert_window(); - if (win == nullptr) - return nullptr; - - osd_dim nd = win->get_size(); + osd_dim nd = window().get_size(); if (nd != m_blit_dim) { m_blit_dim = nd; notify_changed(); } - win->target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), win->pixel_aspect()); - return &win->target()->get_primitives(); + window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().pixel_aspect()); + return &window().target()->get_primitives(); +} + + +class video_sdl2 : public osd_module, public render_module +{ +public: + video_sdl2() + : osd_module(OSD_RENDERER_PROVIDER, "accel") + , m_blit_info_initialized(false) + , m_gllib_loaded(false) + { + std::fill(std::begin(m_blit_info), std::end(m_blit_info), nullptr); + } + ~video_sdl2() + { + free_copy_info(); + } + + virtual int init(osd_interface &osd, osd_options const &options) override; + virtual void exit() override { free_copy_info(); } + + virtual std::unique_ptr<osd_renderer> create(osd_window &window) override; + +protected: + virtual unsigned flags() const override { return FLAG_INTERACTIVE | FLAG_SDL_NEEDS_OPENGL; } + +private: + static inline constexpr Uint32 BM_ALL = UINT32_MAX; // SDL_BLENDMODE_MASK | SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD + + void expand_copy_info(); + void free_copy_info(); + + static void add_list(copy_info_t const *&head, copy_info_t const &element, Uint32 bm); + + copy_info_t const *m_blit_info[SDL_TEXFORMAT_LAST + 1]; + bool m_blit_info_initialized; + bool m_gllib_loaded; + + static copy_info_t const s_blit_info_default[]; +}; + +int video_sdl2::init(osd_interface &osd, osd_options const &options) +{ + osd_printf_verbose("Using SDL native texturing driver (SDL 2.0+)\n"); + + // Load the GL library now - else MT will fail + char const *libname = nullptr; +#if USE_OPENGL + libname = dynamic_cast<sdl_options const &>(options).gl_lib(); + if (libname && (!*libname || !std::strcmp(libname, OSDOPTVAL_AUTO))) + libname = nullptr; +#endif + + if (!m_gllib_loaded) + { + // No fatalerror here since not all video drivers support GL! + if (SDL_GL_LoadLibrary(libname) != 0) + { + osd_printf_error("Unable to load OpenGL shared library: %s\n", libname ? libname : "<default>"); + m_gllib_loaded = true; + } + else + { + osd_printf_verbose("Loaded OpenGL shared library: %s\n", libname ? libname : "<default>"); + } + } + + return 0; +} + +std::unique_ptr<osd_renderer> video_sdl2::create(osd_window &window) +{ + if (!m_blit_info_initialized) + { + // On macOS, calling this from drawsdl2_init will prohibit fullscreen toggling. + // It is than not possible to toggle from fullscreen to window mode. + expand_copy_info(); + m_blit_info_initialized = true; + } + + return std::make_unique<renderer_sdl2>(window, m_blit_info); +} + +void video_sdl2::expand_copy_info() +{ + for (const copy_info_t *bi = s_blit_info_default; bi->src_fmt != -1; bi++) + { + if (bi->bm_mask == BM_ALL) + { + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_NONE); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_ADD); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_MOD); + add_list(m_blit_info[bi->src_fmt], *bi, SDL_BLENDMODE_BLEND); + } + else + { + add_list(m_blit_info[bi->src_fmt], *bi, bi->bm_mask); + } + } +} + +void video_sdl2::free_copy_info() +{ + if (m_blit_info_initialized) + { + for (int i = 0; i <= SDL_TEXFORMAT_LAST; i++) + { + for (copy_info_t const *bi = m_blit_info[i]; bi != nullptr; ) + { + if (bi->pixel_count) + { + osd_printf_verbose( + "%s -> %s %s blendmode 0x%02x, %d samples: %d KPixel/sec\n", + bi->srcname, + bi->dstname, + bi->blitter->m_is_rot ? "rot" : "norot", + bi->bm_mask, + bi->samples, + bi->perf); + } + delete std::exchange(bi, bi->next); + } + m_blit_info[i] = nullptr; + } + m_blit_info_initialized = false; + } +} + +void video_sdl2::add_list(copy_info_t const *&head, copy_info_t const &element, Uint32 bm) +{ + copy_info_t *const newci = new copy_info_t(element); + + newci->bm_mask = bm; + newci->next = head; + head = newci; } + + +//============================================================ +// STATIC VARIABLES +//============================================================ + +#define ENTRY(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, 0} +#define ENTRY_BM(a,b,f,bm) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, bm, #a, #b, 0, 0, 0, 0} +#define ENTRY_LR(a,b,f) { SDL_TEXFORMAT_ ## a, SDL_PIXELFORMAT_ ## b, &texcopy_ ## f, BM_ALL, #a, #b, 0, 0, 0, -1} + +copy_info_t const video_sdl2::s_blit_info_default[] = +{ + /* no rotation */ + ENTRY(ARGB32, ARGB8888, argb32_argb32), + ENTRY_LR(ARGB32, RGB888, argb32_rgb32), + /* Entry primarily for directfb */ + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_ADD), + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_MOD), + ENTRY_BM(ARGB32, RGB888, argb32_rgb32, SDL_BLENDMODE_NONE), + + ENTRY(RGB32, ARGB8888, rgb32_argb32), + ENTRY(RGB32, RGB888, rgb32_rgb32), + + ENTRY(RGB32_PALETTED, ARGB8888, rgb32pal_argb32), + ENTRY(RGB32_PALETTED, RGB888, rgb32pal_argb32), + + ENTRY(YUY16, UYVY, yuv16_uyvy), + ENTRY(YUY16, YUY2, yuv16_yuy2), + ENTRY(YUY16, YVYU, yuv16_yvyu), + ENTRY(YUY16, ARGB8888, yuv16_argb32), + ENTRY(YUY16, RGB888, yuv16_argb32), + + ENTRY(YUY16_PALETTED, UYVY, yuv16pal_uyvy), + ENTRY(YUY16_PALETTED, YUY2, yuv16pal_yuy2), + ENTRY(YUY16_PALETTED, YVYU, yuv16pal_yvyu), + ENTRY(YUY16_PALETTED, ARGB8888, yuv16pal_argb32), + ENTRY(YUY16_PALETTED, RGB888, yuv16pal_argb32), + + ENTRY(PALETTE16, ARGB8888, pal16_argb32), + ENTRY(PALETTE16, RGB888, pal16_argb32), + + ENTRY(RGB15, RGB555, rgb15_rgb555), + ENTRY(RGB15, ARGB1555, rgb15_argb1555), + ENTRY(RGB15, ARGB8888, rgb15_argb32), + ENTRY(RGB15, RGB888, rgb15_argb32), + + ENTRY(RGB15_PALETTED, ARGB8888, rgb15pal_argb32), + ENTRY(RGB15_PALETTED, RGB888, rgb15pal_argb32), + + ENTRY(PALETTE16A, ARGB8888, pal16a_argb32), + ENTRY(PALETTE16A, RGB888, pal16a_rgb32), + + /* rotation */ + ENTRY(ARGB32, ARGB8888, rot_argb32_argb32), + ENTRY_LR(ARGB32, RGB888, rot_argb32_rgb32), + /* Entry primarily for directfb */ + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_ADD), + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_MOD), + ENTRY_BM(ARGB32, RGB888, rot_argb32_rgb32, SDL_BLENDMODE_NONE), + + ENTRY(RGB32, ARGB8888, rot_rgb32_argb32), + ENTRY(RGB32, RGB888, rot_argb32_argb32), + + ENTRY(RGB32_PALETTED, ARGB8888, rot_rgb32pal_argb32), + ENTRY(RGB32_PALETTED, RGB888, rot_rgb32pal_argb32), + + ENTRY(YUY16, ARGB8888, rot_yuv16_argb32rot), + ENTRY(YUY16, RGB888, rot_yuv16_argb32rot), + + ENTRY(YUY16_PALETTED, ARGB8888, rot_yuv16pal_argb32rot), + ENTRY(YUY16_PALETTED, RGB888, rot_yuv16pal_argb32rot), + + ENTRY(PALETTE16, ARGB8888, rot_pal16_argb32), + ENTRY(PALETTE16, RGB888, rot_pal16_argb32), + + ENTRY(RGB15, RGB555, rot_rgb15_argb1555), + ENTRY(RGB15, ARGB1555, rot_rgb15_argb1555), + ENTRY(RGB15, ARGB8888, rot_rgb15_argb32), + ENTRY(RGB15, RGB888, rot_rgb15_argb32), + + ENTRY(RGB15_PALETTED, ARGB8888, rot_rgb15pal_argb32), + ENTRY(RGB15_PALETTED, RGB888, rot_rgb15pal_argb32), + + ENTRY(PALETTE16A, ARGB8888, rot_pal16a_argb32), + ENTRY(PALETTE16A, RGB888, rot_pal16a_rgb32), + + { -1 }, +}; + +} // anonymous namespace + +} // namespace osd + + +#else // defined(OSD_SDL) + +namespace osd { namespace { MODULE_NOT_SUPPORTED(video_sdl2, OSD_RENDERER_PROVIDER, "accel") } } + +#endif // defined(OSD_SDL) + + +MODULE_DEFINITION(RENDERER_SDL2, osd::video_sdl2) |