diff options
Diffstat (limited to 'src/emu/screen.cpp')
-rw-r--r-- | src/emu/screen.cpp | 268 |
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(); |