diff options
Diffstat (limited to 'src/osd/modules/render')
-rw-r--r-- | src/osd/modules/render/bgfx/fs_line.sc | 11 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/fs_quad.sc | 11 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/fs_quad_texture.sc | 14 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/makefile | 13 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/varying.def.sc | 7 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/vs_line.sc | 13 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/vs_quad.sc | 13 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/vs_quad_texture.sc | 14 | ||||
-rw-r--r-- | src/osd/modules/render/binpacker.cpp | 195 | ||||
-rw-r--r-- | src/osd/modules/render/binpacker.h | 183 | ||||
-rw-r--r-- | src/osd/modules/render/d3d/d3dhlsl.cpp | 6 | ||||
-rw-r--r-- | src/osd/modules/render/draw13.cpp | 36 | ||||
-rw-r--r-- | src/osd/modules/render/drawbgfx.cpp | 1187 | ||||
-rw-r--r-- | src/osd/modules/render/drawbgfx.h | 108 | ||||
-rw-r--r-- | src/osd/modules/render/drawdd.cpp | 1317 | ||||
-rw-r--r-- | src/osd/modules/render/drawogl.cpp | 66 | ||||
-rw-r--r-- | src/osd/modules/render/drawsdl.cpp | 235 |
17 files changed, 1599 insertions, 1830 deletions
diff --git a/src/osd/modules/render/bgfx/fs_line.sc b/src/osd/modules/render/bgfx/fs_line.sc new file mode 100644 index 00000000000..1fcd3b27284 --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_line.sc @@ -0,0 +1,11 @@ +$input v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_FragColor = v_color0; +} diff --git a/src/osd/modules/render/bgfx/fs_quad.sc b/src/osd/modules/render/bgfx/fs_quad.sc new file mode 100644 index 00000000000..1fcd3b27284 --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_quad.sc @@ -0,0 +1,11 @@ +$input v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_FragColor = v_color0; +} diff --git a/src/osd/modules/render/bgfx/fs_quad_texture.sc b/src/osd/modules/render/bgfx/fs_quad_texture.sc new file mode 100644 index 00000000000..5a45a056171 --- /dev/null +++ b/src/osd/modules/render/bgfx/fs_quad_texture.sc @@ -0,0 +1,14 @@ +$input v_color0, v_texcoord0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +SAMPLER2D(s_tex, 0); + +void main() +{ + vec4 texel = texture2D(s_tex, v_texcoord0); + gl_FragColor = texel * v_color0; +} diff --git a/src/osd/modules/render/bgfx/makefile b/src/osd/modules/render/bgfx/makefile new file mode 100644 index 00000000000..86735a61c38 --- /dev/null +++ b/src/osd/modules/render/bgfx/makefile @@ -0,0 +1,13 @@ +BGFX_DIR=../../../../../3rdparty/bgfx +RUNTIME_DIR=../../../../.. +BUILD_DIR=../../../../../build + +include $(BGFX_DIR)/scripts/shader.mk + +rebuild: + @make -s --no-print-directory TARGET=0 clean all + @make -s --no-print-directory TARGET=1 clean all + @make -s --no-print-directory TARGET=2 clean all + @make -s --no-print-directory TARGET=3 clean all + @make -s --no-print-directory TARGET=4 clean all + @make -s --no-print-directory TARGET=5 clean all diff --git a/src/osd/modules/render/bgfx/varying.def.sc b/src/osd/modules/render/bgfx/varying.def.sc new file mode 100644 index 00000000000..4745725e015 --- /dev/null +++ b/src/osd/modules/render/bgfx/varying.def.sc @@ -0,0 +1,7 @@ +vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); +vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0); +vec3 v_pos : TEXCOORD1 = vec3(0.0, 0.0, 0.0); + +vec3 a_position : POSITION; +vec4 a_color0 : COLOR0; +vec2 a_texcoord0 : TEXCOORD0; diff --git a/src/osd/modules/render/bgfx/vs_line.sc b/src/osd/modules/render/bgfx/vs_line.sc new file mode 100644 index 00000000000..874ffcf46ac --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_line.sc @@ -0,0 +1,13 @@ +$input a_position, a_color0 +$output v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/vs_quad.sc b/src/osd/modules/render/bgfx/vs_quad.sc new file mode 100644 index 00000000000..84e23c5a09b --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_quad.sc @@ -0,0 +1,13 @@ +$input a_position, a_color0 +$output v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/bgfx/vs_quad_texture.sc b/src/osd/modules/render/bgfx/vs_quad_texture.sc new file mode 100644 index 00000000000..c3699f6fbd9 --- /dev/null +++ b/src/osd/modules/render/bgfx/vs_quad_texture.sc @@ -0,0 +1,14 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +// license:BSD-3-Clause +// copyright-holders:Dario Manesku + +#include "../../../../../3rdparty/bgfx/examples/common/common.sh" + +void main() +{ + gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0)); + v_texcoord0 = a_texcoord0; + v_color0 = a_color0; +} diff --git a/src/osd/modules/render/binpacker.cpp b/src/osd/modules/render/binpacker.cpp new file mode 100644 index 00000000000..2054dfa54cf --- /dev/null +++ b/src/osd/modules/render/binpacker.cpp @@ -0,0 +1,195 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//============================================================ +// +// binpacker.cpp - Simple texture packer for dynamic atlasing +// +//============================================================ + +#include "binpacker.h" +#include <algorithm> + +bool rectangle_packer::pack(const std::vector<packable_rectangle>& rects, std::vector<std::vector<packed_rectangle>>& packs, int pack_size) +{ + clear(); + + m_pack_size = pack_size; + + // Add rects to member array, and check to make sure none is too big + for (size_t rect = 0; rect < rects.size(); rect++) + { + m_rects.push_back(rectangle(0, 0, rects[rect].width(), rects[rect].height(), rects[rect].hash(), rects[rect].format(), rects[rect].rowpixels(), rects[rect].palette(), rects[rect].base())); + } + + // Sort from greatest to least area + std::sort(m_rects.rbegin(), m_rects.rend()); + + // Pack + while (m_num_packed < (int)m_rects.size()) + { + int i = m_packs.size(); + m_packs.push_back(rectangle(m_pack_size)); + m_roots.push_back(i); + if (!fill(i)) + { + return false; + } + } + + // Write out + packs.resize(m_roots.size()); + for (size_t i = 0; i < m_roots.size(); ++i) + { + packs[i].clear(); + add_pack_to_array(m_roots[i], packs[i]); + } + + return true; +} + +void rectangle_packer::clear() +{ + m_pack_size = 0; + m_num_packed = 0; + m_rects.clear(); + m_packs.clear(); + m_roots.clear(); +} + +bool rectangle_packer::fill(int pack) +{ + // For each rect + for (size_t rect = 0; rect < m_rects.size(); ++rect) + { + // If it's not already packed + if (!m_rects[rect].packed) + { + // If it fits in the current working area + if (fits(m_rects[rect], m_packs[pack])) + { + // Store in lower-left of working area, split, and recurse + m_num_packed++; + split(pack, rect); + fill(m_packs[pack].children[0]); + fill(m_packs[pack].children[1]); + return true; + } + } + } + return false; +} + +void rectangle_packer::split(int pack, int rect) +{ + // Split the working area either horizontally or vertically with respect + // to the rect we're storing, such that we get the largest possible child + // area. + + rectangle left = m_packs[pack]; + rectangle right = m_packs[pack]; + rectangle bottom = m_packs[pack]; + rectangle top = m_packs[pack]; + + left.y += m_rects[rect].h; + left.w = m_rects[rect].w; + left.h -= m_rects[rect].h; + + right.x += m_rects[rect].w; + right.w -= m_rects[rect].w; + + bottom.x += m_rects[rect].w; + bottom.h = m_rects[rect].h; + bottom.w -= m_rects[rect].w; + + top.y += m_rects[rect].h; + top.h -= m_rects[rect].h; + + int max_lr_area = left.get_area(); + if (right.get_area() > max_lr_area) + { + max_lr_area = right.get_area(); + } + + int max_bt_area = bottom.get_area(); + if (top.get_area() > max_bt_area) + { + max_bt_area = top.get_area(); + } + + if (max_lr_area > max_bt_area) + { + if (left.get_area() > right.get_area()) + { + m_packs.push_back(left); + m_packs.push_back(right); + } + else + { + m_packs.push_back(right); + m_packs.push_back(left); + } + } + else + { + if (bottom.get_area() > top.get_area()) + { + m_packs.push_back(bottom); + m_packs.push_back(top); + } + else + { + m_packs.push_back(top); + m_packs.push_back(bottom); + } + } + + // This pack area now represents the rect we've just stored, so save the + // relevant info to it, and assign children. + m_packs[pack].w = m_rects[rect].w; + m_packs[pack].h = m_rects[rect].h; + m_packs[pack].hash = m_rects[rect].hash; + m_packs[pack].format = m_rects[rect].format; + m_packs[pack].rowpixels = m_rects[rect].rowpixels; + m_packs[pack].palette = m_rects[rect].palette; + m_packs[pack].base = m_rects[rect].base; + m_packs[pack].children[0] = m_packs.size() - 2; + m_packs[pack].children[1] = m_packs.size() - 1; + + // Done with the rect + m_rects[rect].packed = true; + +} + +bool rectangle_packer::fits(rectangle& rect1, const rectangle& rect2) +{ + // Check to see if rect1 fits in rect2 + + if (rect1.w <= rect2.w && rect1.h <= rect2.h) + { + return true; + } + else + { + return false; + } +} + +void rectangle_packer::add_pack_to_array(int pack, std::vector<packed_rectangle>& array) const +{ + if (m_packs[pack].hash != 0) + { + array.push_back(packed_rectangle(m_packs[pack].hash, m_packs[pack].format, + m_packs[pack].w, m_packs[pack].h, m_packs[pack].x, m_packs[pack].y, + m_packs[pack].rowpixels, m_packs[pack].palette, m_packs[pack].base)); + + if (m_packs[pack].children[0] != -1) + { + add_pack_to_array(m_packs[pack].children[0], array); + } + + if (m_packs[pack].children[1] != -1) + { + add_pack_to_array(m_packs[pack].children[1], array); + } + } +} diff --git a/src/osd/modules/render/binpacker.h b/src/osd/modules/render/binpacker.h new file mode 100644 index 00000000000..677083b5c09 --- /dev/null +++ b/src/osd/modules/render/binpacker.h @@ -0,0 +1,183 @@ +#pragma once + +#ifndef __RECTPACKER_H__ +#define __RECTPACKER_H__ + +#include "emu.h" + +#include <vector> + +class rectangle_packer +{ +public: + // The input and output are in terms of vectors of ints to avoid + // dependencies (although I suppose a public member struct could have been + // used). The parameters are: + + // packs : After packing, the outer array contains the packs (therefore + // the number of packs is packs.size()). Each inner array contains a + // sequence of sets of 3 ints. Each set represents a rectangle in the + // pack. The elements in the set are 1) the rect ID, 2) the x position + // of the rect with respect to the pack, and 3) the y position of the rect + // with respect to the pack. The widths and heights of the rects are not + // included, as it's assumed they are stored on the caller's side (they + // were after all the input to the function). + + class packable_rectangle + { + public: + packable_rectangle() : m_hash(0), m_width(-1), m_height(-1) { } + packable_rectangle(UINT32 hash, UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base) + : m_hash(hash) + , m_format(format) + , m_width(width) + , m_height(height) + , m_rowpixels(rowpixels) + , m_palette(palette) + , m_base(base) + { + } + + UINT32 hash() const { return m_hash; } + UINT32 format() const { return m_format; } + int width() const { return m_width; } + int height() const { return m_height; } + int rowpixels() const { return m_rowpixels; } + const rgb_t* palette() const { return m_palette; } + void* base() const { return m_base; } + + private: + UINT32 m_hash; + UINT32 m_format; + int m_width; + int m_height; + int m_rowpixels; + const rgb_t* m_palette; + void* m_base; + }; + + class packed_rectangle + { + public: + packed_rectangle() : m_hash(0), m_format(0), m_width(-1), m_height(-1), m_x(-1), m_y(-1), m_rowpixels(0), m_palette(nullptr), m_base(nullptr) { } + packed_rectangle(const packed_rectangle& rect) + : m_hash(rect.m_hash) + , m_format(rect.m_format) + , m_width(rect.m_width) + , m_height(rect.m_height) + , m_x(rect.m_x) + , m_y(rect.m_y) + , m_rowpixels(rect.m_rowpixels) + , m_palette(rect.m_palette) + , m_base(rect.m_base) + { + } + packed_rectangle(UINT32 hash, UINT32 format, int width, int height, int x, int y, int rowpixels, const rgb_t *palette, void *base) + : m_hash(hash) + , m_format(format) + , m_width(width) + , m_height(height) + , m_x(x) + , m_y(y) + , m_rowpixels(rowpixels) + , m_palette(palette) + , m_base(base) + { + } + + UINT32 hash() const { return m_hash; } + UINT32 format() const { return m_format; } + int width() const { return m_width; } + int height() const { return m_height; } + int x() const { return m_x; } + int y() const { return m_y; } + int rowpixels() const { return m_rowpixels; } + const rgb_t* palette() const { return m_palette; } + void* base() const { return m_base; } + + private: + UINT32 m_hash; + UINT32 m_format; + int m_width; + int m_height; + int m_x; + int m_y; + int m_rowpixels; + const rgb_t* m_palette; + void* m_base; + }; + + bool pack(const std::vector<packable_rectangle>& rects, std::vector<std::vector<packed_rectangle>>& packs, int pack_size); + +private: + struct rectangle + { + rectangle(int size) + : x(0) + , y(0) + , w(size) + , h(size) + , hash(-1) + , format(0) + , rowpixels(0) + , palette(nullptr) + , base(nullptr) + , packed(false) + { + children[0] = -1; + children[1] = -1; + } + + rectangle(int x, int y, int w, int h, int hash, UINT32 format, int rowpixels, const rgb_t *palette, void *base) + : x(x) + , y(y) + , w(w) + , h(h) + , hash(hash) + , format(format) + , rowpixels(rowpixels) + , palette(palette) + , base(base) + , packed(false) + { + children[0] = -1; + children[1] = -1; + } + + int get_area() const + { + return w * h; + } + + bool operator<(const rectangle& rect) const + { + return get_area() < rect.get_area(); + } + + int x; + int y; + int w; + int h; + int hash; + UINT32 format; + int rowpixels; + const rgb_t* palette; + void* base; + int children[2]; + bool packed; + }; + + void clear(); + bool fill(int pack); + void split(int pack, int rect); + bool fits(rectangle& rect1, const rectangle& rect2); + void add_pack_to_array(int pack, std::vector<packed_rectangle>& array) const; + + int m_pack_size; + int m_num_packed; + std::vector<rectangle> m_rects; + std::vector<rectangle> m_packs; + std::vector<int> m_roots; +}; + +#endif // __RECTPACKER_H__
\ No newline at end of file diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 7284eaabaa6..3ffcee44707 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -1457,9 +1457,9 @@ int shaders::downsample_pass(render_target *rt, int source_index, poly_info *pol curr_effect->update_uniforms(); int bloom_index = 0; - float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); - float bloom_width = d3d->get_width(); - float bloom_height = d3d->get_height(); + float bloom_width = rt->target_width; + float bloom_height = rt->target_height; + float bloom_size = bloom_width < bloom_height ? bloom_width : bloom_height; for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) { bloom_dims[bloom_index][0] = (float)(int)bloom_width; diff --git a/src/osd/modules/render/draw13.cpp b/src/osd/modules/render/draw13.cpp index f357d567e71..320cc9f3a62 100644 --- a/src/osd/modules/render/draw13.cpp +++ b/src/osd/modules/render/draw13.cpp @@ -203,12 +203,6 @@ private: INT32 m_blittimer; -#if (SDLMAME_SDL2) - //SDL_GLContext m_gl_context_id; -#else - // SDL surface - SDL_Surface *m_sdlsurf; -#endif simple_list<texture_info> m_texlist; // list of active textures @@ -601,32 +595,6 @@ static void drawsdl2_exit(void) //============================================================ // sdl_info::create -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a //============================================================ static void drawsdl_show_info(struct SDL_RendererInfo *render_info) @@ -661,7 +629,6 @@ static void drawsdl_show_info(struct SDL_RendererInfo *render_info) int sdl_info13::create() { -#if (SDLMAME_SDL2) // create renderer /* Enable bilinear filtering in case it is supported. @@ -699,9 +666,6 @@ int sdl_info13::create() SDL_GetRendererInfo(m_sdl_renderer, &render_info); drawsdl_show_info(&render_info); -#else - -#endif return 0; } diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp index ee808bfc197..9d751c9f816 100644 --- a/src/osd/modules/render/drawbgfx.cpp +++ b/src/osd/modules/render/drawbgfx.cpp @@ -1,8 +1,8 @@ // license:BSD-3-Clause -// copyright-holders:Miodrag Milanovic +// copyright-holders:Miodrag Milanovic,Ryan Holtz,Dario Manesku,Branimir Karadzic,Aaron Giles //============================================================ // -// drawbgfx.c - BGFX drawer +// drawbgfx.cpp - BGFX renderer // //============================================================ #define __STDC_LIMIT_MACROS @@ -14,11 +14,7 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> #if defined(SDLMAME_WIN32) -#if (SDLMAME_SDL2) #include <SDL2/SDL_syswm.h> -#else -#include <SDL/SDL_syswm.h> -#endif #endif #else #include "sdlinc.h" @@ -30,6 +26,11 @@ #include <bgfx/bgfxplatform.h> #include <bgfx/bgfx.h> +#include <bx/fpumath.h> +#include <bx/readerwriter.h> +#include <algorithm> + +#include "drawbgfx.h" //============================================================ // DEBUGGING @@ -43,6 +44,8 @@ // MACROS //============================================================ +#define GIBBERISH (0) + //============================================================ // INLINES //============================================================ @@ -53,67 +56,6 @@ //============================================================ -/* sdl_info is the information about SDL for the current screen */ -class renderer_bgfx : public osd_renderer -{ -public: - renderer_bgfx(osd_window *w) - : osd_renderer(w, FLAG_NONE), m_blittimer(0), - m_blit_dim(0, 0), - m_last_hofs(0), m_last_vofs(0), - m_last_blit_time(0), m_last_blit_pixels(0) - {} - - virtual int create() override; - virtual int draw(const int update) override; -#ifdef OSD_SDL - virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; -#else - virtual void save() override { } - virtual void record() override { } - virtual void toggle_fsfx() override { } -#endif - virtual void destroy() override; - virtual render_primitive_list *get_primitives() override - { -#ifdef OSD_WINDOWS - RECT client; - GetClientRect(window().m_hwnd, &client); - window().target()->set_bounds(rect_width(&client), rect_height(&client), window().aspect()); - return &window().target()->get_primitives(); -#else - osd_dim nd = window().blit_surface_size(); - if (nd != m_blit_dim) - { - m_blit_dim = nd; - notify_changed(); - } - window().target()->set_bounds(m_blit_dim.width(), m_blit_dim.height(), window().aspect()); - return &window().target()->get_primitives(); -#endif - } - - // 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); - - INT32 m_blittimer; - - //simple_list<texture_info> m_texlist; // list of active textures - - osd_dim m_blit_dim; - float m_last_hofs; - float m_last_vofs; - - // Stats - INT64 m_last_blit_time; - INT64 m_last_blit_pixels; - - // Original display_mode -}; - - //============================================================ // PROTOTYPES //============================================================ @@ -150,36 +92,85 @@ int drawbgfx_init(running_machine &machine, osd_draw_callbacks *callbacks) static void drawbgfx_exit(void) { + // Shutdown bgfx. + bgfx::shutdown(); } //============================================================ // renderer_bgfx::create //============================================================ +bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName); + + +#ifdef OSD_SDL +static void* sdlNativeWindowHandle(SDL_Window* _window) +{ + SDL_SysWMinfo wmi; + SDL_VERSION(&wmi.version); + if (!SDL_GetWindowWMInfo(_window, &wmi)) + { + return nullptr; + } + +# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD + return (void*)wmi.info.x11.window; +# elif BX_PLATFORM_OSX + return wmi.info.cocoa.window; +# elif BX_PLATFORM_WINDOWS + return wmi.info.win.window; +# elif BX_PLATFORM_STEAMLINK + return wmi.info.vivante.window; +# elif BX_PLATFORM_EMSCRIPTEN + return nullptr; +# endif // BX_PLATFORM_ +} +#endif int renderer_bgfx::create() { // create renderer + osd_dim wdim = window().get_size(); + if (window().m_index == 0) + { #ifdef OSD_WINDOWS - RECT client; - GetClientRect(window().m_hwnd, &client); - - bgfx::winSetHwnd(window().m_hwnd); - bgfx::init(); - bgfx::reset(rect_width(&client), rect_height(&client), BGFX_RESET_VSYNC); + bgfx::winSetHwnd(window().m_hwnd); #else - osd_dim d = window().get_size(); - m_blittimer = 3; - - bgfx::sdlSetWindow(window().sdl_window()); - bgfx::init(); - bgfx::reset(d.width(), d.height(), BGFX_RESET_VSYNC); + bgfx::sdlSetWindow(window().sdl_window()); +#endif + bgfx::init(); + bgfx::reset(wdim.width(), wdim.height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); + // Enable debug text. + bgfx::setDebug(BGFX_DEBUG_TEXT); //BGFX_DEBUG_STATS + m_dimensions = osd_dim(wdim.width(), wdim.height()); + } + else + { +#ifdef OSD_WINDOWS + fbh = bgfx::createFrameBuffer(window().m_hwnd, wdim.width(), wdim.height()); +#else + fbh = bgfx::createFrameBuffer(sdlNativeWindowHandle(window().sdl_window()), wdim.width(), wdim.height()); #endif + bgfx::touch(window().m_index); + } + + ScreenVertex::init(); + + // Create program from shaders. + m_progQuad = loadProgram("vs_quad", "fs_quad"); + m_progQuadTexture = loadProgram("vs_quad_texture", "fs_quad_texture"); + m_s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1); + + uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT; + m_texture_cache = bgfx::createTexture2D(CACHE_SIZE, CACHE_SIZE, 1, bgfx::TextureFormat::RGBA8, flags); + + const bgfx::Memory* memory = bgfx::alloc(sizeof(uint32_t) * CACHE_SIZE * CACHE_SIZE); + memset(memory->data, 0, sizeof(uint32_t) * CACHE_SIZE * CACHE_SIZE); + bgfx::updateTexture2D(m_texture_cache, 0, 0, 0, CACHE_SIZE, CACHE_SIZE, memory, CACHE_SIZE * sizeof(uint32_t)); - // Enable debug text. - bgfx::setDebug(BGFX_DEBUG_STATS);// BGFX_DEBUG_TEXT); + memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16); + m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white)); - osd_printf_verbose("Leave drawsdl2_window_create\n"); return 0; } @@ -189,12 +180,14 @@ int renderer_bgfx::create() void renderer_bgfx::destroy() { - // free the memory in the window - - // destroy_all_textures(); - - // Shutdown bgfx. - bgfx::shutdown(); + if (window().m_index > 0) + { + bgfx::destroyFrameBuffer(fbh); + } + bgfx::destroyUniform(m_s_texColor); + // Cleanup. + bgfx::destroyProgram(m_progQuad); + bgfx::destroyProgram(m_progQuadTexture); } @@ -205,133 +198,973 @@ void renderer_bgfx::destroy() #ifdef OSD_SDL int renderer_bgfx::xy_to_render_target(int x, int y, int *xt, int *yt) { - *xt = x - m_last_hofs; - *yt = y - m_last_vofs; - if (*xt<0 || *xt >= m_blit_dim.width()) + *xt = x; + *yt = y; + if (*xt<0 || *xt >= m_dimensions.width()) return 0; - if (*yt<0 || *yt >= m_blit_dim.height()) + if (*yt<0 || *yt >= m_dimensions.height()) return 0; return 1; } #endif +static const bgfx::Memory* loadMem(bx::FileReaderI* _reader, const char* _filePath) +{ + if (bx::open(_reader, _filePath)) + { + uint32_t size = (uint32_t)bx::getSize(_reader); + const bgfx::Memory* mem = bgfx::alloc(size + 1); + bx::read(_reader, mem->data, size); + bx::close(_reader); + mem->data[mem->size - 1] = '\0'; + return mem; + } + + return nullptr; +} +static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader, const char* _name) +{ + char filePath[512]; + + const char* shaderPath = "shaders/dx9/"; + + switch (bgfx::getRendererType()) + { + case bgfx::RendererType::Direct3D11: + case bgfx::RendererType::Direct3D12: + shaderPath = "shaders/dx11/"; + break; + + case bgfx::RendererType::OpenGL: + shaderPath = "shaders/glsl/"; + break; + + case bgfx::RendererType::Metal: + shaderPath = "shaders/metal/"; + break; + + case bgfx::RendererType::OpenGLES: + shaderPath = "shaders/gles/"; + break; + + default: + break; + } + + strcpy(filePath, shaderPath); + strcat(filePath, _name); + strcat(filePath, ".bin"); + + return bgfx::createShader(loadMem(_reader, filePath)); +} + +bgfx::ProgramHandle renderer_bgfx::loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName) +{ + bgfx::ShaderHandle vsh = loadShader(_reader, _vsName); + bgfx::ShaderHandle fsh = BGFX_INVALID_HANDLE; + if (nullptr != _fsName) + { + fsh = loadShader(_reader, _fsName); + } + + return bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */); +} +static auto s_fileReader = new bx::CrtFileReader; + +bgfx::ProgramHandle renderer_bgfx::loadProgram(const char* _vsName, const char* _fsName) +{ + return loadProgram(s_fileReader, _vsName, _fsName); +} + //============================================================ // drawbgfx_window_draw //============================================================ +bgfx::VertexDecl renderer_bgfx::ScreenVertex::ms_decl; + +void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, ScreenVertex* vertex) +{ + rectangle_packer::packed_rectangle& rect = m_hash_to_entry[hash]; + float u0 = float(rect.x()) / float(CACHE_SIZE); + float v0 = float(rect.y()) / float(CACHE_SIZE); + float u1 = u0 + float(rect.width()) / float(CACHE_SIZE); + float v1 = v0 + float(rect.height()) / float(CACHE_SIZE); + u1 -= 0.5f / float(CACHE_SIZE); + v1 -= 0.5f / float(CACHE_SIZE); + u0 += 0.5f / float(CACHE_SIZE); + v0 += 0.5f / float(CACHE_SIZE); + UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255); + + float x[4] = { prim->bounds.x0, prim->bounds.x1, prim->bounds.x0, prim->bounds.x1 }; + float y[4] = { prim->bounds.y0, prim->bounds.y0, prim->bounds.y1, prim->bounds.y1 }; + float u[4] = { u0, u1, u0, u1 }; + float v[4] = { v0, v0, v1, v1 }; + + if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_SWAP_XY) + { + std::swap(u[1], u[2]); + std::swap(v[1], v[2]); + } + + if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_FLIP_X) + { + std::swap(u[0], u[1]); + std::swap(v[0], v[1]); + std::swap(u[2], u[3]); + std::swap(v[2], v[3]); + } + + if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_FLIP_Y) + { + std::swap(u[0], u[2]); + std::swap(v[0], v[2]); + std::swap(u[1], u[3]); + std::swap(v[1], v[3]); + } + + vertex[0].m_x = x[0]; // 0 + vertex[0].m_y = y[0]; + vertex[0].m_z = 0; + vertex[0].m_rgba = rgba; + vertex[0].m_u = u[0]; + vertex[0].m_v = v[0]; + + vertex[1].m_x = x[1]; // 1 + vertex[1].m_y = y[1]; + vertex[1].m_z = 0; + vertex[1].m_rgba = rgba; + vertex[1].m_u = u[1]; + vertex[1].m_v = v[1]; + + vertex[2].m_x = x[3]; // 3 + vertex[2].m_y = y[3]; + vertex[2].m_z = 0; + vertex[2].m_rgba = rgba; + vertex[2].m_u = u[3]; + vertex[2].m_v = v[3]; + + vertex[3].m_x = x[3]; // 3 + vertex[3].m_y = y[3]; + vertex[3].m_z = 0; + vertex[3].m_rgba = rgba; + vertex[3].m_u = u[3]; + vertex[3].m_v = v[3]; + + vertex[4].m_x = x[2]; // 2 + vertex[4].m_y = y[2]; + vertex[4].m_z = 0; + vertex[4].m_rgba = rgba; + vertex[4].m_u = u[2]; + vertex[4].m_v = v[2]; + + vertex[5].m_x = x[0]; // 0 + vertex[5].m_y = y[0]; + vertex[5].m_z = 0; + vertex[5].m_rgba = rgba; + vertex[5].m_u = u[0]; + vertex[5].m_v = v[0]; +} + +void renderer_bgfx::render_textured_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer) +{ + ScreenVertex* vertex = (ScreenVertex*)buffer->data; + + UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255); + + vertex[0].m_x = prim->bounds.x0; + vertex[0].m_y = prim->bounds.y0; + vertex[0].m_z = 0; + vertex[0].m_rgba = rgba; + vertex[0].m_u = prim->texcoords.tl.u; + vertex[0].m_v = prim->texcoords.tl.v; + + vertex[1].m_x = prim->bounds.x1; + vertex[1].m_y = prim->bounds.y0; + vertex[1].m_z = 0; + vertex[1].m_rgba = rgba; + vertex[1].m_u = prim->texcoords.tr.u; + vertex[1].m_v = prim->texcoords.tr.v; + + vertex[2].m_x = prim->bounds.x1; + vertex[2].m_y = prim->bounds.y1; + vertex[2].m_z = 0; + vertex[2].m_rgba = rgba; + vertex[2].m_u = prim->texcoords.br.u; + vertex[2].m_v = prim->texcoords.br.v; + + vertex[3].m_x = prim->bounds.x1; + vertex[3].m_y = prim->bounds.y1; + vertex[3].m_z = 0; + vertex[3].m_rgba = rgba; + vertex[3].m_u = prim->texcoords.br.u; + vertex[3].m_v = prim->texcoords.br.v; + + vertex[4].m_x = prim->bounds.x0; + vertex[4].m_y = prim->bounds.y1; + vertex[4].m_z = 0; + vertex[4].m_rgba = rgba; + vertex[4].m_u = prim->texcoords.bl.u; + vertex[4].m_v = prim->texcoords.bl.v; + + vertex[5].m_x = prim->bounds.x0; + vertex[5].m_y = prim->bounds.y0; + vertex[5].m_z = 0; + vertex[5].m_rgba = rgba; + vertex[5].m_u = prim->texcoords.tl.u; + vertex[5].m_v = prim->texcoords.tl.v; + bgfx::setVertexBuffer(buffer); + + uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP; + if (video_config.filter == 0) + { + texture_flags |= BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT; + } + + const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(prim->flags & PRIMFLAG_TEXFORMAT_MASK, + prim->texture.width, prim->texture.height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base); + + bgfx::TextureHandle texture = bgfx::createTexture2D((uint16_t)prim->texture.width, (uint16_t)prim->texture.height, 1, bgfx::TextureFormat::RGBA8, texture_flags, mem); + + bgfx::setTexture(0, m_s_texColor, texture); + + set_bgfx_state(PRIMFLAG_GET_BLENDMODE(prim->flags)); + bgfx::submit(view, m_progQuadTexture); + + bgfx::destroyTexture(texture); +} + +#define MAX_TEMP_COORDS 100 + +void renderer_bgfx::put_polygon(const float* coords, UINT32 num_coords, float r, UINT32 rgba, ScreenVertex* vertex) +{ + float tempCoords[MAX_TEMP_COORDS * 3]; + float tempNormals[MAX_TEMP_COORDS * 2]; + + rectangle_packer::packed_rectangle& rect = m_hash_to_entry[WHITE_HASH]; + float u0 = float(rect.x()) / float(CACHE_SIZE); + float v0 = float(rect.y()) / float(CACHE_SIZE); + + num_coords = num_coords < MAX_TEMP_COORDS ? num_coords : MAX_TEMP_COORDS; + + for (uint32_t ii = 0, jj = num_coords - 1; ii < num_coords; jj = ii++) + { + const float* v0 = &coords[jj * 3]; + const float* v1 = &coords[ii * 3]; + float dx = v1[0] - v0[0]; + float dy = v1[1] - v0[1]; + float d = sqrtf(dx * dx + dy * dy); + if (d > 0) + { + d = 1.0f / d; + dx *= d; + dy *= d; + } + + tempNormals[jj * 2 + 0] = dy; + tempNormals[jj * 2 + 1] = -dx; + } + + for (uint32_t ii = 0, jj = num_coords - 1; ii < num_coords; jj = ii++) + { + float dlx0 = tempNormals[jj * 2 + 0]; + float dly0 = tempNormals[jj * 2 + 1]; + float dlx1 = tempNormals[ii * 2 + 0]; + float dly1 = tempNormals[ii * 2 + 1]; + float dmx = (dlx0 + dlx1) * 0.5f; + float dmy = (dly0 + dly1) * 0.5f; + float dmr2 = dmx * dmx + dmy * dmy; + if (dmr2 > 0.000001f) + { + float scale = 1.0f / dmr2; + if (scale > 10.0f) + { + scale = 10.0f; + } + + dmx *= scale; + dmy *= scale; + } + + tempCoords[ii * 3 + 0] = coords[ii * 3 + 0] + dmx * r; + tempCoords[ii * 3 + 1] = coords[ii * 3 + 1] + dmy * r; + tempCoords[ii * 3 + 2] = coords[ii * 3 + 2]; + } + + int vertIndex = 0; + UINT32 trans = rgba & 0x00ffffff; + for (uint32_t ii = 0, jj = num_coords - 1; ii < num_coords; jj = ii++) + { + vertex[vertIndex].m_x = coords[ii * 3 + 0]; + vertex[vertIndex].m_y = coords[ii * 3 + 1]; + vertex[vertIndex].m_z = coords[ii * 3 + 2]; + vertex[vertIndex].m_rgba = rgba; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + + vertex[vertIndex].m_x = coords[jj * 3 + 0]; + vertex[vertIndex].m_y = coords[jj * 3 + 1]; + vertex[vertIndex].m_z = coords[jj * 3 + 2]; + vertex[vertIndex].m_rgba = rgba; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + + vertex[vertIndex].m_x = tempCoords[jj * 3 + 0]; + vertex[vertIndex].m_y = tempCoords[jj * 3 + 1]; + vertex[vertIndex].m_z = tempCoords[jj * 3 + 2]; + vertex[vertIndex].m_rgba = trans; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + + vertex[vertIndex].m_x = tempCoords[jj * 3 + 0]; + vertex[vertIndex].m_y = tempCoords[jj * 3 + 1]; + vertex[vertIndex].m_z = tempCoords[jj * 3 + 2]; + vertex[vertIndex].m_rgba = trans; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + + vertex[vertIndex].m_x = tempCoords[ii * 3 + 0]; + vertex[vertIndex].m_y = tempCoords[ii * 3 + 1]; + vertex[vertIndex].m_z = tempCoords[ii * 3 + 2]; + vertex[vertIndex].m_rgba = trans; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + + vertex[vertIndex].m_x = coords[ii * 3 + 0]; + vertex[vertIndex].m_y = coords[ii * 3 + 1]; + vertex[vertIndex].m_z = coords[ii * 3 + 2]; + vertex[vertIndex].m_rgba = rgba; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + } + + for (uint32_t ii = 2; ii < num_coords; ++ii) + { + vertex[vertIndex].m_x = coords[0]; + vertex[vertIndex].m_y = coords[1]; + vertex[vertIndex].m_z = coords[2]; + vertex[vertIndex].m_rgba = rgba; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + + vertex[vertIndex].m_x = coords[(ii - 1) * 3 + 0]; + vertex[vertIndex].m_y = coords[(ii - 1) * 3 + 1]; + vertex[vertIndex].m_z = coords[(ii - 1) * 3 + 2]; + vertex[vertIndex].m_rgba = rgba; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + + vertex[vertIndex].m_x = coords[ii * 3 + 0]; + vertex[vertIndex].m_y = coords[ii * 3 + 1]; + vertex[vertIndex].m_z = coords[ii * 3 + 2]; + vertex[vertIndex].m_rgba = rgba; + vertex[vertIndex].m_u = u0; + vertex[vertIndex].m_v = v0; + vertIndex++; + } +} + +void renderer_bgfx::put_line(float x0, float y0, float x1, float y1, float r, UINT32 rgba, ScreenVertex* vertex, float fth) +{ + float dx = x1 - x0; + float dy = y1 - y0; + float d = sqrtf(dx * dx + dy * dy); + if (d > 0.0001f) + { + d = 1.0f / d; + dx *= d; + dy *= d; + } + + float nx = dy; + float ny = -dx; + float verts[4 * 3]; + r -= fth; + r *= 0.5f; + if (r < 0.01f) + { + r = 0.01f; + } + + dx *= r; + dy *= r; + nx *= r; + ny *= r; + + verts[0] = x0 - dx - nx; + verts[1] = y0 - dy - ny; + verts[2] = 0; + + verts[3] = x0 - dx + nx; + verts[4] = y0 - dy + ny; + verts[5] = 0; + + verts[6] = x1 + dx + nx; + verts[7] = y1 + dy + ny; + verts[8] = 0; + + verts[9] = x1 + dx - nx; + verts[10] = y1 + dy - ny; + verts[11] = 0; + + put_polygon(verts, 4, fth, rgba, vertex); +} + +uint32_t renderer_bgfx::u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 255) +{ + return (a << 24) | (b << 16) | (g << 8) | r; +} + +//============================================================ +// copyline_palette16 +//============================================================ + +static inline void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette) +{ + for (int x = 0; x < width; x++) + { + rgb_t srcpixel = palette[*src++]; + *dst++ = 0xff000000 | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r(); + } +} + + +//============================================================ +// copyline_palettea16 +//============================================================ + +static inline void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette) +{ + for (int x = 0; x < width; x++) + { + rgb_t srcpixel = palette[*src++]; + *dst++ = (srcpixel.a() << 24) | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r(); + } +} + + +//============================================================ +// copyline_rgb32 +//============================================================ + +static inline void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette) +{ + int x; + + // palette (really RGB map) case + if (palette != nullptr) + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = 0xff000000 | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()]; + } + } + + // direct case + else + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = 0xff000000 | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r(); + } + } +} + + +//============================================================ +// copyline_argb32 +//============================================================ + +static inline void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette) +{ + int x; + // palette (really RGB map) case + if (palette != nullptr) + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()]; + } + } + + // direct case + else + { + for (x = 0; x < width; x++) + { + rgb_t srcpix = *src++; + *dst++ = (srcpix.a() << 24) | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r(); + } + } +} + +static inline UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr) +{ + /* original equations: + + C = Y - 16 + D = Cb - 128 + E = Cr - 128 + + R = clip(( 298 * C + 409 * E + 128) >> 8) + G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) + B = clip(( 298 * C + 516 * D + 128) >> 8) + + R = clip(( 298 * (Y - 16) + 409 * (Cr - 128) + 128) >> 8) + G = clip(( 298 * (Y - 16) - 100 * (Cb - 128) - 208 * (Cr - 128) + 128) >> 8) + B = clip(( 298 * (Y - 16) + 516 * (Cb - 128) + 128) >> 8) + + R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) + G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) + B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) + + R = clip(( 298 * Y - 298 * 16 + 409 * Cr - 409 * 128 + 128) >> 8) + G = clip(( 298 * Y - 298 * 16 - 100 * Cb + 100 * 128 - 208 * Cr + 208 * 128 + 128) >> 8) + B = clip(( 298 * Y - 298 * 16 + 516 * Cb - 516 * 128 + 128) >> 8) + */ + int r, g, b, common; + + common = 298 * y - 298 * 16; + r = (common + 409 * cr - 409 * 128 + 128) >> 8; + g = (common - 100 * cb + 100 * 128 - 208 * cr + 208 * 128 + 128) >> 8; + b = (common + 516 * cb - 516 * 128 + 128) >> 8; + + if (r < 0) r = 0; + else if (r > 255) r = 255; + if (g < 0) g = 0; + else if (g > 255) g = 255; + if (b < 0) b = 0; + else if (b > 255) b = 255; + + return 0xff000000 | (b << 16) | (g << 8) | r; +} + +//============================================================ +// copyline_yuy16_to_argb +//============================================================ + +static inline void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette, int xprescale) +{ + int x; + + assert(width % 2 == 0); + + // palette (really RGB map) case + if (palette != nullptr) + { + for (x = 0; x < width / 2; x++) + { + UINT16 srcpix0 = *src++; + UINT16 srcpix1 = *src++; + UINT8 cb = srcpix0 & 0xff; + UINT8 cr = srcpix1 & 0xff; + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(palette[0x000 + (srcpix0 >> 8)], cb, cr); + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(palette[0x000 + (srcpix1 >> 8)], cb, cr); + } + } + + // direct case + else + { + for (x = 0; x < width; x += 2) + { + UINT16 srcpix0 = *src++; + UINT16 srcpix1 = *src++; + UINT8 cb = srcpix0 & 0xff; + UINT8 cr = srcpix1 & 0xff; + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(srcpix0 >> 8, cb, cr); + for (int x2 = 0; x2 < xprescale; x2++) + *dst++ = ycc_to_rgb(srcpix1 >> 8, cb, cr); + } + } +} + +const bgfx::Memory* renderer_bgfx::mame_texture_data_to_bgfx_texture_data(UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base) +{ + const bgfx::Memory* mem = bgfx::alloc(width * height * 4); + for (int y = 0; y < height; y++) + { + switch (format) + { + case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16): + copyline_palette16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette); + break; + case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTEA16): + copyline_palettea16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette); + break; + case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16): + copyline_yuy16_to_argb((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette, 1); + break; + case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32): + copyline_argb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette); + break; + case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32): + copyline_rgb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette); + break; + default: + break; + } + } + return mem; +} + int renderer_bgfx::draw(int update) { - //if (has_flags(FI_CHANGED) || (window().width() != m_last_width) || (window().height() != m_last_height)) - // do something - //clear_flags(FI_CHANGED); + int index = window().m_index; + // Set view 0 default viewport. + osd_dim wdim = window().get_size(); + int width = wdim.width(); + int height = wdim.height(); + if (index == 0) + { + if ((m_dimensions != osd_dim(width, height))) { + bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); + m_dimensions = osd_dim(width, height); + } + } + else { + if ((m_dimensions != osd_dim(width, height))) { + bgfx::reset(window().m_main->get_size().width(), window().m_main->get_size().height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE); + if (bgfx::isValid(fbh)) + { + bgfx::destroyFrameBuffer(fbh); + } +#ifdef OSD_WINDOWS + fbh = bgfx::createFrameBuffer(window().m_hwnd, width, height); +#else + fbh = bgfx::createFrameBuffer(sdlNativeWindowHandle(window().sdl_window()), width, height); +#endif + bgfx::setViewFrameBuffer(index, fbh); + m_dimensions = osd_dim(width, height); + bgfx::setViewClear(index + , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH + , 0x000000ff + , 1.0f + , 0 + ); + bgfx::touch(index); + bgfx::frame(); + return 0; + } + } + if (index != 0) bgfx::setViewFrameBuffer(index, fbh); + bgfx::setViewSeq(index, true); + bgfx::setViewRect(index, 0, 0, width, height); + + // Setup view transform. + { + float view[16]; + bx::mtxIdentity(view); - bgfx::setViewClear(0 - , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + float left = 0.0f; + float top = 0.0f; + float right = width; + float bottom = height; + float proj[16]; + bx::mtxOrtho(proj, left, right, bottom, top, 0.0f, 100.0f); + bgfx::setViewTransform(index, view, proj); + } + bgfx::setViewClear(index + , BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH , 0x000000ff , 1.0f , 0 ); - // Set view 0 default viewport. -#ifdef OSD_WINDOWS - RECT client; - GetClientRect(window().m_hwnd, &client); - bgfx::setViewRect(0, 0, 0, rect_width(&client), rect_height(&client)); -#else - bgfx::setViewRect(0, 0, 0, m_blit_dim.width(), m_blit_dim.height()); -#endif + // This dummy draw call is here to make sure that view 0 is cleared // if no other draw calls are submitted to view 0. - bgfx::touch(0); + bgfx::touch(index); window().m_primlist->acquire_lock(); - // now draw - for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) + // Mark our texture atlas as dirty if we need to do so + bool atlas_valid = update_atlas(); + + render_primitive *prim = window().m_primlist->first(); + while (prim != nullptr) { - switch (prim->type) + UINT32 blend = PRIMFLAG_GET_BLENDMODE(prim->flags); + + bgfx::TransientVertexBuffer buffer; + allocate_buffer(prim, blend, &buffer); + + buffer_status status = buffer_primitives(index, atlas_valid, &prim, &buffer); + + if (status != BUFFER_EMPTY) + { + set_bgfx_state(blend); + bgfx::setVertexBuffer(&buffer); + bgfx::setTexture(0, m_s_texColor, m_texture_cache); + bgfx::submit(index, m_progQuadTexture); + } + + if (status != BUFFER_DONE && status != BUFFER_PRE_FLUSH) + { + prim = prim->next(); + } + } + + window().m_primlist->release_lock(); + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + if (index==0) bgfx::frame(); + + return 0; +} + +renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(int view, bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer) +{ + int vertices = 0; + + UINT32 blend = PRIMFLAG_GET_BLENDMODE((*prim)->flags); + while (*prim != nullptr) + { + switch ((*prim)->type) { - /** - * Try to stay in one Begin/End block as long as possible, - * since entering and leaving one is most expensive.. - */ case render_primitive::LINE: - // check if it's really a point -/* - if (((prim->bounds.x1 - prim->bounds.x0) == 0) && ((prim->bounds.y1 - prim->bounds.y0) == 0)) - { - curPrimitive=GL_POINTS; - } else { - curPrimitive=GL_LINES; - } - - if(pendingPrimitive!=GL_NO_PRIMITIVE && pendingPrimitive!=curPrimitive) - { - glEnd(); - pendingPrimitive=GL_NO_PRIMITIVE; - } - - if ( pendingPrimitive==GL_NO_PRIMITIVE ) - { - set_blendmode(sdl, PRIMFLAG_GET_BLENDMODE(prim->flags)); - } - - glColor4f(prim->color.r, prim->color.g, prim->color.b, prim->color.a); - - if(pendingPrimitive!=curPrimitive) - { - glBegin(curPrimitive); - pendingPrimitive=curPrimitive; - } - - // check if it's really a point - if (curPrimitive==GL_POINTS) - { - glVertex2f(prim->bounds.x0+hofs, prim->bounds.y0+vofs); - } - else - { - glVertex2f(prim->bounds.x0+hofs, prim->bounds.y0+vofs); - glVertex2f(prim->bounds.x1+hofs, prim->bounds.y1+vofs); - }*/ + put_line((*prim)->bounds.x0, (*prim)->bounds.y0, (*prim)->bounds.x1, (*prim)->bounds.y1, 1.0f, u32Color((*prim)->color.r * 255, (*prim)->color.g * 255, (*prim)->color.b * 255, (*prim)->color.a * 255), (ScreenVertex*)buffer->data + vertices, 1.0f); + vertices += 30; break; case render_primitive::QUAD: -/* - if(pendingPrimitive!=GL_NO_PRIMITIVE) - { - glEnd(); - pendingPrimitive=GL_NO_PRIMITIVE; - } + if ((*prim)->texture.base == nullptr) + { + put_packed_quad(*prim, WHITE_HASH, (ScreenVertex*)buffer->data + vertices); + vertices += 6; + } + else + { + const UINT32 hash = get_texture_hash(*prim); + if (atlas_valid && (*prim)->packable(PACKABLE_SIZE) && hash != 0 && m_hash_to_entry[hash].hash()) + { + put_packed_quad(*prim, hash, (ScreenVertex*)buffer->data + vertices); + vertices += 6; + } + else + { + if (vertices > 0) + { + return BUFFER_PRE_FLUSH; + } + render_textured_quad(view, *prim, buffer); + return BUFFER_EMPTY; + } + } + break; + + default: + // Unhandled + break; + } + + if ((*prim)->next() != nullptr && PRIMFLAG_GET_BLENDMODE((*prim)->next()->flags) != blend) + { + break; + } + + *prim = (*prim)->next(); + } + + if (*prim == nullptr) + { + return BUFFER_DONE; + } + if (vertices == 0) + { + return BUFFER_EMPTY; + } + return BUFFER_FLUSH; +} + +void renderer_bgfx::set_bgfx_state(UINT32 blend) +{ + uint64_t flags = BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_TEST_ALWAYS; + + switch (blend) + { + case BLENDMODE_NONE: + bgfx::setState(flags); + break; + case BLENDMODE_ALPHA: + bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)); + break; + case BLENDMODE_RGB_MULTIPLY: + bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO)); + break; + case BLENDMODE_ADD: + bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE)); + break; + } +} - glColor4f(prim->color.r, prim->color.g, prim->color.b, prim->color.a); +bool renderer_bgfx::update_atlas() +{ + bool atlas_dirty = check_for_dirty_atlas(); + + if (atlas_dirty) + { + m_hash_to_entry.clear(); - set_blendmode(sdl, PRIMFLAG_GET_BLENDMODE(prim->flags)); + std::vector<std::vector<rectangle_packer::packed_rectangle>> packed; + if (m_packer.pack(m_texinfo, packed, CACHE_SIZE)) + { + process_atlas_packs(packed); + } + else + { + packed.clear(); - texture = texture_update(window, prim, 0); + m_texinfo.clear(); + m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white)); + m_packer.pack(m_texinfo, packed, CACHE_SIZE); + process_atlas_packs(packed); - sdl->texVerticex[0]=prim->bounds.x0 + hofs; - sdl->texVerticex[1]=prim->bounds.y0 + vofs; - sdl->texVerticex[2]=prim->bounds.x1 + hofs; - sdl->texVerticex[3]=prim->bounds.y0 + vofs; - sdl->texVerticex[4]=prim->bounds.x1 + hofs; - sdl->texVerticex[5]=prim->bounds.y1 + vofs; - sdl->texVerticex[6]=prim->bounds.x0 + hofs; - sdl->texVerticex[7]=prim->bounds.y1 + vofs; + return false; + } + } + return true; +} - glDrawArrays(GL_QUADS, 0, 4); -*/ +void renderer_bgfx::process_atlas_packs(std::vector<std::vector<rectangle_packer::packed_rectangle>>& packed) +{ + for (std::vector<rectangle_packer::packed_rectangle> pack : packed) + { + for (rectangle_packer::packed_rectangle rect : pack) + { + if (rect.hash() == 0xffffffff) + { + continue; + } + m_hash_to_entry[rect.hash()] = rect; + const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(rect.format(), rect.width(), rect.height(), rect.rowpixels(), rect.palette(), rect.base()); + bgfx::updateTexture2D(m_texture_cache, 0, rect.x(), rect.y(), rect.width(), rect.height(), mem); + } + } +} + +UINT32 renderer_bgfx::get_texture_hash(render_primitive *prim) +{ +#if GIBBERISH + UINT32 xor_value = 0x87; + UINT32 hash = 0xdabeefed; + + int bpp = 2; + UINT32 format = PRIMFLAG_GET_TEXFORMAT(prim->flags); + if (format == TEXFORMAT_ARGB32 || format == TEXFORMAT_RGB32) + { + bpp = 4; + } + + for (int y = 0; y < prim->texture.height; y++) + { + UINT8 *base = reinterpret_cast<UINT8*>(prim->texture.base) + prim->texture.rowpixels * y; + for (int x = 0; x < prim->texture.width * bpp; x++) + { + hash += base[x] ^ xor_value; + } + } + return hash; +#else + return (reinterpret_cast<size_t>(prim->texture.base)) & 0xffffffff; +#endif +} + +bool renderer_bgfx::check_for_dirty_atlas() +{ + bool atlas_dirty = false; + + std::map<UINT32, rectangle_packer::packable_rectangle> acquired_infos; + for (render_primitive *prim = window().m_primlist->first(); prim != nullptr; prim = prim->next()) + { + bool pack = prim->packable(PACKABLE_SIZE); + if (prim->type == render_primitive::QUAD && prim->texture.base != nullptr && pack) + { + const UINT32 hash = get_texture_hash(prim); + // If this texture is packable and not currently in the atlas, prepare the texture for putting in the atlas + if ((hash != 0 && m_hash_to_entry[hash].hash() == 0 && acquired_infos[hash].hash() == 0) + || (hash != 0 && m_hash_to_entry[hash].hash() != hash && acquired_infos[hash].hash() == 0)) + { // Create create the texture and mark the atlas dirty + atlas_dirty = true; + + m_texinfo.push_back(rectangle_packer::packable_rectangle(hash, prim->flags & PRIMFLAG_TEXFORMAT_MASK, + prim->texture.width, prim->texture.height, + prim->texture.rowpixels, prim->texture.palette, prim->texture.base)); + acquired_infos[hash] = m_texinfo[m_texinfo.size() - 1]; + } + } + } + + if (m_texinfo.size() == 1) + { + atlas_dirty = true; + } + + return atlas_dirty; +} + +void renderer_bgfx::allocate_buffer(render_primitive *prim, UINT32 blend, bgfx::TransientVertexBuffer *buffer) +{ + int vertices = 0; + + bool mode_switched = false; + while (prim != nullptr && !mode_switched) + { + switch (prim->type) + { + case render_primitive::LINE: + vertices += 30; break; + case render_primitive::QUAD: + if (!prim->packable(PACKABLE_SIZE)) + { + if (prim->texture.base == nullptr) + { + vertices += 6; + } + else + { + mode_switched = true; + if (vertices == 0) + { + vertices += 6; + } + } + } + else + { + vertices += 6; + } + break; default: - throw emu_fatalerror("Unexpected render_primitive type"); + // Do nothing + break; } - } - window().m_primlist->release_lock(); - // Advance to next frame. Rendering thread will be kicked to - // process submitted rendering primitives. - bgfx::frame(); + prim = prim->next(); - return 0; + if (prim != nullptr && PRIMFLAG_GET_BLENDMODE(prim->flags) != blend) + { + mode_switched = true; + } + } + + if (vertices > 0 && bgfx::checkAvailTransientVertexBuffer(vertices, ScreenVertex::ms_decl)) + { + bgfx::allocTransientVertexBuffer(buffer, vertices, ScreenVertex::ms_decl); + } } diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h new file mode 100644 index 00000000000..86619eab718 --- /dev/null +++ b/src/osd/modules/render/drawbgfx.h @@ -0,0 +1,108 @@ +#pragma once + +#ifndef __RENDER_BGFX__ +#define __RENDER_BGFX__ + +#include <map> +#include <vector> + +#include "binpacker.h" + +/* sdl_info is the information about SDL for the current screen */ +class renderer_bgfx : public osd_renderer +{ +public: + renderer_bgfx(osd_window *w) + : osd_renderer(w, FLAG_NONE) + , m_dimensions(0, 0) + { + } + + virtual int create() override; + virtual int draw(const int update) override; +#ifdef OSD_SDL + virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override; +#else + virtual void save() override { } + virtual void record() override { } + virtual void toggle_fsfx() override { } +#endif + virtual void destroy() override; + virtual render_primitive_list *get_primitives() override + { + osd_dim wdim = window().get_size(); + window().target()->set_bounds(wdim.width(), wdim.height(), window().aspect()); + return &window().target()->get_primitives(); + } + +private: + struct ScreenVertex + { + float m_x; + float m_y; + float m_z; + UINT32 m_rgba; + float m_u; + float m_v; + + static void init() + { + ms_decl.begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) + .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) + .end(); + } + + static bgfx::VertexDecl ms_decl; + }; + + void allocate_buffer(render_primitive *prim, UINT32 blend, bgfx::TransientVertexBuffer *buffer); + enum buffer_status + { + BUFFER_PRE_FLUSH, + BUFFER_FLUSH, + BUFFER_EMPTY, + BUFFER_DONE + }; + buffer_status buffer_primitives(int view, bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer); + + void render_textured_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer); + + void put_packed_quad(render_primitive *prim, UINT32 hash, ScreenVertex* vertex); + void put_polygon(const float* coords, UINT32 num_coords, float r, UINT32 rgba, ScreenVertex* vertex); + void put_line(float x0, float y0, float x1, float y1, float r, UINT32 rgba, ScreenVertex* vertex, float fth = 1.0f); + + void set_bgfx_state(UINT32 blend); + + uint32_t u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a); + + bool check_for_dirty_atlas(); + bool update_atlas(); + void process_atlas_packs(std::vector<std::vector<rectangle_packer::packed_rectangle>>& packed); + const bgfx::Memory* mame_texture_data_to_bgfx_texture_data(UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base); + UINT32 get_texture_hash(render_primitive *prim); + + bgfx::ProgramHandle loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName); + bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName); + + bgfx::ProgramHandle m_progQuad; + bgfx::ProgramHandle m_progQuadTexture; + bgfx::UniformHandle m_s_texColor; + bgfx::FrameBufferHandle fbh; + bgfx::TextureHandle m_texture_cache; + + // Original display_mode + osd_dim m_dimensions; + + std::map<UINT32, rectangle_packer::packed_rectangle> m_hash_to_entry; + std::vector<rectangle_packer::packable_rectangle> m_texinfo; + rectangle_packer m_packer; + + uint32_t m_white[16*16]; + enum : uint16_t { CACHE_SIZE = 1024 }; + enum : uint32_t { PACKABLE_SIZE = 128 }; + enum : UINT32 { WHITE_HASH = 0x87654321 }; +}; + +#endif diff --git a/src/osd/modules/render/drawdd.cpp b/src/osd/modules/render/drawdd.cpp deleted file mode 100644 index fb82dff3c1f..00000000000 --- a/src/osd/modules/render/drawdd.cpp +++ /dev/null @@ -1,1317 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -//============================================================ -// -// drawdd.c - Win32 DirectDraw implementation -// -//============================================================ - -// standard windows headers -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <mmsystem.h> -#include <ddraw.h> -#undef interface - -// MAME headers -#include "emu.h" -#include "render.h" -#include "rendutil.h" -#include "rendersw.inc" - -// MAMEOS headers -#include "winmain.h" -#include "window.h" - - - -//============================================================ -// TYPE DEFINITIONS -//============================================================ - -typedef HRESULT (WINAPI *directdrawcreateex_ptr)(GUID FAR *lpGuid, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter); -typedef HRESULT (WINAPI *directdrawenumerateex_ptr)(LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags); - - -/* dd_info is the information about DirectDraw for the current screen */ -class renderer_dd : public osd_renderer -{ -public: - renderer_dd(osd_window *window) - : osd_renderer(window, FLAG_NONE), - width(0), - height(0), - refresh(0), - //adapter(0), - adapter_ptr(NULL), - clearouter(0), - blitwidth(0), blitheight(0), - //lastdest - ddraw(NULL), - primary(NULL), - back(NULL), - blit(NULL), - clipper(NULL), - gamma(NULL), - //DDSURFACEDESC2 primarydesc; - //DDSURFACEDESC2 blitdesc; - //DDSURFACEDESC2 origmode; - //ddcaps(0), - //helcaps(0), - membuffer(NULL), - membuffersize(0) - { } - - virtual ~renderer_dd() { } - - virtual int create() override; - virtual render_primitive_list *get_primitives() override; - virtual int draw(const int update) override; - virtual void save() override {}; - virtual void record() override {}; - virtual void toggle_fsfx() override {}; - virtual void destroy() override; - - int width, height; // current width, height - int refresh; // current refresh rate - -private: - - inline void update_outer_rects(); - - // surface management - int ddraw_create(); - int ddraw_create_surfaces(); - void ddraw_delete(); - void ddraw_delete_surfaces(); - int ddraw_verify_caps(); - int ddraw_test_cooperative(); - HRESULT create_surface(DDSURFACEDESC2 *desc, IDirectDrawSurface7 **surface, const char *type); - int create_clipper(); - - // drawing helpers - void compute_blit_surface_size(); - void blit_to_primary(int srcwidth, int srcheight); - - // video modes - int config_adapter_mode(); - void get_adapter_for_monitor(osd_monitor_info *monitor); - void pick_best_mode(); - - // various - void calc_fullscreen_margins(DWORD desc_width, DWORD desc_height, RECT *margins); - - - GUID adapter; // current display adapter - GUID * adapter_ptr; // pointer to current display adapter - int clearouter; // clear the outer areas? - - INT32 blitwidth, blitheight; // current blit width/height values - RECT lastdest; // last destination rectangle - - IDirectDraw7 * ddraw; // pointer to the DirectDraw object - IDirectDrawSurface7 * primary; // pointer to the primary surface object - IDirectDrawSurface7 * back; // pointer to the back buffer surface object - IDirectDrawSurface7 * blit; // pointer to the blit surface object - IDirectDrawClipper * clipper; // pointer to the clipper object - IDirectDrawGammaControl *gamma; // pointer to the gamma control object - - DDSURFACEDESC2 primarydesc; // description of the primary surface - DDSURFACEDESC2 blitdesc; // description of the blitting surface - DDSURFACEDESC2 origmode; // original video mode - - DDCAPS ddcaps; // capabilities of the device - DDCAPS helcaps; // capabilities of the hardware - - UINT8 * membuffer; // memory buffer for complex rendering - UINT32 membuffersize; // current size of the memory buffer -}; - - -/* monitor_enum_info holds information during a monitor enumeration */ -struct monitor_enum_info -{ - osd_monitor_info * monitor; // pointer to monitor we want - GUID guid; // GUID of the one we found - GUID * guid_ptr; // pointer to our GUID - int foundit; // TRUE if we found what we wanted -}; - - -/* mode_enum_info holds information during a display mode enumeration */ -struct mode_enum_info -{ - renderer_dd * renderer; - osd_window * window; - INT32 minimum_width, minimum_height; - INT32 target_width, target_height; - double target_refresh; - float best_score; -}; - - - -//============================================================ -// GLOBALS -//============================================================ - -static HINSTANCE dllhandle; -static directdrawcreateex_ptr directdrawcreateex; -static directdrawenumerateex_ptr directdrawenumerateex; - - - -//============================================================ -// INLINES -//============================================================ - -inline void renderer_dd::update_outer_rects() -{ - clearouter = (back != NULL) ? 3 : 1; -} - - -static inline int better_mode(int width0, int height0, int width1, int height1, float desired_aspect) -{ - float aspect0 = (float)width0 / (float)height0; - float aspect1 = (float)width1 / (float)height1; - return (fabs(desired_aspect - aspect0) < fabs(desired_aspect - aspect1)) ? 0 : 1; -} - - - -//============================================================ -// PROTOTYPES -//============================================================ - -// core functions -static void drawdd_exit(void); - - - -//============================================================ -// drawnone_create -//============================================================ - -static osd_renderer *drawdd_create(osd_window *window) -{ - return global_alloc(renderer_dd(window)); -} - - -//============================================================ -// drawdd_init -//============================================================ - -int drawdd_init(running_machine &machine, osd_draw_callbacks *callbacks) -{ - // dynamically grab the create function from ddraw.dll - dllhandle = LoadLibrary(TEXT("ddraw.dll")); - if (dllhandle == NULL) - { - osd_printf_verbose("DirectDraw: Unable to access ddraw.dll\n"); - return 1; - } - - // import the create function - directdrawcreateex = (directdrawcreateex_ptr)GetProcAddress(dllhandle, "DirectDrawCreateEx"); - if (directdrawcreateex == NULL) - { - osd_printf_verbose("DirectDraw: Unable to find DirectDrawCreateEx\n"); - FreeLibrary(dllhandle); - dllhandle = NULL; - return 1; - } - - // import the enumerate function - directdrawenumerateex = (directdrawenumerateex_ptr)GetProcAddress(dllhandle, "DirectDrawEnumerateExA"); - if (directdrawenumerateex == NULL) - { - osd_printf_verbose("DirectDraw: Unable to find DirectDrawEnumerateExA\n"); - FreeLibrary(dllhandle); - dllhandle = NULL; - return 1; - } - - // fill in the callbacks - memset(callbacks, 0, sizeof(*callbacks)); - callbacks->exit = drawdd_exit; - callbacks->create = drawdd_create; - - osd_printf_verbose("DirectDraw: Using DirectDraw 7\n"); - return 0; -} - - - -//============================================================ -// drawdd_exit -//============================================================ - -static void drawdd_exit(void) -{ - if (dllhandle != NULL) - FreeLibrary(dllhandle); -} - - - -//============================================================ -// drawdd_window_init -//============================================================ - -int renderer_dd::create() -{ - // configure the adapter for the mode we want - if (config_adapter_mode()) - { - osd_printf_error("Unable to configure adapter.\n"); - goto error; - } - - // create the ddraw object - if (ddraw_create()) - { - osd_printf_error("Unable to create ddraw object.\n"); - goto error; - } - - return 0; - -error: - destroy(); - osd_printf_error("Unable to initialize DirectDraw.\n"); - return 1; -} - - - -//============================================================ -// drawdd_window_destroy -//============================================================ - -void renderer_dd::destroy() -{ - // delete the ddraw object - ddraw_delete(); -} - - - -//============================================================ -// drawdd_window_get_primitives -//============================================================ - -render_primitive_list *renderer_dd::get_primitives() -{ - compute_blit_surface_size(); - window().target()->set_bounds(blitwidth, blitheight, 0); - window().target()->set_max_update_rate((refresh == 0) ? origmode.dwRefreshRate : refresh); - - return &window().target()->get_primitives(); -} - - - -//============================================================ -// drawdd_window_draw -//============================================================ - -int renderer_dd::draw(const int update) -{ - render_primitive *prim; - int usemembuffer = FALSE; - HRESULT result; - - // if we're updating, remember to erase the outer stuff - if (update) - update_outer_rects(); - - // if we have a ddraw object, check the cooperative level - if (ddraw_test_cooperative()) - return 1; - - // get the size; if we're too small, delete the existing surfaces - if (blitwidth > blitdesc.dwWidth || blitheight > blitdesc.dwHeight) - ddraw_delete_surfaces(); - - // if we need to create surfaces, do it now - if (blit == NULL && ddraw_create_surfaces() != 0) - return 1; - - // select our surface and lock it - result = IDirectDrawSurface7_Lock(blit, NULL, &blitdesc, DDLOCK_WAIT, NULL); - if (result == DDERR_SURFACELOST) - { - osd_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n"); - ddraw_delete_surfaces(); - return 1; - } - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result); - return 1; - } - - // render to it - window().m_primlist->acquire_lock(); - - // scan the list of primitives for tricky stuff - for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next()) - if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE || - (prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32)) - { - usemembuffer = TRUE; - break; - } - - // if we're using the memory buffer, draw offscreen first and then copy - if (usemembuffer) - { - int x, y; - - // based on the target format, use one of our standard renderers - switch (blitdesc.ddpfPixelFormat.dwRBitMask) - { - case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; - case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; - case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; - case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth); break; - default: - osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); - break; - } - - // handle copying to both 16bpp and 32bpp destinations - for (y = 0; y < blitheight; y++) - { - if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 32) - { - UINT32 *src = (UINT32 *)membuffer + y * blitwidth; - UINT32 *dst = (UINT32 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); - for (x = 0; x < blitwidth; x++) - *dst++ = *src++; - } - else if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 16) - { - UINT16 *src = (UINT16 *)membuffer + y * blitwidth; - UINT16 *dst = (UINT16 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch); - for (x = 0; x < blitwidth; x++) - *dst++ = *src++; - } - } - - } - - // otherwise, draw directly - else - { - // based on the target format, use one of our standard renderers - switch (blitdesc.ddpfPixelFormat.dwRBitMask) - { - case 0x00ff0000: software_renderer<UINT32, 0,0,0, 16,8,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; - case 0x000000ff: software_renderer<UINT32, 0,0,0, 0,8,16, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break; - case 0xf800: software_renderer<UINT16, 3,2,3, 11,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; - case 0x7c00: software_renderer<UINT16, 3,3,3, 10,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break; - default: - osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask); - break; - } - } - window().m_primlist->release_lock(); - - // unlock and blit - result = IDirectDrawSurface7_Unlock(blit, NULL); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result); - - // sync to VBLANK - if ((video_config.waitvsync || video_config.syncrefresh) && window().machine().video().throttled() && (!window().fullscreen() || back == NULL)) - { - result = IDirectDraw7_WaitForVerticalBlank(ddraw, DDWAITVB_BLOCKBEGIN, NULL); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); - } - - // complete the blitting - blit_to_primary(blitwidth, blitheight); - return 0; -} - - - -//============================================================ -// ddraw_create -//============================================================ - -int renderer_dd::ddraw_create() -{ - HRESULT result; - int verify; - - // if a device exists, free it - if (ddraw != NULL) - ddraw_delete(); - - // create the DirectDraw object - result = (*directdrawcreateex)(adapter_ptr, (LPVOID *)&ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X during DirectDrawCreateEx call\n", (int)result); - goto error; - } - - // verify the caps - verify = ddraw_verify_caps(); - if (verify == 2) - { - osd_printf_error("DirectDraw: Error - Device does not meet minimum requirements for DirectDraw rendering\n"); - goto error; - } - if (verify == 1) - osd_printf_verbose("DirectDraw: Warning - Device may not perform well for DirectDraw rendering\n"); - - // set the cooperative level - // for non-window modes, we will use full screen here - result = IDirectDraw7_SetCooperativeLevel(ddraw, win_window_list->m_hwnd, DDSCL_SETFOCUSWINDOW); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(FOCUSWINDOW) call\n", (int)result); - goto error; - } - result = IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_SETDEVICEWINDOW | (window().fullscreen() ? DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE : DDSCL_NORMAL)); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_SetCooperativeLevel(DEVICEWINDOW) call\n", (int)result); - goto error; - } - - // full screen mode: set the resolution - if (window().fullscreen() && video_config.switchres) - { - result = IDirectDraw7_SetDisplayMode(ddraw, width, height, 32, refresh, 0); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X attempting to set video mode %dx%d@%d call\n", (int)result, width, height, refresh); - goto error; - } - } - - return ddraw_create_surfaces(); - -error: - ddraw_delete(); - return 1; -} - - - -//============================================================ -// ddraw_create_surfaces -//============================================================ - -int renderer_dd::ddraw_create_surfaces() -{ - HRESULT result; - - // make a description of the primary surface - memset(&primarydesc, 0, sizeof(primarydesc)); - primarydesc.dwSize = sizeof(primarydesc); - primarydesc.dwFlags = DDSD_CAPS; - primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - // for triple-buffered full screen mode, allocate flipping surfaces - if (window().fullscreen() && video_config.triplebuf) - { - primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT; - primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; - primarydesc.dwBackBufferCount = 2; - } - - // create the primary surface and report errors - result = create_surface(&primarydesc, &primary, "primary"); - if (result != DD_OK) goto error; - - // full screen mode: get the back surface - back = NULL; - if (window().fullscreen() && video_config.triplebuf) - { - DDSCAPS2 caps = { DDSCAPS_BACKBUFFER }; - result = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &back); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X getting attached back surface\n", (int)result); - goto error; - } - } - - // now make a description of our blit surface, based on the primary surface - if (blitwidth == 0 || blitheight == 0) - compute_blit_surface_size(); - blitdesc = primarydesc; - blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; - blitdesc.dwWidth = blitwidth; - blitdesc.dwHeight = blitheight; - blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; - - // then create the blit surface, fall back to system memory if video mem doesn't work - result = create_surface(&blitdesc, &blit, "blit"); - if (result != DD_OK) - { - blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY; - result = create_surface(&blitdesc, &blit, "blit"); - } - if (result != DD_OK) goto error; - - // create a memory buffer for offscreen drawing - if (membuffersize < blitwidth * blitheight * 4) - { - membuffersize = blitwidth * blitheight * 4; - global_free_array(membuffer); - membuffer = global_alloc_array(UINT8, membuffersize); - } - if (membuffer == NULL) - goto error; - - // create a clipper for windowed mode - if (!window().fullscreen() && create_clipper()) - goto error; - - // full screen mode: set the gamma - if (window().fullscreen()) - { - // only set the gamma if it's not 1.0f - windows_options &options = downcast<windows_options &>(window().machine().options()); - float brightness = options.full_screen_brightness(); - float contrast = options.full_screen_contrast(); - float fgamma = options.full_screen_gamma(); - if (brightness != 1.0f || contrast != 1.0f || fgamma != 1.0f) - { - // see if we can get a GammaControl object - result = IDirectDrawSurface_QueryInterface(primary, WRAP_REFIID(IID_IDirectDrawGammaControl), (void **)&gamma); - if (result != DD_OK) - { - osd_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n"); - this->gamma = NULL; - } - - // proceed if we can - if (this->gamma != NULL) - { - DDGAMMARAMP ramp; - int i; - - // create a standard ramp and set it - for (i = 0; i < 256; i++) - ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, fgamma) << 8; - - // attempt to set it - result = IDirectDrawGammaControl_SetGammaRamp(this->gamma, 0, &ramp); - if (result != DD_OK) - osd_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result); - } - } - } - - // force some updates - update_outer_rects(); - return 0; - -error: - ddraw_delete_surfaces(); - return 1; -} - - - -//============================================================ -// ddraw_delete -//============================================================ - -void renderer_dd::ddraw_delete() -{ - // free surfaces - ddraw_delete_surfaces(); - - // restore resolutions - if (ddraw != NULL) - IDirectDraw7_RestoreDisplayMode(ddraw); - - // reset cooperative level - if (ddraw != NULL && window().m_hwnd != NULL) - IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_NORMAL); - - // release the DirectDraw object itself - if (ddraw != NULL) - IDirectDraw7_Release(ddraw); - ddraw = NULL; -} - - - -//============================================================ -// ddraw_delete_surfaces -//============================================================ - -void renderer_dd::ddraw_delete_surfaces() -{ - // release the gamma control - if (gamma != NULL) - IDirectDrawGammaControl_Release(gamma); - gamma = NULL; - - // release the clipper - if (clipper != NULL) - IDirectDrawClipper_Release(clipper); - clipper = NULL; - - // free the memory buffer - global_free_array(membuffer); - membuffer = NULL; - membuffersize = 0; - - // release the blit surface - if (blit != NULL) - IDirectDrawSurface7_Release(blit); - blit = NULL; - - // release the back surface - if (back != NULL) - IDirectDrawSurface7_Release(back); - back = NULL; - - // release the primary surface - if (primary != NULL) - IDirectDrawSurface7_Release(primary); - primary = NULL; -} - - - -//============================================================ -// ddraw_verify_caps -//============================================================ - -int renderer_dd::ddraw_verify_caps() -{ - int retval = 0; - HRESULT result; - - // get the capabilities - ddcaps.dwSize = sizeof(ddcaps); - helcaps.dwSize = sizeof(helcaps); - result = IDirectDraw7_GetCaps(ddraw, &ddcaps, &helcaps); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X during IDirectDraw7_GetCaps call\n", (int)result); - return 1; - } - - // determine if hardware stretching is available - if ((ddcaps.dwCaps & DDCAPS_BLTSTRETCH) == 0) - { - osd_printf_verbose("DirectDraw: Warning - Device does not support hardware stretching\n"); - retval = 1; - } - - return retval; -} - - - -//============================================================ -// ddraw_test_cooperative -//============================================================ - -int renderer_dd::ddraw_test_cooperative() -{ - HRESULT result; - - // check our current status; if we lost the device, punt to GDI - result = IDirectDraw7_TestCooperativeLevel(ddraw); - switch (result) - { - // punt to GDI if someone else has exclusive mode - case DDERR_NOEXCLUSIVEMODE: - case DDERR_EXCLUSIVEMODEALREADYSET: - ddraw_delete_surfaces(); - return 1; - - // if we're ok, but we don't have a primary surface, create one - default: - case DD_OK: - if (primary == NULL) - return ddraw_create_surfaces(); - return 0; - } -} - - - -//============================================================ -// create_surface -//============================================================ - -HRESULT renderer_dd::create_surface(DDSURFACEDESC2 *desc, IDirectDrawSurface7 **surface, const char *type) -{ - HRESULT result; - - // create the surface as requested - result = IDirectDraw7_CreateSurface(ddraw, desc, surface, NULL); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X creating %s surface\n", (int)result, type); - return result; - } - - // get a description of the primary surface - result = IDirectDrawSurface7_GetSurfaceDesc(*surface, desc); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X getting %s surface desciption\n", (int)result, type); - IDirectDrawSurface7_Release(*surface); - *surface = NULL; - return result; - } - - // print out the good stuff - osd_printf_verbose("DirectDraw: %s surface created: %dx%dx%d (R=%08X G=%08X B=%08X)\n", - type, - (int)desc->dwWidth, - (int)desc->dwHeight, - (int)desc->ddpfPixelFormat.dwRGBBitCount, - (UINT32)desc->ddpfPixelFormat.dwRBitMask, - (UINT32)desc->ddpfPixelFormat.dwGBitMask, - (UINT32)desc->ddpfPixelFormat.dwBBitMask); - return result; -} - - - -//============================================================ -// create_clipper -//============================================================ - -int renderer_dd::create_clipper() -{ - HRESULT result; - - // create a clipper for the primary surface - result = IDirectDraw7_CreateClipper(ddraw, 0, &clipper, NULL); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X creating clipper\n", (int)result); - return 1; - } - - // set the clipper's hwnd - result = IDirectDrawClipper_SetHWnd(clipper, 0, window().m_hwnd); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X setting clipper hwnd\n", (int)result); - return 1; - } - - // set the clipper on the primary surface - result = IDirectDrawSurface7_SetClipper(primary, clipper); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X setting clipper on primary surface\n", (int)result); - return 1; - } - return 0; -} - - - -//============================================================ -// compute_blit_surface_size -//============================================================ - -void renderer_dd::compute_blit_surface_size() -{ - INT32 newwidth, newheight; - int xscale, yscale; - RECT client; - - // start with the minimum size - window().target()->compute_minimum_size(newwidth, newheight); - - // get the window's client rectangle - GetClientRect(window().m_hwnd, &client); - - // hardware stretch case: apply prescale - if (video_config.hwstretch) - { - int prescale = (window().prescale() < 1) ? 1 : window().prescale(); - - // clamp the prescale to something smaller than the target bounds - xscale = prescale; - while (xscale > 1 && newwidth * xscale > rect_width(&client)) - xscale--; - yscale = prescale; - while (yscale > 1 && newheight * yscale > rect_height(&client)) - yscale--; - } - - // non stretch case - else - { - INT32 target_width = rect_width(&client); - INT32 target_height = rect_height(&client); - float desired_aspect = 1.0f; - - // compute the appropriate visible area if we're trying to keepaspect - if (video_config.keepaspect) - { - osd_monitor_info *monitor = window().winwindow_video_window_monitor(NULL); - window().target()->compute_visible_area(target_width, target_height, monitor->aspect(), window().target()->orientation(), target_width, target_height); - desired_aspect = (float)target_width / (float)target_height; - } - - // compute maximum integral scaling to fit the window - xscale = (target_width + 2) / newwidth; - yscale = (target_height + 2) / newheight; - - // try a little harder to keep the aspect ratio if desired - if (video_config.keepaspect) - { - // if we could stretch more in the X direction, and that makes a better fit, bump the xscale - while (newwidth * (xscale + 1) <= rect_width(&client) && - better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect)) - xscale++; - - // if we could stretch more in the Y direction, and that makes a better fit, bump the yscale - while (newheight * (yscale + 1) <= rect_height(&client) && - better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect)) - yscale++; - - // now that we've maxed out, see if backing off the maximally stretched one makes a better fit - if (rect_width(&client) - newwidth * xscale < rect_height(&client) - newheight * yscale) - { - while (xscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect)) - xscale--; - } - else - { - while (yscale > 1 && better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect)) - yscale--; - } - } - } - - // ensure at least a scale factor of 1 - if (xscale == 0) xscale = 1; - if (yscale == 0) yscale = 1; - - // apply the final scale - newwidth *= xscale; - newheight *= yscale; - if (newwidth != blitwidth || newheight != blitheight) - { - // force some updates - update_outer_rects(); - osd_printf_verbose("DirectDraw: New blit size = %dx%d\n", newwidth, newheight); - } - blitwidth = newwidth; - blitheight = newheight; -} - - - -//============================================================ -// calc_fullscreen_margins -//============================================================ - -void renderer_dd::calc_fullscreen_margins(DWORD desc_width, DWORD desc_height, RECT *margins) -{ - margins->left = 0; - margins->top = 0; - margins->right = desc_width; - margins->bottom = desc_height; - - if (window().win_has_menu()) - { - static int height_with_menubar = 0; - if (height_with_menubar == 0) - { - RECT with_menu = { 100, 100, 200, 200 }; - RECT without_menu = { 100, 100, 200, 200 }; - AdjustWindowRect(&with_menu, WS_OVERLAPPED, TRUE); - AdjustWindowRect(&without_menu, WS_OVERLAPPED, FALSE); - height_with_menubar = (with_menu.bottom - with_menu.top) - (without_menu.bottom - without_menu.top); - } - margins->top = height_with_menubar; - } -} - - - -//============================================================ -// blit_to_primary -//============================================================ - -void renderer_dd::blit_to_primary(int srcwidth, int srcheight) -{ - IDirectDrawSurface7 *target = (back != NULL) ? back : primary; - osd_monitor_info *monitor = window().winwindow_video_window_monitor(NULL); - DDBLTFX blitfx = { sizeof(DDBLTFX) }; - RECT clear, outer, dest, source; - INT32 dstwidth, dstheight; - HRESULT result; - - // compute source rect - source.left = source.top = 0; - source.right = srcwidth; - source.bottom = srcheight; - - // compute outer rect -- windowed version - if (!window().fullscreen()) - { - GetClientRect(window().m_hwnd, &outer); - ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[0]); - ClientToScreen(window().m_hwnd, &((LPPOINT)&outer)[1]); - - // adjust to be relative to the monitor - osd_rect pos = monitor->position_size(); - outer.left -= pos.left(); - outer.right -= pos.left(); - outer.top -= pos.top(); - outer.bottom -= pos.top(); - } - - // compute outer rect -- full screen version - else - { - calc_fullscreen_margins(primarydesc.dwWidth, primarydesc.dwHeight, &outer); - } - - // if we're respecting the aspect ratio, we need to adjust to fit - dstwidth = rect_width(&outer); - dstheight = rect_height(&outer); - if (!video_config.hwstretch) - { - // trim the source if necessary - if (rect_width(&outer) < srcwidth) - { - source.left += (srcwidth - rect_width(&outer)) / 2; - source.right = source.left + rect_width(&outer); - } - if (rect_height(&outer) < srcheight) - { - source.top += (srcheight - rect_height(&outer)) / 2; - source.bottom = source.top + rect_height(&outer); - } - - // match the destination and source sizes - dstwidth = srcwidth = source.right - source.left; - dstheight = srcheight = source.bottom - source.top; - } - else if (video_config.keepaspect) - { - // compute the appropriate visible area - window().target()->compute_visible_area(rect_width(&outer), rect_height(&outer), monitor->aspect(), window().target()->orientation(), dstwidth, dstheight); - } - - // center within - dest.left = outer.left + (rect_width(&outer) - dstwidth) / 2; - dest.right = dest.left + dstwidth; - dest.top = outer.top + (rect_height(&outer) - dstheight) / 2; - dest.bottom = dest.top + dstheight; - - // compare against last destination; if different, force a redraw - if (dest.left != lastdest.left || dest.right != lastdest.right || dest.top != lastdest.top || dest.bottom != lastdest.bottom) - { - lastdest = dest; - update_outer_rects(); - } - - // clear outer rects if we need to - if (clearouter != 0) - { - clearouter--; - - // clear the left edge - if (dest.left > outer.left) - { - clear = outer; - clear.right = dest.left; - result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); - } - - // clear the right edge - if (dest.right < outer.right) - { - clear = outer; - clear.left = dest.right; - result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); - } - - // clear the top edge - if (dest.top > outer.top) - { - clear = outer; - clear.bottom = dest.top; - result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); - } - - // clear the bottom edge - if (dest.bottom < outer.bottom) - { - clear = outer; - clear.top = dest.bottom; - result = IDirectDrawSurface_Blt(target, &clear, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blitfx); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X clearing the screen\n", (int)result); - } - } - - // do the blit - result = IDirectDrawSurface7_Blt(target, &dest, blit, &source, DDBLT_WAIT, NULL); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X blitting to the screen\n", (int)result); - - // page flip if triple buffered - if (window().fullscreen() && back != NULL) - { - result = IDirectDrawSurface7_Flip(primary, NULL, DDFLIP_WAIT); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); - } -} - - - -//============================================================ -// config_adapter_mode -//============================================================ - -int renderer_dd::config_adapter_mode() -{ - DDDEVICEIDENTIFIER2 identifier; - HRESULT result; - - // choose the monitor number - get_adapter_for_monitor(window().monitor()); - - // create a temporary DirectDraw object - result = (*directdrawcreateex)(adapter_ptr, (LPVOID *)&ddraw, WRAP_REFIID(IID_IDirectDraw7), NULL); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X during DirectDrawCreateEx call\n", (int)result); - return 1; - } - - // get the identifier - result = IDirectDraw7_GetDeviceIdentifier(ddraw, &identifier, 0); - if (result != DD_OK) - { - osd_printf_error("Error getting identifier for device\n"); - return 1; - } - osd_printf_verbose("DirectDraw: Configuring device %s\n", identifier.szDescription); - - // get the current display mode - memset(&origmode, 0, sizeof(origmode)); - origmode.dwSize = sizeof(origmode); - result = IDirectDraw7_GetDisplayMode(ddraw, &origmode); - if (result != DD_OK) - { - osd_printf_verbose("DirectDraw: Error %08X getting current display mode\n", (int)result); - IDirectDraw7_Release(ddraw); - return 1; - } - - // choose a resolution: full screen mode case - if (window().fullscreen()) - { - // default to the current mode exactly - width = origmode.dwWidth; - height = origmode.dwHeight; - refresh = origmode.dwRefreshRate; - - // if we're allowed to switch resolutions, override with something better - if (video_config.switchres) - pick_best_mode(); - } - - // release the DirectDraw object - IDirectDraw7_Release(ddraw); - ddraw = NULL; - - // if we're not changing resolutions, make sure we have a resolution we can handle - if (!window().fullscreen() || !video_config.switchres) - { - switch (origmode.ddpfPixelFormat.dwRBitMask) - { - case 0x00ff0000: - case 0x000000ff: - case 0xf800: - case 0x7c00: - break; - - default: - osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)origmode.ddpfPixelFormat.dwRBitMask, (int)origmode.ddpfPixelFormat.dwGBitMask, (int)origmode.ddpfPixelFormat.dwBBitMask); - return 1; - } - } - - return 0; -} - - - -//============================================================ -// monitor_enum_callback -//============================================================ - -static BOOL WINAPI monitor_enum_callback(GUID FAR *guid, LPSTR description, LPSTR name, LPVOID context, HMONITOR hmonitor) -{ - monitor_enum_info *einfo = (monitor_enum_info *)context; - - // do we match the desired monitor? - if (hmonitor == *((HMONITOR *)einfo->monitor->oshandle()) || (hmonitor == NULL && einfo->monitor->is_primary())) - { - einfo->guid_ptr = (guid != NULL) ? &einfo->guid : NULL; - if (guid != NULL) - einfo->guid = *guid; - einfo->foundit = TRUE; - } - return 1; -} - - - -//============================================================ -// get_adapter_for_monitor -//============================================================ - -void renderer_dd::get_adapter_for_monitor(osd_monitor_info *monitor) -{ - monitor_enum_info einfo; - HRESULT result; - - // try to find our monitor - memset(&einfo, 0, sizeof(einfo)); - einfo.monitor = monitor; - result = (*directdrawenumerateex)(monitor_enum_callback, &einfo, DDENUM_ATTACHEDSECONDARYDEVICES); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X during DirectDrawEnumerateEx call\n", (int)result); - - // set up the adapter - if (einfo.foundit && einfo.guid_ptr != NULL) - { - adapter = einfo.guid; - adapter_ptr = &adapter; - } - else - adapter_ptr = NULL; -} - - - -//============================================================ -// enum_modes_callback -//============================================================ - -static HRESULT WINAPI enum_modes_callback(LPDDSURFACEDESC2 desc, LPVOID context) -{ - float size_score, refresh_score, final_score; - mode_enum_info *einfo = (mode_enum_info *)context; - renderer_dd *dd = einfo->renderer; - - // skip non-32 bit modes - if (desc->ddpfPixelFormat.dwRGBBitCount != 32) - return DDENUMRET_OK; - - // compute initial score based on difference between target and current - size_score = 1.0f / (1.0f + fabs((float)((INT32)desc->dwWidth - einfo->target_width)) + fabs((float)((INT32)desc->dwHeight - einfo->target_height))); - - // if the mode is too small, give a big penalty - if (desc->dwWidth < einfo->minimum_width || desc->dwHeight < einfo->minimum_height) - size_score *= 0.01f; - - // if mode is smaller than we'd like, it only scores up to 0.1 - if (desc->dwWidth < einfo->target_width || desc->dwHeight < einfo->target_height) - size_score *= 0.1f; - - // if we're looking for a particular mode, that's a winner - if (desc->dwWidth == einfo->window->m_win_config.width && desc->dwHeight == einfo->window->m_win_config.height) - size_score = 2.0f; - - // compute refresh score - refresh_score = 1.0f / (1.0f + fabs((double)desc->dwRefreshRate - einfo->target_refresh)); - - // if refresh is smaller than we'd like, it only scores up to 0.1 - if ((double)desc->dwRefreshRate < einfo->target_refresh) - refresh_score *= 0.1f; - - // if we're looking for a particular refresh, make sure it matches - if (desc->dwRefreshRate == einfo->window->m_win_config.refresh) - refresh_score = 2.0f; - - // weight size and refresh equally - final_score = size_score + refresh_score; - - // best so far? - osd_printf_verbose(" %4dx%4d@%3dHz -> %f\n", (int)desc->dwWidth, (int)desc->dwHeight, (int)desc->dwRefreshRate, final_score * 1000.0f); - if (final_score > einfo->best_score) - { - einfo->best_score = final_score; - dd->width = desc->dwWidth; - dd->height = desc->dwHeight; - dd->refresh = desc->dwRefreshRate; - } - return DDENUMRET_OK; -} - - - -//============================================================ -// pick_best_mode -//============================================================ - -void renderer_dd::pick_best_mode() -{ - mode_enum_info einfo; - HRESULT result; - - // determine the minimum width/height for the selected target - // note: technically we should not be calling this from an alternate window - // thread; however, it is only done during init time, and the init code on - // the main thread is waiting for us to finish, so it is safe to do so here - window().target()->compute_minimum_size(einfo.minimum_width, einfo.minimum_height); - - // use those as the target for now - einfo.target_width = einfo.minimum_width * MAX(1, window().prescale()); - einfo.target_height = einfo.minimum_height * MAX(1, window().prescale()); - - // determine the refresh rate of the primary screen - einfo.target_refresh = 60.0; - const screen_device *primary_screen = window().machine().config().first_screen(); - if (primary_screen != NULL) - einfo.target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh_attoseconds()); - printf("Target refresh = %f\n", einfo.target_refresh); - - // if we're not stretching, allow some slop on the minimum since we can handle it - if (!video_config.hwstretch) - { - einfo.minimum_width -= 4; - einfo.minimum_height -= 4; - } - - // if we are stretching, aim for a mode approximately 2x the game's resolution - else if (window().prescale() <= 1) - { - einfo.target_width *= 2; - einfo.target_height *= 2; - } - - // fill in the rest of the data - einfo.window = &window(); - einfo.renderer = this; - einfo.best_score = 0.0f; - - // enumerate the modes - osd_printf_verbose("DirectDraw: Selecting video mode...\n"); - result = IDirectDraw7_EnumDisplayModes(ddraw, DDEDM_REFRESHRATES, NULL, &einfo, enum_modes_callback); - if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X during EnumDisplayModes call\n", (int)result); - osd_printf_verbose("DirectDraw: Mode selected = %4dx%4d@%3dHz\n", width, height, refresh); -} diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp index 4a2744e4068..728b0810290 100644 --- a/src/osd/modules/render/drawogl.cpp +++ b/src/osd/modules/render/drawogl.cpp @@ -30,10 +30,6 @@ #include "modules/lib/osdlib.h" #include "modules/lib/osdobj_common.h" -#if defined(OSD_WINDOWS) && !defined(SDLMAME_SDL2) -#define SDLMAME_SDL2 0 -#endif - // OpenGL headers #include "modules/opengl/osd_opengl.h" @@ -344,7 +340,7 @@ private: HMODULE win_gl_context::m_module; -#elif SDLMAME_SDL2 +#else class sdl_gl_context : public osd_gl_context { @@ -395,51 +391,6 @@ private: char m_error[256]; }; -#else -// SDL 1.2 -class sdl12_gl_context : public osd_gl_context -{ -public: - sdl12_gl_context(SDL_Surface *window) : osd_gl_context(), m_window(window) - { - m_error[0] = 0; - } - virtual ~sdl12_gl_context() - { - } - virtual void MakeCurrent() - { - } - - virtual int SetSwapInterval(const int swap) - { - // Not supported on 1.2 - return 0; - } - - virtual const char *LastErrorMsg() - { - if (m_error[0] == 0) - return NULL; - else - return m_error; - } - - virtual void *getProcAddress(const char *proc) - { - return SDL_GL_GetProcAddress(proc); - } - - virtual void SwapBuffer() - { - SDL_GL_SwapBuffers(); - } - -private: - SDL_Surface *m_window; - char m_error[256]; -}; - #endif //============================================================ @@ -766,10 +717,8 @@ int drawogl_init(running_machine &machine, osd_draw_callbacks *callbacks) load_gl_lib(machine); #if defined(OSD_WINDOWS) osd_printf_verbose("Using Windows OpenGL driver\n"); -#elif SDLMAME_SDL2 - osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); #else - osd_printf_verbose("Using SDL single-window OpenGL driver (SDL 1.2)\n"); + osd_printf_verbose("Using SDL multi-window OpenGL driver (SDL 2.0+)\n"); #endif return 0; @@ -1035,10 +984,8 @@ int sdl_info_ogl::create() // create renderer #if defined(OSD_WINDOWS) m_gl_context = global_alloc(win_gl_context(window().m_hwnd)); -#elif SDLMAME_SDL2 - m_gl_context = global_alloc(sdl_gl_context(window().sdl_window())); #else - m_gl_context = global_alloc(sdl12_gl_context(window().sdl_surface())); + m_gl_context = global_alloc(sdl_gl_context(window().sdl_window())); #endif if (m_gl_context->LastErrorMsg() != NULL) { @@ -1530,11 +1477,9 @@ int sdl_info_ogl::draw(const int update) if (m_init_context) { // do some one-time OpenGL setup -#if SDLMAME_SDL2 // FIXME: SRGB conversion is working on SDL2, may be of use // when we eventually target gamma and monitor profiles. //glEnable(GL_FRAMEBUFFER_SRGB); -#endif glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); @@ -1560,11 +1505,6 @@ int sdl_info_ogl::draw(const int update) loadGLExtensions(); } -#if !defined(OSD_WINDOWS) && !SDLMAME_SDL2 - // force all textures to be regenerated - destroy_all_textures(); -#endif - m_surf_w = m_width; m_surf_h = m_height; diff --git a/src/osd/modules/render/drawsdl.cpp b/src/osd/modules/render/drawsdl.cpp index 221ac79ef4d..b9a40038082 100644 --- a/src/osd/modules/render/drawsdl.cpp +++ b/src/osd/modules/render/drawsdl.cpp @@ -40,11 +40,9 @@ struct sdl_scale_mode; -#if (SDLMAME_SDL2) #define DRAW2_SCALEMODE_NEAREST "0" #define DRAW2_SCALEMODE_LINEAR "1" #define DRAW2_SCALEMODE_BEST "2" -#endif /* sdl_info is the information about SDL for the current screen */ class sdl_info : public osd_renderer @@ -53,12 +51,8 @@ public: sdl_info(osd_window *w, int extra_flags) : osd_renderer(w, extra_flags), - #if (SDLMAME_SDL2) m_sdl_renderer(NULL), m_texture_id(NULL), - #else - m_yuvsurf(NULL), - #endif m_yuv_lookup(NULL), m_yuv_bitmap(NULL), //m_hw_scale_width(0), @@ -88,24 +82,14 @@ public: private: void destroy_all_textures(); void yuv_init(); -#if (SDLMAME_SDL2) void setup_texture(const osd_dim &size); -#endif void yuv_lookup_set(unsigned int pen, unsigned char red, unsigned char green, unsigned char blue); -#if (!SDLMAME_SDL2) - void yuv_overlay_init(); -#endif - INT32 m_blittimer; -#if (SDLMAME_SDL2) SDL_Renderer *m_sdl_renderer; SDL_Texture *m_texture_id; -#else - SDL_Overlay *m_yuvsurf; -#endif // YUV overlay UINT32 *m_yuv_lookup; @@ -127,11 +111,7 @@ struct sdl_scale_mode int is_yuv; /* Yuv mode? */ int mult_w; /* Width multiplier */ int mult_h; /* Height multiplier */ -#if (!SDLMAME_SDL2) - int m_extra_flags; /* Texture/surface flags */ -#else const char *sdl_scale_mode_hint; /* what to use as a hint ? */ -#endif int pixel_format; /* Pixel/Overlay format */ void (*yuv_blit)(const UINT16 *bitmap, UINT8 *ptr, const int pitch, const UINT32 *lookup, const int width, const int height); }; @@ -160,20 +140,6 @@ static void yuv_RGB_to_YUY2X2(const UINT16 *bitmap, UINT8 *ptr, const int pitch, // Static declarations -#if (!SDLMAME_SDL2) -static int shown_video_info = 0; - -static const sdl_scale_mode scale_modes[] = -{ - { "none", 0, 0, 1, 1, osd_renderer::FLAG_NEEDS_DOUBLEBUF, 0, 0 }, - { "async", 0, 0, 1, 1, osd_renderer::FLAG_NEEDS_DOUBLEBUF | osd_renderer::FLAG_NEEDS_ASYNCBLIT, 0, 0 }, - { "yv12", 1, 1, 1, 1, 0, SDL_YV12_OVERLAY, yuv_RGB_to_YV12 }, - { "yv12x2", 1, 1, 2, 2, 0, SDL_YV12_OVERLAY, yuv_RGB_to_YV12X2 }, - { "yuy2", 1, 1, 1, 1, 0, SDL_YUY2_OVERLAY, yuv_RGB_to_YUY2 }, - { "yuy2x2", 1, 1, 2, 1, 0, SDL_YUY2_OVERLAY, yuv_RGB_to_YUY2X2 }, - { NULL } -}; -#else static const sdl_scale_mode scale_modes[] = { { "none", 0, 0, 1, 1, DRAW2_SCALEMODE_NEAREST, 0, 0 }, @@ -186,7 +152,6 @@ static const sdl_scale_mode scale_modes[] = { "yuy2x2", 1, 1, 2, 1, DRAW2_SCALEMODE_BEST, SDL_PIXELFORMAT_YUY2, yuv_RGB_to_YUY2X2 }, { NULL } }; -#endif //============================================================ // drawsdl_scale_mode @@ -226,12 +191,7 @@ int drawsdl_scale_mode(const char *s) static osd_renderer *drawsdl_create(osd_window *window) { // FIXME: QUALITY HINTS -#if (SDLMAME_SDL2) return global_alloc(sdl_info(window, osd_renderer::FLAG_NONE)); -#else - const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode]; - return global_alloc(sdl_info(window, sm->m_extra_flags)); -#endif } //============================================================ @@ -244,11 +204,7 @@ int drawsdl_init(osd_draw_callbacks *callbacks) callbacks->create = drawsdl_create; callbacks->exit = drawsdl_exit; - if (SDLMAME_SDL2) - osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n"); - else - osd_printf_verbose("Using SDL single-window soft driver (SDL 1.2)\n"); - + osd_printf_verbose("Using SDL multi-window soft driver (SDL 2.0+)\n"); return 0; } @@ -264,7 +220,6 @@ static void drawsdl_exit(void) // setup_texture for window //============================================================ -#if (SDLMAME_SDL2) void sdl_info::setup_texture(const osd_dim &size) { const sdl_scale_mode *sdl_sm = &scale_modes[video_config.scale_mode]; @@ -311,64 +266,11 @@ void sdl_info::setup_texture(const osd_dim &size) size.width(), size.height()); } } -#endif - -//============================================================ -// yuv_overlay_init -//============================================================ - -#if (!SDLMAME_SDL2) -void sdl_info::yuv_overlay_init() -{ - const sdl_scale_mode *sdl_sm = &scale_modes[video_config.scale_mode]; - int minimum_width, minimum_height; - - window().target()->compute_minimum_size(minimum_width, minimum_height); - - if (window().prescale()) - { - minimum_width *= window().prescale(); - minimum_height *= window().prescale(); - } - - if (m_yuvsurf != NULL) - { - SDL_FreeYUVOverlay(m_yuvsurf); - m_yuvsurf = NULL; - } - - if (m_yuv_bitmap != NULL) - { - global_free_array(m_yuv_bitmap); - } - - osd_printf_verbose("SDL: Creating %d x %d YUV-Overlay ...\n", minimum_width, minimum_height); - - m_yuv_bitmap = global_alloc_array(UINT16, minimum_width*minimum_height); - - m_yuvsurf = SDL_CreateYUVOverlay(minimum_width * sdl_sm->mult_w, minimum_height * sdl_sm->mult_h, - sdl_sm->pixel_format, window().sdl_surface()); - - if ( m_yuvsurf == NULL ) { - osd_printf_error("SDL: Couldn't create SDL_yuv_overlay: %s\n", SDL_GetError()); - //return 1; - } - - if (!shown_video_info) - { - osd_printf_verbose("YUV Mode : %s\n", sdl_sm->name); - osd_printf_verbose("YUV Overlay Size : %d x %d\n", minimum_width, minimum_height); - osd_printf_verbose("YUV Acceleration : %s\n", m_yuvsurf->hw_overlay ? "Hardware" : "Software"); - shown_video_info = 1; - } -} -#endif //============================================================ // drawsdl_show_info //============================================================ -#if (SDLMAME_SDL2) static void drawsdl_show_info(struct SDL_RendererInfo *render_info) { #define RF_ENTRY(x) {x, #x } @@ -395,42 +297,14 @@ static void drawsdl_show_info(struct SDL_RendererInfo *render_info) if (render_info->flags & rflist[i].flag) osd_printf_verbose("renderer: flag %s\n", rflist[i].name); } -#endif //============================================================ // sdl_info::create -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a -// a //============================================================ int sdl_info::create() { -#if (SDLMAME_SDL2) const sdl_scale_mode *sm = &scale_modes[video_config.scale_mode]; // create renderer @@ -486,8 +360,6 @@ int sdl_info::create() window().get_size(w, h); setup_texture(w, h); #endif -#else -#endif m_yuv_lookup = NULL; m_blittimer = 0; @@ -517,9 +389,7 @@ void sdl_info::destroy() global_free_array(m_yuv_bitmap); m_yuv_bitmap = NULL; } -#if (SDLMAME_SDL2) SDL_DestroyRenderer(m_sdl_renderer); -#endif } //============================================================ @@ -543,16 +413,8 @@ int sdl_info::xy_to_render_target(int x, int y, int *xt, int *yt) void sdl_info::destroy_all_textures() { -#if (SDLMAME_SDL2) SDL_DestroyTexture(m_texture_id); m_texture_id = NULL; -#else - if (m_yuvsurf != NULL) - { - SDL_FreeYUVOverlay(m_yuvsurf); - m_yuvsurf = NULL; - } -#endif } @@ -566,9 +428,7 @@ int sdl_info::draw(int update) UINT8 *surfptr; INT32 pitch; Uint32 rmask, gmask, bmask; -#if (SDLMAME_SDL2) Uint32 amask; -#endif INT32 vofs, hofs, blitwidth, blitheight, ch, cw; int bpp; @@ -584,68 +444,14 @@ int sdl_info::draw(int update) clear_flags(FI_CHANGED); m_blittimer = 3; m_last_dim = wdim; -#if (SDLMAME_SDL2) SDL_RenderSetViewport(m_sdl_renderer, NULL); if (m_texture_id != NULL) SDL_DestroyTexture(m_texture_id); setup_texture(m_blit_dim); m_blittimer = 3; -#else - const sdl_scale_mode *sdl_sm = &scale_modes[video_config.scale_mode]; - if (sdl_sm->is_yuv) - { - yuv_overlay_init(); - } -#endif } // lock it if we need it -#if (!SDLMAME_SDL2) - - pitch = window().sdl_surface()->pitch; - bpp = window().sdl_surface()->format->BytesPerPixel; - rmask = window().sdl_surface()->format->Rmask; - gmask = window().sdl_surface()->format->Gmask; - bmask = window().sdl_surface()->format->Bmask; -// amask = sdlsurf->format->Amask; -#if 0 - if (window().blitwidth() != m_old_blitwidth || window().blitheight() != m_old_blitheight) - { - if (sm->is_yuv) - yuv_overlay_init(); - m_old_blitwidth = window().blitwidth(); - m_old_blitheight = window().blitheight(); - m_blittimer = 3; - } -#endif - if (SDL_MUSTLOCK(window().sdl_surface())) - SDL_LockSurface(window().sdl_surface()); - - // Clear if necessary - if (m_blittimer > 0) - { - memset(window().sdl_surface()->pixels, 0, wdim.height() * window().sdl_surface()->pitch); - m_blittimer--; - } - - - if (sm->is_yuv) - { - SDL_LockYUVOverlay(m_yuvsurf); - surfptr = m_yuvsurf->pixels[0]; // (UINT8 *) m_yuv_bitmap; - pitch = m_yuvsurf->pitches[0]; // (UINT8 *) m_yuv_bitmap; -#if 0 - printf("abcd %d\n", m_yuvsurf->h); - printf("abcd %d %d %d\n", m_yuvsurf->pitches[0], m_yuvsurf->pitches[1], m_yuvsurf->pitches[2]); - printf("abcd %p %p %p\n", m_yuvsurf->pixels[0], m_yuvsurf->pixels[1], m_yuvsurf->pixels[2]); - printf("abcd %ld %ld\n", m_yuvsurf->pixels[1] - m_yuvsurf->pixels[0], m_yuvsurf->pixels[2] - m_yuvsurf->pixels[1]); -#endif - } - else - surfptr = (UINT8 *)window().sdl_surface()->pixels; -#else - //SDL_SelectRenderer(window().sdl_window); - { Uint32 format; @@ -668,7 +474,6 @@ int sdl_info::draw(int update) SDL_LockTexture(m_texture_id, NULL, (void **) &surfptr, &pitch); -#endif // get ready to center the image vofs = hofs = 0; blitwidth = m_blit_dim.width(); @@ -703,25 +508,11 @@ int sdl_info::draw(int update) int mamewidth, mameheight; -#if !SDLMAME_SDL2 - if (!sm->is_yuv) - { - surfptr += ((vofs * pitch) + (hofs * bpp)); - mamewidth = blitwidth; //sdl_surface()->w; - mameheight = blitheight; //sdl_surface()->h; - } - else - { - mamewidth = m_yuvsurf->w / sm->mult_w; - mameheight = m_yuvsurf->h / sm->mult_h; - } -#else Uint32 fmt = 0; int access = 0; SDL_QueryTexture(m_texture_id, &fmt, &access, &mamewidth, &mameheight); mamewidth /= sm->mult_w; mameheight /= sm->mult_h; -#endif //printf("w h %d %d %d %d\n", mamewidth, mameheight, blitwidth, blitheight); // rescale bounds @@ -780,24 +571,6 @@ int sdl_info::draw(int update) window().m_primlist->release_lock(); // unlock and flip -#if (!SDLMAME_SDL2) - if (SDL_MUSTLOCK(window().sdl_surface())) SDL_UnlockSurface(window().sdl_surface()); - if (!sm->is_yuv) - { - SDL_Flip(window().sdl_surface()); - } - else - { - SDL_Rect r; - - SDL_UnlockYUVOverlay(m_yuvsurf); - r.x = hofs; - r.y = vofs; - r.w = blitwidth; - r.h = blitheight; - SDL_DisplayYUVOverlay(m_yuvsurf, &r); - } -#else SDL_UnlockTexture(m_texture_id); { SDL_Rect r; @@ -811,7 +584,6 @@ int sdl_info::draw(int update) SDL_RenderCopy(m_sdl_renderer,m_texture_id, NULL, &r); SDL_RenderPresent(m_sdl_renderer); } -#endif return 0; } //============================================================ @@ -950,12 +722,7 @@ static void yuv_RGB_to_YV12X2(const UINT16 *bitmap, UINT8 *ptr, const int pitch, pixels[0] = ptr; pixels[1] = ptr + pitch * height * 2; -#if (SDLMAME_SDL2) int p2 = (pitch >> 1); -#else - int p2 = (pitch + 7) & ~ 7;; - p2 = (p2 >> 1); -#endif pixels[2] = pixels[1] + p2 * height; for(y=0;y<height;y++) |