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.cpp217
1 files changed, 128 insertions, 89 deletions
diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp
index 00a1a6435e7..2ec5b660876 100644
--- a/src/emu/screen.cpp
+++ b/src/emu/screen.cpp
@@ -546,43 +546,45 @@ void screen_device::svg_renderer::rebuild_cache()
//-------------------------------------------------
screen_device::screen_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, SCREEN, tag, owner, clock),
- m_type(SCREEN_TYPE_RASTER),
- m_oldstyle_vblank_supplied(false),
- m_refresh(0),
- m_vblank(0),
- m_xoffset(0.0f),
- m_yoffset(0.0f),
- m_xscale(1.0f),
- m_yscale(1.0f),
- m_screen_vblank(*this),
- m_palette(*this, finder_base::DUMMY_TAG),
- m_video_attributes(0),
- m_svg_region(nullptr),
- m_container(nullptr),
- m_width(100),
- m_height(100),
- m_visarea(0, 99, 0, 99),
- m_texformat(),
- m_curbitmap(0),
- m_curtexture(0),
- m_changed(true),
- m_last_partial_scan(0),
- m_partial_scan_hpos(0),
- m_color(rgb_t(0xff, 0xff, 0xff, 0xff)),
- m_brightness(0xff),
- m_frame_period(DEFAULT_FRAME_PERIOD.as_attoseconds()),
- m_scantime(1),
- m_pixeltime(1),
- m_vblank_period(0),
- m_vblank_start_time(attotime::zero),
- m_vblank_end_time(attotime::zero),
- m_vblank_begin_timer(nullptr),
- m_vblank_end_timer(nullptr),
- m_scanline0_timer(nullptr),
- m_scanline_timer(nullptr),
- m_frame_number(0),
- m_partial_updates_this_frame(0)
+ : device_t(mconfig, SCREEN, tag, owner, clock)
+ , m_type(SCREEN_TYPE_RASTER)
+ , m_orientation(ROT0)
+ , m_phys_aspect(0U, 0U)
+ , m_oldstyle_vblank_supplied(false)
+ , m_refresh(0)
+ , m_vblank(0)
+ , m_xoffset(0.0f)
+ , m_yoffset(0.0f)
+ , m_xscale(1.0f)
+ , m_yscale(1.0f)
+ , m_screen_vblank(*this)
+ , m_palette(*this, finder_base::DUMMY_TAG)
+ , m_video_attributes(0)
+ , m_svg_region(nullptr)
+ , m_container(nullptr)
+ , m_width(100)
+ , m_height(100)
+ , m_visarea(0, 99, 0, 99)
+ , m_texformat()
+ , m_curbitmap(0)
+ , m_curtexture(0)
+ , m_changed(true)
+ , m_last_partial_scan(0)
+ , m_partial_scan_hpos(0)
+ , m_color(rgb_t(0xff, 0xff, 0xff, 0xff))
+ , m_brightness(0xff)
+ , m_frame_period(DEFAULT_FRAME_PERIOD.as_attoseconds())
+ , m_scantime(1)
+ , m_pixeltime(1)
+ , m_vblank_period(0)
+ , m_vblank_start_time(attotime::zero)
+ , m_vblank_end_time(attotime::zero)
+ , m_vblank_begin_timer(nullptr)
+ , m_vblank_end_timer(nullptr)
+ , m_scanline0_timer(nullptr)
+ , m_scanline_timer(nullptr)
+ , m_frame_number(0)
+ , m_partial_updates_this_frame(0)
{
m_unique_id = m_id_counter;
m_id_counter++;
@@ -613,7 +615,7 @@ void screen_device::device_validity_check(validity_checker &valid) const
// sanity check display area
if (m_type != SCREEN_TYPE_VECTOR && m_type != SCREEN_TYPE_SVG)
{
- if (m_visarea.empty() || m_visarea.max_x >= m_width || m_visarea.max_y >= m_height)
+ if (m_visarea.empty() || m_visarea.right() >= m_width || m_visarea.bottom() >= m_height)
osd_printf_error("Invalid display area\n");
// sanity check screen formats
@@ -646,6 +648,48 @@ void screen_device::device_validity_check(validity_checker &valid) const
//-------------------------------------------------
+// device_config_complete - finalise static
+// configuration
+//-------------------------------------------------
+
+void screen_device::device_config_complete()
+{
+ // combine orientation with machine orientation
+ m_orientation = orientation_add(m_orientation, mconfig().gamedrv().flags & machine_flags::MASK_ORIENTATION);
+
+ // physical aspect ratio unconfigured
+ if (!m_phys_aspect.first || !m_phys_aspect.second)
+ {
+ switch (m_type)
+ {
+ case SCREEN_TYPE_RASTER:
+ case SCREEN_TYPE_VECTOR:
+ m_phys_aspect = std::make_pair(4, 3); // assume standard CRT
+ break;
+ case SCREEN_TYPE_LCD:
+ case SCREEN_TYPE_SVG:
+ m_phys_aspect = std::make_pair(~0U, ~0U); // assume square pixels
+ break;
+ case SCREEN_TYPE_INVALID:
+ default:
+ throw emu_fatalerror("%s: invalid screen type configured\n", tag());
+ }
+ }
+
+ // square pixels?
+ if ((~0U == m_phys_aspect.first) && (~0U == m_phys_aspect.second))
+ {
+ m_phys_aspect.first = visible_area().width();
+ m_phys_aspect.second = visible_area().height();
+ }
+
+ // always keep this in reduced form
+ util::reduce_fraction(m_phys_aspect.first, m_phys_aspect.second);
+}
+
+
+
+//-------------------------------------------------
// device_resolve_objects - resolve objects that
// may be needed for other devices to set
// initial conditions at start time
@@ -674,16 +718,18 @@ void screen_device::device_start()
{
memory_region *reg = owner()->memregion(m_svg_region);
if (!reg)
- fatalerror("SVG region \"%s\" does not exist\n", m_svg_region);
+ fatalerror("%s: SVG region \"%s\" does not exist\n", tag(), m_svg_region);
m_svg = std::make_unique<svg_renderer>(reg);
machine().output().set_notifier(nullptr, svg_renderer::output_notifier, m_svg.get());
- if (0)
+ // 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
+ if (false)
{
- // The osd picks up the size before start is called, so that's useless
+ // The OSD picks up the size before start is called, so this only affect the info display if it's called up in-game
m_width = m_svg->width();
m_height = m_svg->height();
- m_visarea.set(0, m_width-1, 0, m_height-1);
+ m_visarea.set(0, m_width - 1, 0, m_height - 1);
}
}
@@ -845,8 +891,8 @@ void screen_device::device_timer(emu_timer &timer, device_timer_id id, int param
// compute the next visible scanline
param++;
- if (param > m_visarea.max_y)
- param = m_visarea.min_y;
+ if (param > m_visarea.bottom())
+ param = m_visarea.top();
m_scanline_timer->adjust(time_until_pos(param), param);
break;
}
@@ -862,12 +908,12 @@ void screen_device::configure(int width, int height, const rectangle &visarea, a
// validate arguments
assert(width > 0);
assert(height > 0);
- assert(visarea.min_x >= 0);
- assert(visarea.min_y >= 0);
-// assert(visarea.max_x < width);
-// assert(visarea.max_y < height);
- assert(m_type == SCREEN_TYPE_VECTOR || m_type == SCREEN_TYPE_SVG || visarea.min_x < width);
- assert(m_type == SCREEN_TYPE_VECTOR || m_type == SCREEN_TYPE_SVG || visarea.min_y < height);
+ assert(visarea.left() >= 0);
+ assert(visarea.top() >= 0);
+// assert(visarea.right() < width);
+// assert(visarea.bottom() < height);
+ assert(m_type == SCREEN_TYPE_VECTOR || m_type == SCREEN_TYPE_SVG || visarea.left() < width);
+ assert(m_type == SCREEN_TYPE_VECTOR || m_type == SCREEN_TYPE_SVG || visarea.top() < height);
assert(frame_period > 0);
// fill in the new parameters
@@ -932,9 +978,9 @@ void screen_device::reset_origin(int beamy, int beamx)
else
m_scanline0_timer->adjust(time_until_pos(0));
- // if we are resetting relative to (visarea.max_y + 1, 0) == VBLANK start,
+ // 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.max_y + 1) % m_height) && beamx == 0)
+ if (beamy == ((m_visarea.bottom() + 1) % m_height) && beamx == 0)
vblank_begin();
else
m_vblank_begin_timer->adjust(time_until_vblank_start());
@@ -953,8 +999,8 @@ void screen_device::realloc_screen_bitmaps()
return;
// determine effective size to allocate
- s32 effwidth = std::max(m_width, m_visarea.max_x + 1);
- s32 effheight = std::max(m_height, m_visarea.max_y + 1);
+ s32 effwidth = std::max(m_width, m_visarea.right() + 1);
+ s32 effheight = std::max(m_height, m_visarea.bottom() + 1);
// reize all registered screen bitmaps
for (auto &item : m_auto_bitmap_list)
@@ -1022,21 +1068,20 @@ bool screen_device::update_partial(int scanline)
}
// set the range of scanlines to render
- rectangle clip = m_visarea;
- if (m_last_partial_scan > clip.min_y)
- clip.min_y = m_last_partial_scan;
- if (scanline < clip.max_y)
- clip.max_y = scanline;
+ rectangle clip(m_visarea);
+ clip.sety(
+ (std::max)(clip.top(), m_last_partial_scan),
+ (std::min)(clip.bottom(), scanline));
// skip if entirely outside of visible area
- if (clip.min_y > clip.max_y)
+ if (clip.top() > clip.bottom())
{
LOG_PARTIAL_UPDATES(("skipped because outside of visible area\n"));
return false;
}
// otherwise, render
- LOG_PARTIAL_UPDATES(("updating %d-%d\n", clip.min_y, clip.max_y));
+ LOG_PARTIAL_UPDATES(("updating %d-%d\n", clip.top(), clip.bottom()));
g_profiler.start(PROFILER_VIDEO);
u32 flags;
@@ -1096,7 +1141,7 @@ void screen_device::update_now()
int current_hpos = hpos();
rectangle clip = m_visarea;
- LOG_PARTIAL_UPDATES(("update_now(): Y=%d, X=%d, last partial %d, partial hpos %d (vis %d %d)\n", current_vpos, current_hpos, m_last_partial_scan, m_partial_scan_hpos, m_visarea.max_x, m_visarea.max_y));
+ LOG_PARTIAL_UPDATES(("update_now(): Y=%d, X=%d, last partial %d, partial hpos %d (vis %d %d)\n", current_vpos, current_hpos, m_last_partial_scan, m_partial_scan_hpos, m_visarea.right(), m_visarea.bottom()));
// start off by doing a partial update up to the line before us, in case that was necessary
if (current_vpos > m_last_partial_scan)
@@ -1113,17 +1158,14 @@ void screen_device::update_now()
// now finish the previous partial scanline
int scanline = current_vpos - 1;
- if (m_partial_scan_hpos > clip.min_x)
- clip.min_x = m_partial_scan_hpos;
- if (current_hpos < clip.max_x)
- clip.max_x = current_hpos;
- if (m_last_partial_scan > clip.min_y)
- clip.min_y = m_last_partial_scan;
- if (scanline < clip.max_y)
- clip.max_y = scanline;
+ clip.set(
+ (std::max)(clip.left(), m_partial_scan_hpos),
+ (std::min)(clip.right(), current_hpos),
+ (std::max)(clip.top(), m_last_partial_scan),
+ (std::min)(clip.bottom(), scanline));
// if there's something to draw, do it
- if ((clip.min_x <= clip.max_x) && (clip.min_y <= clip.max_y))
+ if (!clip.empty())
{
g_profiler.start(PROFILER_VIDEO);
@@ -1150,21 +1192,18 @@ void screen_device::update_now()
// now draw this partial scanline
clip = m_visarea;
- if (m_partial_scan_hpos > clip.min_x)
- clip.min_x = m_partial_scan_hpos;
- if (current_hpos < clip.max_x)
- clip.max_x = current_hpos;
- if (current_vpos > clip.min_y)
- clip.min_y = current_vpos;
- if (current_vpos < clip.max_y)
- clip.max_y = current_vpos;
+ clip.set(
+ (std::max)(clip.left(), m_partial_scan_hpos),
+ (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.min_x <= clip.max_x) && (clip.min_y <= clip.max_y))
+ if (!clip.empty())
{
g_profiler.start(PROFILER_VIDEO);
- LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.max_y, clip.min_x, clip.max_x));
+ LOG_PARTIAL_UPDATES(("doing scanline partial draw: Y %d X %d-%d\n", clip.bottom(), clip.left(), clip.right()));
u32 flags;
screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
@@ -1186,7 +1225,7 @@ void screen_device::update_now()
m_last_partial_scan = current_vpos;
// if we completed the line, mark it so
- if (current_hpos >= m_visarea.max_x)
+ if (current_hpos >= m_visarea.right())
{
m_partial_scan_hpos = 0;
m_last_partial_scan = current_vpos + 1;
@@ -1226,7 +1265,7 @@ int screen_device::vpos() const
vpos = delta / m_scantime;
// adjust for the fact that VBLANK starts at the bottom of the visible area
- return (m_visarea.max_y + 1 + vpos) % m_height;
+ return (m_visarea.bottom() + 1 + vpos) % m_height;
}
@@ -1266,7 +1305,7 @@ attotime screen_device::time_until_pos(int vpos, int hpos) const
assert(hpos >= 0);
// since we measure time relative to VBLANK, compute the scanline offset from VBLANK
- vpos += m_height - (m_visarea.max_y + 1);
+ vpos += m_height - (m_visarea.bottom() + 1);
vpos %= m_height;
// compute the delta for the given X,Y position
@@ -1504,11 +1543,11 @@ void screen_device::finalize_burnin()
return;
// compute the scaled visible region
- rectangle scaledvis;
- scaledvis.min_x = m_visarea.min_x * m_burnin.width() / m_width;
- scaledvis.max_x = m_visarea.max_x * m_burnin.width() / m_width;
- scaledvis.min_y = m_visarea.min_y * m_burnin.height() / m_height;
- scaledvis.max_y = m_visarea.max_y * m_burnin.height() / m_height;
+ rectangle scaledvis(
+ m_visarea.left() * m_burnin.width() / m_width,
+ m_visarea.right() * m_burnin.width() / m_width,
+ 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
bitmap_argb32 finalmap(scaledvis.width(), scaledvis.height());