summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/screen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/screen.cpp')
-rw-r--r--src/emu/screen.cpp268
1 files changed, 127 insertions, 141 deletions
diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp
index c265b14e31b..cf311fb21eb 100644
--- a/src/emu/screen.cpp
+++ b/src/emu/screen.cpp
@@ -12,6 +12,8 @@
#include "screen.h"
#include "emuopts.h"
+#include "fileio.h"
+#include "main.h"
#include "render.h"
#include "rendutil.h"
@@ -554,7 +556,7 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev
, m_curtexture(0)
, m_changed(true)
, m_last_partial_scan(0)
- , m_partial_scan_hpos(-1)
+ , m_partial_scan_hpos(0)
, m_color(rgb_t(0xff, 0xff, 0xff, 0xff))
, m_brightness(0xff)
, m_frame_period(DEFAULT_FRAME_PERIOD.as_attoseconds())
@@ -635,12 +637,12 @@ void screen_device::allocate_scan_bitmaps()
else
m_scan_bitmaps[j].push_back(new bitmap_rgb32(effwidth, 1));
}
- m_scan_widths.push_back(m_width);
+ m_scan_widths.push_back(effwidth);
}
}
else
{
- for (int i = effheight; i < old_height; i++)
+ for (int i = old_height - 1; i >= effheight; i--)
{
for (int j = 0; j < 2; j++)
{
@@ -683,9 +685,9 @@ void screen_device::device_validity_check(validity_checker &valid) const
osd_printf_error("Non-raster display cannot have a variable width\n");
}
- // check for zero frame rate
- if (m_refresh == 0)
- osd_printf_error("Invalid (zero) refresh rate\n");
+ // check for invalid frame rate
+ if (m_refresh == 0 || m_refresh > ATTOSECONDS_PER_SECOND)
+ osd_printf_error("Invalid (under 1Hz) refresh rate\n");
texture_format texformat = !m_screen_update_ind16.isnull() ? TEXFORMAT_PALETTE16 : TEXFORMAT_RGB32;
if (m_palette.finder_tag() != finder_base::DUMMY_TAG)
@@ -770,8 +772,6 @@ void screen_device::device_resolve_objects()
// bind our handlers
m_screen_update_ind16.resolve();
m_screen_update_rgb32.resolve();
- m_screen_vblank.resolve_safe();
- m_scanline_cb.resolve();
// assign our format to the palette before it starts
if (m_palette)
@@ -794,7 +794,7 @@ void screen_device::device_start()
if (!m_svg_region)
fatalerror("%s: SVG region \"%s\" does not exist\n", tag(), m_svg_region.finder_tag());
m_svg = std::make_unique<svg_renderer>(m_svg_region);
- machine().output().set_notifier(nullptr, svg_renderer::output_notifier, m_svg.get());
+ machine().output().set_global_notifier(svg_renderer::output_notifier, m_svg.get());
// don't do this - SVG units are arbitrary and interpreting them as pixels causes bad things to happen
// just render at the size/aspect ratio supplied by the driver
@@ -826,8 +826,7 @@ void screen_device::device_start()
m_texture[1]->set_id((u64(m_unique_id) << 57) | 1);
// configure the default cliparea
- render_container::user_settings settings;
- m_container->get_user_settings(settings);
+ render_container::user_settings settings = m_container->get_user_settings();
settings.m_xoffset = m_xoffset;
settings.m_yoffset = m_yoffset;
settings.m_xscale = m_xscale;
@@ -835,15 +834,15 @@ void screen_device::device_start()
m_container->set_user_settings(settings);
// allocate the VBLANK timers
- m_vblank_begin_timer = timer_alloc(TID_VBLANK_START);
- m_vblank_end_timer = timer_alloc(TID_VBLANK_END);
+ m_vblank_begin_timer = timer_alloc(FUNC(screen_device::vblank_begin), this);
+ m_vblank_end_timer = timer_alloc(FUNC(screen_device::vblank_end), this);
// allocate a timer to reset partial updates
- m_scanline0_timer = timer_alloc(TID_SCANLINE0);
+ m_scanline0_timer = timer_alloc(FUNC(screen_device::first_scanline_tick), this);
// allocate a timer to generate per-scanline updates
- if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || m_scanline_cb)
- m_scanline_timer = timer_alloc(TID_SCANLINE);
+ if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || !m_scanline_cb.isunset())
+ m_scanline_timer = timer_alloc(FUNC(screen_device::scanline_tick), this);
// configure the screen with the default parameters
configure(m_width, m_height, m_visarea, m_refresh);
@@ -853,7 +852,7 @@ void screen_device::device_start()
m_vblank_end_time = attotime(0, m_vblank_period);
// start the timer to generate per-scanline updates
- if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || m_scanline_cb)
+ if ((m_video_attributes & VIDEO_UPDATE_SCANLINE) != 0 || !m_scanline_cb.isunset())
m_scanline_timer->adjust(time_until_pos(0));
// create burn-in bitmap
@@ -888,9 +887,9 @@ void screen_device::device_start()
save_item(NAME(m_vblank_end_time));
save_item(NAME(m_frame_number));
if (m_oldstyle_vblank_supplied)
- logerror("%s: Deprecated legacy Old Style screen configured (MCFG_SCREEN_VBLANK_TIME), please use MCFG_SCREEN_RAW_PARAMS instead.\n",this->tag());
+ logerror("%s: Deprecated legacy Old Style screen configured (set_vblank_time), please use set_raw instead.\n",this->tag());
- m_is_primary_screen = (this == screen_device_iterator(machine().root_device()).first());
+ m_is_primary_screen = (this == screen_device_enumerator(machine().root_device()).first());
}
@@ -931,54 +930,39 @@ void screen_device::device_post_load()
//-------------------------------------------------
-// device_timer - called whenever a device timer
-// fires
+// timer events
//-------------------------------------------------
-void screen_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(screen_device::first_scanline_tick)
{
- switch (id)
+ // first scanline
+ reset_partial_updates();
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- // signal VBLANK start
- case TID_VBLANK_START:
- vblank_begin();
- break;
-
- // signal VBLANK end
- case TID_VBLANK_END:
- vblank_end();
- break;
-
- // first scanline
- case TID_SCANLINE0:
- reset_partial_updates();
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
- {
- pre_update_scanline(0);
- }
- break;
+ pre_update_scanline(0);
+ }
+}
- // subsequent scanlines when scanline updates are enabled
- case TID_SCANLINE:
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
- {
- pre_update_scanline(param);
- }
- if (m_video_attributes & VIDEO_UPDATE_SCANLINE)
- {
- // force a partial update to the current scanline
- update_partial(param);
- }
- if (m_scanline_cb)
- m_scanline_cb(param);
-
- // compute the next visible scanline
- param++;
- if (param > m_visarea.bottom())
- param = m_visarea.top();
- m_scanline_timer->adjust(time_until_pos(param), param);
- break;
+TIMER_CALLBACK_MEMBER(screen_device::scanline_tick)
+{
+ // subsequent scanlines when scanline updates are enabled
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
+ {
+ pre_update_scanline(param);
+ }
+ if (m_video_attributes & VIDEO_UPDATE_SCANLINE)
+ {
+ // force a partial update to the current scanline
+ update_partial(param);
}
+ if (!m_scanline_cb.isunset())
+ m_scanline_cb(param);
+
+ // compute the next visible scanline
+ param++;
+ if (param > m_visarea.bottom())
+ param = m_visarea.top();
+ m_scanline_timer->adjust(time_until_pos(param), param);
}
@@ -1027,7 +1011,7 @@ void screen_device::configure(int width, int height, const rectangle &visarea, a
// call the VBLANK start timer now; otherwise, adjust it for the future
attoseconds_t delta = (machine().time() - m_vblank_start_time).as_attoseconds();
if (delta >= m_frame_period)
- vblank_begin();
+ vblank_begin(0);
else
m_vblank_begin_timer->adjust(time_until_vblank_start());
@@ -1065,7 +1049,7 @@ void screen_device::reset_origin(int beamy, int beamx)
// if we are resetting relative to (visarea.bottom() + 1, 0) == VBLANK start,
// call the VBLANK start timer now; otherwise, adjust it for the future
if (beamy == ((m_visarea.bottom() + 1) % m_height) && beamx == 0)
- vblank_begin();
+ vblank_begin(0);
else
m_vblank_begin_timer->adjust(time_until_vblank_start());
}
@@ -1109,7 +1093,7 @@ void screen_device::realloc_screen_bitmaps()
s32 effwidth = std::max(per_scanline ? m_max_width : m_width, m_visarea.right() + 1);
s32 effheight = std::max(m_height, m_visarea.bottom() + 1);
- // reize all registered screen bitmaps
+ // resize all registered screen bitmaps
for (auto &item : m_auto_bitmap_list)
item->m_bitmap.resize(effwidth, effheight);
@@ -1197,55 +1181,56 @@ bool screen_device::update_partial(int scanline)
// otherwise, render
LOG_PARTIAL_UPDATES(("updating %d-%d\n", clip.top(), clip.bottom()));
- g_profiler.start(PROFILER_VIDEO);
u32 flags = 0;
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- rectangle scan_clip(clip);
- for (int y = clip.top(); y <= clip.bottom(); y++)
+ auto profile = g_profiler.start(PROFILER_VIDEO);
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- scan_clip.sety(y, y);
- pre_update_scanline(y);
-
- screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
- switch (curbitmap.format())
+ rectangle scan_clip(clip);
+ for (int y = clip.top(); y <= clip.bottom(); y++)
{
- default:
- case BITMAP_FORMAT_IND16: flags |= m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
- case BITMAP_FORMAT_RGB32: flags |= m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
- }
+ scan_clip.sety(y, y);
+ pre_update_scanline(y);
- m_partial_updates_this_frame++;
- }
- }
- else
- {
- if (m_type != SCREEN_TYPE_SVG)
- {
- screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
- switch (curbitmap.format())
- {
- default:
- case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break;
- case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break;
+ screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
+ switch (curbitmap.format())
+ {
+ default:
+ case BITMAP_FORMAT_IND16: flags |= m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
+ case BITMAP_FORMAT_RGB32: flags |= m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][y], scan_clip); break;
+ }
+
+ m_partial_updates_this_frame++;
}
}
else
{
- flags = m_svg->render(*this, m_bitmap[m_curbitmap].as_rgb32(), clip);
+ if (m_type != SCREEN_TYPE_SVG)
+ {
+ screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
+ switch (curbitmap.format())
+ {
+ default:
+ case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break;
+ case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break;
+ }
+ }
+ else
+ {
+ flags = m_svg->render(*this, m_bitmap[m_curbitmap].as_rgb32(), clip);
+ }
+ m_partial_updates_this_frame++;
}
- m_partial_updates_this_frame++;
+ // stop profiling
}
- g_profiler.stop();
-
// if we modified the bitmap, we have to commit
m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
// remember where we left off
m_last_partial_scan = scanline + 1;
- m_partial_scan_hpos = -1;
+ m_partial_scan_hpos = 0;
return true;
}
@@ -1299,10 +1284,10 @@ void screen_device::update_now()
if (current_vpos > m_last_partial_scan)
{
// if the line before us was incomplete, we must do it in two pieces
- if (m_partial_scan_hpos >= 0)
+ if (m_partial_scan_hpos > 0)
{
// now finish the previous partial scanline
- clip.set((std::max)(clip.left(), m_partial_scan_hpos + 1),
+ clip.set((std::max)(clip.left(), m_partial_scan_hpos),
clip.right(),
(std::max)(clip.top(), m_last_partial_scan),
(std::min)(clip.bottom(), m_last_partial_scan));
@@ -1310,7 +1295,7 @@ void screen_device::update_now()
// if there's something to draw, do it
if (!clip.empty())
{
- g_profiler.start(PROFILER_VIDEO);
+ auto profile = g_profiler.start(PROFILER_VIDEO);
u32 flags = 0;
screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
@@ -1334,14 +1319,13 @@ void screen_device::update_now()
}
}
- g_profiler.stop();
m_partial_updates_this_frame++;
// if we modified the bitmap, we have to commit
m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
}
- m_partial_scan_hpos = -1;
+ m_partial_scan_hpos = 0;
m_last_partial_scan++;
}
if (current_vpos > m_last_partial_scan)
@@ -1351,47 +1335,49 @@ void screen_device::update_now()
}
// now draw this partial scanline
- clip = m_visarea;
-
- clip.set((std::max)(clip.left(), m_partial_scan_hpos + 1),
- (std::min)(clip.right(), current_hpos),
- (std::max)(clip.top(), current_vpos),
- (std::min)(clip.bottom(), current_vpos));
-
- // and if there's something to draw, do it
- if (!clip.empty())
+ if (current_hpos > 0)
{
- g_profiler.start(PROFILER_VIDEO);
+ clip = m_visarea;
- LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right()));
+ clip.set((std::max)(clip.left(), m_partial_scan_hpos),
+ (std::min)(clip.right(), current_hpos - 1),
+ (std::max)(clip.top(), current_vpos),
+ (std::min)(clip.bottom(), current_vpos));
- u32 flags = 0;
- screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
- if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
+ // and if there's something to draw, do it
+ if (!clip.empty())
{
- pre_update_scanline(current_vpos);
- switch (curbitmap.format())
+ auto profile = g_profiler.start(PROFILER_VIDEO);
+
+ LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right()));
+
+ u32 flags = 0;
+ screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
+ if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
{
- default:
- case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
- case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
+ pre_update_scanline(current_vpos);
+ switch (curbitmap.format())
+ {
+ default:
+ case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, *(bitmap_ind16 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
+ case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, *(bitmap_rgb32 *)m_scan_bitmaps[m_curbitmap][current_vpos], clip); break;
+ }
}
- }
- else
- {
- switch (curbitmap.format())
+ else
{
- default:
- case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break;
- case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break;
+ switch (curbitmap.format())
+ {
+ default:
+ case BITMAP_FORMAT_IND16: flags = m_screen_update_ind16(*this, curbitmap.as_ind16(), clip); break;
+ case BITMAP_FORMAT_RGB32: flags = m_screen_update_rgb32(*this, curbitmap.as_rgb32(), clip); break;
+ }
}
- }
- m_partial_updates_this_frame++;
- g_profiler.stop();
+ m_partial_updates_this_frame++;
- // if we modified the bitmap, we have to commit
- m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
+ // if we modified the bitmap, we have to commit
+ m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
+ }
}
// remember where we left off
@@ -1408,7 +1394,7 @@ void screen_device::update_now()
void screen_device::reset_partial_updates()
{
m_last_partial_scan = 0;
- m_partial_scan_hpos = -1;
+ m_partial_scan_hpos = 0;
m_partial_updates_this_frame = 0;
m_scanline0_timer->adjust(time_until_pos(0));
}
@@ -1647,7 +1633,7 @@ void screen_device::register_screen_bitmap(bitmap_t &bitmap)
// signal the VBLANK period has begun
//-------------------------------------------------
-void screen_device::vblank_begin()
+TIMER_CALLBACK_MEMBER(screen_device::vblank_begin)
{
// reset the starting VBLANK time
m_vblank_start_time = machine().time();
@@ -1667,7 +1653,7 @@ void screen_device::vblank_begin()
// if no VBLANK period, call the VBLANK end callback immediately, otherwise reset the timer
if (m_vblank_period == 0)
- vblank_end();
+ vblank_end(0);
else
m_vblank_end_timer->adjust(time_until_vblank_end());
}
@@ -1678,7 +1664,7 @@ void screen_device::vblank_begin()
// signal the VBLANK period has ended
//-------------------------------------------------
-void screen_device::vblank_end()
+TIMER_CALLBACK_MEMBER(screen_device::vblank_end)
{
// call the screen specific callbacks
for (auto &item : m_callback_list)
@@ -1871,7 +1857,7 @@ void screen_device::finalize_burnin()
m_visarea.top() * m_burnin.height() / m_height,
m_visarea.bottom() * m_burnin.height() / m_height);
- // wrap a bitmap around the memregion we care about
+ // wrap a bitmap around the subregion we care about
bitmap_argb32 finalmap(scaledvis.width(), scaledvis.height());
int srcwidth = m_burnin.width();
int srcheight = m_burnin.height();
@@ -1912,14 +1898,14 @@ void screen_device::finalize_burnin()
// compute the name and create the file
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- osd_file::error filerr = file.open(util::string_format("%s" PATH_SEPARATOR "burnin-%s.png", machine().basename(), tag() + 1));
- if (filerr == osd_file::error::NONE)
+ std::error_condition const filerr = file.open(util::string_format("%s" PATH_SEPARATOR "burnin-%s.png", machine().basename(), tag() + 1));
+ if (!filerr)
{
util::png_info pnginfo;
// add two text entries describing the image
- pnginfo.add_text("Software", util::string_format("%s %s", emulator_info::get_appname(), emulator_info::get_build_version()).c_str());
- pnginfo.add_text("System", util::string_format("%s %s", machine().system().manufacturer, machine().system().type.fullname()).c_str());
+ pnginfo.add_text("Software", util::string_format("%s %s", emulator_info::get_appname(), emulator_info::get_build_version()));
+ pnginfo.add_text("System", util::string_format("%s %s", machine().system().manufacturer, machine().system().type.fullname()));
// now do the actual work
util::png_write_bitmap(file, &pnginfo, finalmap, 0, nullptr);
@@ -1943,7 +1929,7 @@ void screen_device::load_effect_overlay(const char *filename)
// load the file
m_screen_overlay_bitmap.reset();
emu_file file(machine().options().art_path(), OPEN_FLAG_READ);
- if (file.open(fullname) == osd_file::error::NONE)
+ if (!file.open(fullname))
{
render_load_png(m_screen_overlay_bitmap, file);
file.close();