mirror of
https://github.com/libretro/same_cdi.git
synced 2026-11-07 12:37:58 -10:00
Update screen driver
This commit is contained in:
1 parent
bf2d3c85a9
commit
45d64b0804
2 files changed
+247
-164
No files matched your search
+222
-129
@@ -12,6 +12,8 @@
|
||||
#include "screen.h"
|
||||
|
||||
#include "emuopts.h"
|
||||
#include "fileio.h"
|
||||
#include "main.h"
|
||||
#include "render.h"
|
||||
#include "rendutil.h"
|
||||
|
||||
@@ -20,6 +22,19 @@
|
||||
|
||||
#include <set>
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
#include "libretro/osdretro.h"
|
||||
#endif
|
||||
|
||||
//**************************************************************************
|
||||
// DEBUGGING
|
||||
//**************************************************************************
|
||||
|
||||
#define VERBOSE (0)
|
||||
#define LOG_PARTIAL_UPDATES(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
@@ -543,8 +558,9 @@ screen_device::screen_device(const machine_config &mconfig, const char *tag, dev
|
||||
, m_curbitmap(0)
|
||||
, m_curtexture(0)
|
||||
, m_changed(true)
|
||||
, m_last_partial_reset(attotime::zero)
|
||||
, 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())
|
||||
@@ -760,8 +776,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)
|
||||
@@ -824,15 +838,19 @@ 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);
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
screen_configured = 0;
|
||||
#endif
|
||||
|
||||
// configure the screen with the default parameters
|
||||
configure(m_width, m_height, m_visarea, m_refresh);
|
||||
@@ -842,7 +860,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
|
||||
@@ -867,6 +885,7 @@ void screen_device::device_start()
|
||||
save_item(NAME(m_visarea.min_y));
|
||||
save_item(NAME(m_visarea.max_x));
|
||||
save_item(NAME(m_visarea.max_y));
|
||||
save_item(NAME(m_last_partial_reset));
|
||||
save_item(NAME(m_last_partial_scan));
|
||||
save_item(NAME(m_frame_period));
|
||||
save_item(NAME(m_brightness));
|
||||
@@ -876,6 +895,9 @@ void screen_device::device_start()
|
||||
save_item(NAME(m_vblank_start_time));
|
||||
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 (set_vblank_time), please use set_raw instead.\n",this->tag());
|
||||
|
||||
m_is_primary_screen = (this == screen_device_enumerator(machine().root_device()).first());
|
||||
}
|
||||
|
||||
@@ -917,56 +939,41 @@ 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;
|
||||
|
||||
// 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;
|
||||
pre_update_scanline(0);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// configure - configure screen parameters
|
||||
@@ -1006,6 +1013,15 @@ void screen_device::configure(int width, int height, const rectangle &visarea, a
|
||||
else
|
||||
m_vblank_period = m_scantime * (height - visarea.height());
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
/* Performance hack fix for "pong" and "breakout" */
|
||||
if (screen_configured > 10
|
||||
&& width == m_width
|
||||
&& height == m_height
|
||||
&& floorf(ATTOSECONDS_TO_HZ(frame_period)) == floorf(ATTOSECONDS_TO_HZ(m_frame_period)))
|
||||
return;
|
||||
#endif
|
||||
|
||||
// we are now fully configured with the new parameters
|
||||
// and can safely call time_until_pos(), etc.
|
||||
|
||||
@@ -1013,7 +1029,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());
|
||||
|
||||
@@ -1026,6 +1042,17 @@ void screen_device::configure(int width, int height, const rectangle &visarea, a
|
||||
|
||||
// adjust speed if necessary
|
||||
machine().video().update_refresh_speed();
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
float retro_fps_new = ATTOSECONDS_TO_HZ(m_frame_period);
|
||||
if (!screen_configured
|
||||
&& retro_fps_new != retro_fps
|
||||
&& retro_fps_new <= 120.0f
|
||||
&& retro_fps_new >= 40.0f)
|
||||
retro_fps = retro_fps_new;
|
||||
|
||||
screen_configured++;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1041,19 +1068,19 @@ void screen_device::reset_origin(int beamy, int beamx)
|
||||
m_vblank_end_time = curtime - attotime(0, beamy * m_scantime + beamx * m_pixeltime);
|
||||
m_vblank_start_time = m_vblank_end_time - attotime(0, m_vblank_period);
|
||||
|
||||
// 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(0);
|
||||
else
|
||||
m_vblank_begin_timer->adjust(time_until_vblank_start());
|
||||
|
||||
// if we are resetting relative to (0,0) == VBLANK end, call the
|
||||
// scanline 0 timer by hand now; otherwise, adjust it for the future
|
||||
if (beamy == 0 && beamx == 0)
|
||||
reset_partial_updates();
|
||||
else
|
||||
m_scanline0_timer->adjust(time_until_pos(0));
|
||||
|
||||
// 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();
|
||||
else
|
||||
m_vblank_begin_timer->adjust(time_until_vblank_start());
|
||||
}
|
||||
|
||||
|
||||
@@ -1143,21 +1170,40 @@ void screen_device::set_visible_area(int min_x, int max_x, int min_y, int max_y)
|
||||
|
||||
bool screen_device::update_partial(int scanline)
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("Partial: update_partial(%s, %d): ", tag(), scanline));
|
||||
|
||||
// these two checks only apply if we're allowed to skip frames
|
||||
if (!(m_video_attributes & VIDEO_ALWAYS_UPDATE))
|
||||
{
|
||||
// if skipping this frame, bail
|
||||
if (machine().video().skip_this_frame())
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped due to frameskipping\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip if this screen is not visible anywhere
|
||||
if (!machine().render().is_live(*this))
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped because screen not live\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// skip if we already rendered this line
|
||||
if (scanline < m_last_partial_scan)
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped because line was already rendered\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip if we already rendered this frame
|
||||
// this can happen if a cpu timeslice that called update_partial is in the previous frame while scanline 0 already started
|
||||
if (m_last_partial_scan == 0 && m_last_partial_reset > machine().time())
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped because frame was already rendered\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the range of scanlines to render
|
||||
rectangle clip(m_visarea);
|
||||
@@ -1165,46 +1211,61 @@ bool screen_device::update_partial(int scanline)
|
||||
|
||||
// skip if entirely outside of visible area
|
||||
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.top(), clip.bottom()));
|
||||
|
||||
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
|
||||
{
|
||||
// optional screen_update callback before rendering svg (eg. for preparing outputs used by the svg)
|
||||
// bitmap can be considered read-only, as it gets overwritten later
|
||||
if (!m_screen_update_rgb32.isnull())
|
||||
flags = m_screen_update_rgb32(*this, m_bitmap[m_curbitmap].as_rgb32(), clip);
|
||||
|
||||
if (~flags & UPDATE_HAS_NOT_CHANGED)
|
||||
flags = m_svg->render(*this, m_bitmap[m_curbitmap].as_rgb32(), clip);
|
||||
}
|
||||
m_partial_updates_this_frame++;
|
||||
}
|
||||
m_partial_updates_this_frame++;
|
||||
// stop profiling
|
||||
}
|
||||
|
||||
// if we modified the bitmap, we have to commit
|
||||
@@ -1212,7 +1273,7 @@ bool screen_device::update_partial(int scanline)
|
||||
|
||||
// remember where we left off
|
||||
m_last_partial_scan = scanline + 1;
|
||||
m_partial_scan_hpos = -1;
|
||||
m_partial_scan_hpos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1229,11 +1290,17 @@ void screen_device::update_now()
|
||||
{
|
||||
// if skipping this frame, bail
|
||||
if (machine().video().skip_this_frame())
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped due to frameskipping\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// skip if this screen is not visible anywhere
|
||||
if (!machine().render().is_live(*this))
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped because screen not live\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int current_vpos = vpos();
|
||||
@@ -1242,20 +1309,36 @@ void screen_device::update_now()
|
||||
|
||||
// skip if we already rendered this line
|
||||
if (current_vpos < m_last_partial_scan)
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped because line was already rendered\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// if beam position is the same, there's nothing to update
|
||||
if (current_vpos == m_last_partial_scan && current_hpos == m_partial_scan_hpos)
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped because beam position is unchanged\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// skip if we already rendered this frame
|
||||
// this can happen if a cpu timeslice that called update_now is in the previous frame while scanline 0 already started
|
||||
if (m_last_partial_scan == 0 && m_partial_scan_hpos == 0 && m_last_partial_reset > machine().time())
|
||||
{
|
||||
LOG_PARTIAL_UPDATES(("skipped because frame was already rendered\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// 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));
|
||||
@@ -1263,6 +1346,8 @@ void screen_device::update_now()
|
||||
// if there's something to draw, do it
|
||||
if (!clip.empty())
|
||||
{
|
||||
auto profile = g_profiler.start(PROFILER_VIDEO);
|
||||
|
||||
u32 flags = 0;
|
||||
screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
@@ -1291,7 +1376,7 @@ void screen_device::update_now()
|
||||
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)
|
||||
@@ -1301,42 +1386,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)
|
||||
{
|
||||
u32 flags = 0;
|
||||
screen_bitmap &curbitmap = m_bitmap[m_curbitmap];
|
||||
if (m_video_attributes & VIDEO_VARIABLE_WIDTH)
|
||||
{
|
||||
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())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
clip = m_visarea;
|
||||
|
||||
m_partial_updates_this_frame++;
|
||||
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));
|
||||
|
||||
// if we modified the bitmap, we have to commit
|
||||
m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
|
||||
// and if there's something to draw, do it
|
||||
if (!clip.empty())
|
||||
{
|
||||
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)
|
||||
{
|
||||
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())
|
||||
{
|
||||
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++;
|
||||
|
||||
// if we modified the bitmap, we have to commit
|
||||
m_changed |= ~flags & UPDATE_HAS_NOT_CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
// remember where we left off
|
||||
@@ -1352,8 +1444,9 @@ void screen_device::update_now()
|
||||
|
||||
void screen_device::reset_partial_updates()
|
||||
{
|
||||
m_last_partial_reset = machine().time();
|
||||
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));
|
||||
}
|
||||
@@ -1592,7 +1685,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();
|
||||
@@ -1612,7 +1705,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());
|
||||
}
|
||||
@@ -1623,7 +1716,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)
|
||||
@@ -1873,7 +1966,7 @@ void screen_device::finalize_burnin()
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// finalize_burnin - finalize the burnin bitmap
|
||||
// load_effect_overlay -
|
||||
//-------------------------------------------------
|
||||
|
||||
void screen_device::load_effect_overlay(const char *filename)
|
||||
|
||||
+25
-35
@@ -13,6 +13,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rendertypes.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
@@ -31,28 +33,18 @@ enum screen_type_enum
|
||||
SCREEN_TYPE_SVG
|
||||
};
|
||||
|
||||
// texture formats
|
||||
enum texture_format
|
||||
{
|
||||
TEXFORMAT_UNDEFINED = 0, // require a format to be specified
|
||||
TEXFORMAT_PALETTE16, // 16bpp palettized, no alpha
|
||||
TEXFORMAT_RGB32, // 32bpp 8-8-8 RGB
|
||||
TEXFORMAT_ARGB32, // 32bpp 8-8-8-8 ARGB
|
||||
TEXFORMAT_YUY16 // 16bpp 8-8 Y/Cb, Y/Cr in sequence
|
||||
};
|
||||
|
||||
// screen_update callback flags
|
||||
constexpr u32 UPDATE_HAS_NOT_CHANGED = 0x0001; // the video has not changed
|
||||
constexpr u32 UPDATE_HAS_NOT_CHANGED = 0x0001; // the video has not changed
|
||||
|
||||
/*!
|
||||
@defgroup flags for video_attributes
|
||||
@{
|
||||
@def VIDEO_UPDATE_BEFORE_VBLANK
|
||||
update_video called at the start of the VBLANK period
|
||||
update_video called at the start of the VBLANK period, this is the default
|
||||
@todo hack, remove me
|
||||
|
||||
@def VIDEO_UPDATE_AFTER_VBLANK
|
||||
update_video called at the end of the VBLANK period
|
||||
update_video called at the end of the VBLANK period (in other words: before active display)
|
||||
@todo hack, remove me
|
||||
|
||||
@def VIDEO_SELF_RENDER
|
||||
@@ -233,9 +225,10 @@ public:
|
||||
screen_device &set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
|
||||
{
|
||||
assert(pixclock != 0);
|
||||
m_clock = pixclock;
|
||||
set_clock(pixclock);
|
||||
m_refresh = HZ_TO_ATTOSECONDS(pixclock) * htotal * vtotal;
|
||||
m_vblank = m_refresh / vtotal * (vtotal - (vbstart - vbend));
|
||||
m_oldstyle_vblank_supplied = false;
|
||||
m_width = htotal;
|
||||
m_height = vtotal;
|
||||
m_visarea.set(hbend, hbstart ? hbstart - 1 : htotal - 1, vbend, vbstart - 1);
|
||||
@@ -246,6 +239,10 @@ public:
|
||||
xtal.validate(std::string("Configuring screen ") + tag());
|
||||
return set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart);
|
||||
}
|
||||
screen_device &set_raw(const XTAL &xtal, u16 htotal, u16 vtotal, rectangle visarea)
|
||||
{
|
||||
return set_raw(xtal, htotal, visarea.left(), visarea.right() + 1, vtotal, visarea.top(), visarea.bottom() + 1);
|
||||
}
|
||||
void set_refresh(attoseconds_t rate) { m_refresh = rate; }
|
||||
|
||||
/// \brief Set refresh rate in Hertz
|
||||
@@ -389,8 +386,8 @@ public:
|
||||
// beam positioning and state
|
||||
int vpos() const;
|
||||
int hpos() const;
|
||||
DECLARE_READ_LINE_MEMBER(vblank) const { return (machine().time() < m_vblank_end_time) ? 1 : 0; }
|
||||
DECLARE_READ_LINE_MEMBER(hblank) const { int const curpos = hpos(); return (curpos < m_visarea.left() || curpos > m_visarea.right()) ? 1 : 0; }
|
||||
int vblank() const { return (machine().time() < m_vblank_end_time) ? 1 : 0; }
|
||||
int hblank() const { int const curpos = hpos(); return (curpos < m_visarea.left() || curpos > m_visarea.right()) ? 1 : 0; }
|
||||
|
||||
// timing
|
||||
attotime time_until_pos(int vpos, int hpos = 0) const;
|
||||
@@ -428,30 +425,22 @@ public:
|
||||
private:
|
||||
class svg_renderer;
|
||||
|
||||
// timer IDs
|
||||
enum
|
||||
{
|
||||
TID_VBLANK_START,
|
||||
TID_VBLANK_END,
|
||||
TID_SCANLINE0,
|
||||
TID_SCANLINE
|
||||
};
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_validity_check(validity_checker &valid) const override;
|
||||
virtual void device_config_complete() override;
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_stop() override;
|
||||
virtual void device_resolve_objects() override ATTR_COLD;
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
virtual void device_reset() override ATTR_COLD;
|
||||
virtual void device_stop() override ATTR_COLD;
|
||||
virtual void device_post_load() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
// internal helpers
|
||||
void set_container(render_container &container) { m_container = &container; }
|
||||
void realloc_screen_bitmaps();
|
||||
void vblank_begin();
|
||||
void vblank_end();
|
||||
TIMER_CALLBACK_MEMBER(vblank_begin);
|
||||
TIMER_CALLBACK_MEMBER(vblank_end);
|
||||
TIMER_CALLBACK_MEMBER(first_scanline_tick);
|
||||
TIMER_CALLBACK_MEMBER(scanline_tick);
|
||||
void finalize_burnin();
|
||||
void load_effect_overlay(const char *filename);
|
||||
void update_scan_bitmap_size(int y);
|
||||
@@ -473,7 +462,7 @@ private:
|
||||
screen_update_rgb32_delegate m_screen_update_rgb32; // screen update callback (32-bit RGB)
|
||||
devcb_write_line m_screen_vblank; // screen vblank line callback
|
||||
devcb_write32 m_scanline_cb; // screen scanline callback
|
||||
optional_device<device_palette_interface> m_palette; // our palette
|
||||
optional_device<device_palette_interface> m_palette; // our palette
|
||||
u32 m_video_attributes; // flags describing the video system
|
||||
optional_memory_region m_svg_region; // the region in which the svg data is in
|
||||
|
||||
@@ -497,6 +486,7 @@ private:
|
||||
u8 m_curbitmap; // current bitmap index
|
||||
u8 m_curtexture; // current texture index
|
||||
bool m_changed; // has this bitmap changed?
|
||||
attotime m_last_partial_reset; // last time partial updates were reset
|
||||
s32 m_last_partial_scan; // scanline of last partial update
|
||||
s32 m_partial_scan_hpos; // horizontal pixel last rendered on this partial scanline
|
||||
bitmap_argb32 m_screen_overlay_bitmap; // screen overlay bitmap
|
||||
@@ -516,7 +506,7 @@ private:
|
||||
emu_timer * m_scanline0_timer; // scanline 0 timer
|
||||
emu_timer * m_scanline_timer; // scanline timer
|
||||
u64 m_frame_number; // the current frame number
|
||||
u32 m_partial_updates_this_frame;// partial update counter this frame
|
||||
u32 m_partial_updates_this_frame; // partial update counter this frame
|
||||
|
||||
bool m_is_primary_screen;
|
||||
|
||||
@@ -529,7 +519,7 @@ private:
|
||||
|
||||
vblank_state_delegate m_callback;
|
||||
};
|
||||
std::vector<std::unique_ptr<callback_item>> m_callback_list; // list of VBLANK callbacks
|
||||
std::vector<std::unique_ptr<callback_item>> m_callback_list; // list of VBLANK callbacks
|
||||
|
||||
// auto-sizing bitmaps
|
||||
class auto_bitmap_item
|
||||
|
||||
Reference in new issue
Block a user