From 6b004964ef5f67a0416f6036d34c4f9a57059793 Mon Sep 17 00:00:00 2001 From: couriersud Date: Sun, 17 Nov 2019 03:07:04 +0100 Subject: netlist video: Add VECTOR support. [Couriersud] Fixfreq now supports VECTOR screens automatically. For now the default remains to be RASTER since bgfx does not support VECTOR screens. Nevertheless please expect changes in the video output. Video output is now collected timing-exact, i.e. with subpixel accuracy. Only during screen_update this is converted and scaled to the bitmap. There may be changes due to rounding in comparison to current rendering. Also added a link to a video showing a breakout cocktail table. --- src/devices/video/fixfreq.cpp | 55 ++++++++++++++++++++++++++++--------------- src/devices/video/fixfreq.h | 20 +++++++++++----- src/mame/drivers/pong.cpp | 10 +++++++- 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/devices/video/fixfreq.cpp b/src/devices/video/fixfreq.cpp index c5dc2e5ffcb..4957a0343fa 100644 --- a/src/devices/video/fixfreq.cpp +++ b/src/devices/video/fixfreq.cpp @@ -14,6 +14,7 @@ ***************************************************************************/ #include "emu.h" +#include "rendutil.h" #include "fixfreq.h" //#define VERBOSE 1 @@ -83,7 +84,7 @@ void fixedfreq_monitor_state::update_sync_channel(const time_type &time, const d void fixedfreq_monitor_state::update_bm(const time_type &time) { - const int pixels = round((time - m_line_time) * m_desc.m_hscale / m_clock_period); + const float pixels = (time - m_line_time) * static_cast(m_desc.m_hscale) / m_clock_period; const int has_fields = (m_desc.m_fieldcount > 1) ? 1: 0; uint32_t col(0xffff0000); // Mark sync areas @@ -91,7 +92,8 @@ void fixedfreq_monitor_state::update_bm(const time_type &time) if (m_sync_signal >= m_desc.m_sync_threshold) col = m_col; - m_intf.plot_hline(m_last_x, m_last_y + m_sig_field * has_fields, pixels - m_last_x, col); + m_fragments.push_back({static_cast(m_last_y + m_sig_field * has_fields), m_last_x, pixels, col}); + //m_intf.plot_hline(m_last_x, m_last_y + m_sig_field * has_fields, pixels, col); m_last_x = pixels; } @@ -157,7 +159,6 @@ void fixedfreq_monitor_state::update_sync(const time_type &time, const double da fixedfreq_device::fixedfreq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock), device_video_interface(mconfig, *this, false), - m_cur_bm(0), m_htotal(0), m_vtotal(0), m_refresh_period(time_type(0)), @@ -190,12 +191,8 @@ void fixedfreq_device::device_start() m_refresh_period = time_type(0); - m_cur_bm = 0; - m_htotal = m_monitor.m_hbackporch; m_vtotal = m_monitor.m_vbackporch; - m_bitmap[0] = std::make_unique(m_htotal * m_monitor.m_hscale, m_vtotal); - m_bitmap[1] = std::make_unique(m_htotal * m_monitor.m_hscale, m_vtotal); m_state.start(); @@ -209,9 +206,6 @@ void fixedfreq_device::device_start() save_item(NAME(m_state.m_last_vsync_time)); save_item(NAME(m_refresh_period)); save_item(NAME(m_state.m_clock_period)); - //save_item(NAME(m_bitmap[0])); - //save_item(NAME(m_bitmap[1])); - save_item(NAME(m_cur_bm)); /* sync separator */ save_item(NAME(m_state.m_vsync_filter)); @@ -235,15 +229,45 @@ void fixedfreq_device::device_post_load() uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - copybitmap(bitmap, *m_bitmap[!m_cur_bm], 0, 0, 0, 0, cliprect); + if (screen.screen_type() == SCREEN_TYPE_RASTER) + { + for (auto &f : m_state.m_fragments) + if (f.y < bitmap.height()) + bitmap.plot_box(f.x, f.y, f.xr - f.x, 1, f.col); + } + else if (screen.screen_type() == SCREEN_TYPE_VECTOR) + { + constexpr const uint32_t flags(PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_VECTOR(1)); + const rectangle &visarea = screen.visible_area(); + float xscale = 1.0f / visarea.width(); + float yscale = 1.0f / visarea.height(); + float xoffs = (float)visarea.min_x; + float yoffs = (float)visarea.min_y; + screen.container().empty(); + screen.container().add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(0xff,0x00,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_VECTORBUF(1)); + + for (auto &f : m_state.m_fragments) + { + const float x0((f.x - xoffs) * xscale); + const float y0((f.y - yoffs) * yscale); + const float x1((f.xr - xoffs) * xscale); + const float y1((f.y + 1.0f - yoffs) * yscale); + + screen.container().add_rect( + x0, y0, x1, y1, + (0xff << 24) | (f.col & 0xffffff), + flags); + } + } + m_state.m_fragments.clear(); return 0; } void fixedfreq_device::vsync_start_cb(double refresh_time) { // toggle bitmap - m_cur_bm ^= 1; + //m_cur_bm ^= 1; rectangle visarea(m_monitor.minh(), m_monitor.maxh(), m_monitor.minv(), m_monitor.maxv()); @@ -251,13 +275,6 @@ void fixedfreq_device::vsync_start_cb(double refresh_time) screen().configure(m_htotal * m_monitor.m_hscale, m_vtotal, visarea, DOUBLE_TO_ATTOSECONDS(m_refresh_period)); } -void fixedfreq_device::plot_hline(int x, int y, int w, uint32_t col) -{ - bitmap_rgb32 *bm = m_bitmap[m_cur_bm].get(); - if (y < bm->height()) - bm->plot_box(x, y, w, 1, col); -} - NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_composite_monochrome) { // double is good enough for this exercise; diff --git a/src/devices/video/fixfreq.h b/src/devices/video/fixfreq.h index 6e758ec4ffa..fdbf728f04a 100644 --- a/src/devices/video/fixfreq.h +++ b/src/devices/video/fixfreq.h @@ -60,7 +60,14 @@ struct fixedfreq_monitor_intf { virtual ~fixedfreq_monitor_intf() = default; virtual void vsync_start_cb(double refresh_time) = 0; - virtual void plot_hline(int x, int y, int w, uint32_t col) = 0; +}; + +struct fixedfreq_monitor_line +{ + float y; + float x; + float xr; + uint32_t col; }; struct fixedfreq_monitor_state @@ -127,8 +134,10 @@ struct fixedfreq_monitor_state m_clock_period = 1.0 / m_desc.m_monitor_clock; // Minimum frame period to be passed to video system ? m_min_frame_period = 0.25 * m_clock_period * m_desc.m_vbackporch * m_desc.m_hbackporch; - m_intf.vsync_start_cb(m_min_frame_period); + m_fragments.clear(); + + m_intf.vsync_start_cb(m_min_frame_period); } void reset() @@ -148,6 +157,7 @@ struct fixedfreq_monitor_state m_sig_vsync = 0; m_sig_composite = 0; m_sig_field = 0; + m_fragments.clear(); } void update_sync_channel(const time_type &time, const double newval); @@ -163,7 +173,7 @@ struct fixedfreq_monitor_state double m_sync_signal; uint32_t m_col; - int m_last_x; + float m_last_x; int m_last_y; time_type m_last_sync_time; time_type m_line_time; @@ -180,6 +190,7 @@ struct fixedfreq_monitor_state int m_sig_composite; int m_sig_field; time_type m_min_frame_period; + std::vector m_fragments; }; // ======================> fixedfreq_device @@ -254,12 +265,9 @@ protected: //virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); void vsync_start_cb(double refresh_time) override; - void plot_hline(int x, int y, int w, uint32_t col) override; private: - std::unique_ptr m_bitmap[2]; - int m_cur_bm; int m_htotal; int m_vtotal; diff --git a/src/mame/drivers/pong.cpp b/src/mame/drivers/pong.cpp index a140ea5ea8a..ea4ad14e7ab 100644 --- a/src/mame/drivers/pong.cpp +++ b/src/mame/drivers/pong.cpp @@ -97,6 +97,12 @@ TODO: Volleyball... * https://www.youtube.com/watch?v=pDrRnJOCKZc (no longer available) * * https://www.youtube.com/watch?v=fiShX2pTz9A + * https://www.youtube.com/watch?v=YmzH4E3x1_g + * + * Breakout videos: + * + * https://www.youtube.com/watch?v=NOGO49j5gCE + * */ static const int NS_PER_CLOCK_PONG = static_cast((double) NETLIST_INTERNAL_RES / (double) 7159000 + 0.5); @@ -483,6 +489,7 @@ void pong_state::pong(machine_config &config) /* video hardware */ SCREEN(config, "screen", SCREEN_TYPE_RASTER); + //SCREEN(config, "screen", SCREEN_TYPE_VECTOR); FIXFREQ(config, m_video).set_screen("screen"); m_video->set_monitor_clock(MASTER_CLOCK_PONG); m_video->set_horz_params(H_TOTAL_PONG-67,H_TOTAL_PONG-40,H_TOTAL_PONG-8,H_TOTAL_PONG); @@ -533,8 +540,9 @@ void breakout_state::breakout(machine_config &config) NETLIST_ANALOG_OUTPUT(config, "maincpu:coin_counter", 0).set_params("CON_T", FUNC(breakout_state::coin_counter_cb)); /* video hardware */ - SCREEN(config, "screen", SCREEN_TYPE_RASTER); FIXFREQ(config, m_video).set_screen("screen"); + SCREEN(config, "screen", SCREEN_TYPE_RASTER); + //SCREEN(config, "screen", SCREEN_TYPE_VECTOR); /* The Pixel width is a 2,1,2,1,2,1,1,1 repeating pattern * Thus we must use double resolution horizontally */ -- cgit v1.2.3