summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/screen.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/screen.h')
-rw-r--r--src/emu/screen.h317
1 files changed, 172 insertions, 145 deletions
diff --git a/src/emu/screen.h b/src/emu/screen.h
index 0ae11f85b9b..9100ae5bacc 100644
--- a/src/emu/screen.h
+++ b/src/emu/screen.h
@@ -7,11 +7,15 @@
Core MAME screen device.
***************************************************************************/
+
#ifndef MAME_EMU_SCREEN_H
#define MAME_EMU_SCREEN_H
#pragma once
+#include "rendertypes.h"
+
+#include <type_traits>
#include <utility>
@@ -29,16 +33,6 @@ 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
@@ -63,6 +57,9 @@ constexpr u32 UPDATE_HAS_NOT_CHANGED = 0x0001; // the video has not changed
@def VIDEO_UPDATE_SCANLINE
calls VIDEO_UPDATE for every visible scanline, even for skipped frames
+ @def VIDEO_VARIABLE_WIDTH
+ causes the screen to construct its final bitmap from a composite upscale of individual scanline bitmaps
+
@}
*/
@@ -72,6 +69,7 @@ constexpr u32 VIDEO_UPDATE_AFTER_VBLANK = 0x0004;
constexpr u32 VIDEO_SELF_RENDER = 0x0008;
constexpr u32 VIDEO_ALWAYS_UPDATE = 0x0080;
constexpr u32 VIDEO_UPDATE_SCANLINE = 0x0100;
+constexpr u32 VIDEO_VARIABLE_WIDTH = 0x0200;
//**************************************************************************
@@ -207,68 +205,169 @@ public:
void set_orientation(int orientation) { assert(!configured()); m_orientation = orientation; }
void set_physical_aspect(unsigned x, unsigned y) { assert(!configured()); m_phys_aspect = std::make_pair(x, y); }
void set_native_aspect() { assert(!configured()); m_phys_aspect = std::make_pair(~0U, ~0U); }
- void set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
+
+ /// \brief Configure screen parameters
+ ///
+ /// \param [in] pixclock Pixel clock frequency in Hertz.
+ /// \param [in] htotal Total pixel clocks per line, including
+ /// horizontal blanking period.
+ /// \param [in] hbend Index of first visible pixel after horizontal
+ /// blanking period ends.
+ /// \param [in] hbstart Index of first pixel in horzontal blanking
+ /// period after visible pixels.
+ /// \param [in] vtotal Total lines per frame, including vertical
+ /// blanking period.
+ /// \param [in] vbend Index of first visible line after vertical
+ /// blanking period ends.
+ /// \param [in] vbstart Index of first line in vertical blanking
+ /// period after visible lines.
+ /// \return Reference to device for method chaining.
+ 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_width = htotal;
m_height = vtotal;
- m_visarea.set(hbend, hbstart - 1, vbend, vbstart - 1);
+ m_visarea.set(hbend, hbstart ? hbstart - 1 : htotal - 1, vbend, vbstart - 1);
+ return *this;
+ }
+ screen_device &set_raw(const XTAL &xtal, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart)
+ {
+ 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_raw(const XTAL &xtal, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart) { set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart); }
void set_refresh(attoseconds_t rate) { m_refresh = rate; }
- template <typename T> void set_refresh_hz(T &&hz) { set_refresh(HZ_TO_ATTOSECONDS(std::forward<T>(hz))); }
- void set_vblank_time(attoseconds_t time) { m_vblank = time; m_oldstyle_vblank_supplied = true; }
- void set_size(u16 width, u16 height) { m_width = width; m_height = height; }
- void set_visarea(s16 minx, s16 maxx, s16 miny, s16 maxy) { m_visarea.set(minx, maxx, miny, maxy); }
- void set_visarea_full() { m_visarea.set(0, m_width - 1, 0, m_height - 1); } // call after set_size
- void set_default_position(double xscale, double xoffs, double yscale, double yoffs) {
- m_xscale = xscale;
- m_xoffset = xoffs;
- m_yscale = yscale;
- m_yoffset = yoffs;
+
+ /// \brief Set refresh rate in Hertz
+ ///
+ /// Sets refresh rate in Hertz (frames per second). Used in
+ /// conjunction with #set_vblank_time, #set_size and #set_visarea.
+ /// For raster displays, please use #set_raw to configure screen
+ /// parameters in terms of pixel clock.
+ /// \param [in] hz Desired refresh rate.
+ /// \return Reference to device for method chaining.
+ template <typename T> screen_device &set_refresh_hz(T &&hz)
+ {
+ set_refresh(HZ_TO_ATTOSECONDS(std::forward<T>(hz)));
+ return *this;
}
- // FIXME: these should be aware of current device for resolving the tag
- template <class FunctionClass>
- void set_screen_update(u32 (FunctionClass::*callback)(screen_device &, bitmap_ind16 &, const rectangle &), const char *name)
+ /// \brief Set vertical blanking interval time
+ ///
+ /// Sets vertical blanking interval period. Used in conjunction
+ /// with #set_refresh_hz, #set_size and #set_visarea. For raster
+ /// displays, please use #set_raw to configure screen parameters in
+ /// terms of pixel clock.
+ /// \param [in] time Length of vertical blanking interval.
+ /// \return Reference to device for method chaining.
+ screen_device &set_vblank_time(attoseconds_t time)
{
- set_screen_update(screen_update_ind16_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)));
+ m_vblank = time;
+ m_oldstyle_vblank_supplied = true;
+ return *this;
}
- template <class FunctionClass>
- void set_screen_update(u32 (FunctionClass::*callback)(screen_device &, bitmap_rgb32 &, const rectangle &), const char *name)
+
+ /// \brief Set total screen size
+ ///
+ /// Set the total screen size in pixels, including blanking areas if
+ /// applicable. This sets the size of the screen bitmap. Used in
+ /// conjunction with #set_refresh_hz, #set_vblank_time and
+ /// #set_visarea. For raster displays, please use #set_raw to
+ /// configure screen parameters in terms of pixel clock.
+ /// \param [in] width Total width in pixels, including horizontal
+ /// blanking period if applicable.
+ /// \param [in] height Total height in lines, including vertical
+ /// blanking period if applicable.
+ /// \return Reference to device for method chaining.
+ screen_device &set_size(u16 width, u16 height)
{
- set_screen_update(screen_update_rgb32_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)));
+ m_width = width;
+ m_height = height;
+ return *this;
}
- template <class FunctionClass>
- void set_screen_update(const char *devname, u32 (FunctionClass::*callback)(screen_device &, bitmap_ind16 &, const rectangle &), const char *name)
+
+ /// \brief Set visible screen area
+ ///
+ /// Set visible screen area. This should fit within the total
+ /// screen area. Used in conjunction with #set_refresh_hz,
+ /// #set_vblank_time and #set_size. For raster displays, please
+ /// use #set_raw to configure screen parameters in terms of pixel
+ /// clock.
+ /// \param [in] minx First visible pixel index after horizontal
+ /// blanking period ends.
+ /// \param [in] maxx Last visible pixel index before horizontal
+ /// blanking period starts.
+ /// \param [in] miny First visible line index after vertical
+ /// blanking period ends.
+ /// \param [in] maxy Last visible line index before vertical
+ /// blanking period starts.
+ /// \return Reference to device for method chaining.
+ screen_device &set_visarea(s16 minx, s16 maxx, s16 miny, s16 maxy)
{
- set_screen_update(screen_update_ind16_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr)));
+ m_visarea.set(minx, maxx, miny, maxy);
+ return *this;
}
- template <class FunctionClass>
- void set_screen_update(const char *devname, u32 (FunctionClass::*callback)(screen_device &, bitmap_rgb32 &, const rectangle &), const char *name)
+
+ /// \brief Set visible area to full area
+ ///
+ /// Set visible screen area to the full screen area (i.e. no
+ /// horizontal or vertical blanking period). This is generally not
+ /// possible for raster displays, but is useful for other display
+ /// simulations. Must be called after calling #set_size.
+ /// \return Reference to device for method chaining.
+ /// \sa set_visarea
+ screen_device &set_visarea_full()
{
- set_screen_update(screen_update_rgb32_delegate(callback, name, devname, static_cast<FunctionClass *>(nullptr)));
+ m_visarea.set(0, m_width - 1, 0, m_height - 1);
+ return *this;
}
- void set_screen_update(screen_update_ind16_delegate callback)
+
+ void set_default_position(double xscale, double xoffs, double yscale, double yoffs)
{
- m_screen_update_ind16 = callback;
- m_screen_update_rgb32 = screen_update_rgb32_delegate();
+ m_xscale = xscale;
+ m_xoffset = xoffs;
+ m_yscale = yscale;
+ m_yoffset = yoffs;
+ }
+
+ template <typename F>
+ std::enable_if_t<screen_update_ind16_delegate::supports_callback<F>::value> set_screen_update(F &&callback, const char *name)
+ {
+ m_screen_update_ind16.set(std::forward<F>(callback), name);
+ m_screen_update_rgb32 = screen_update_rgb32_delegate(*this);
}
- void set_screen_update(screen_update_rgb32_delegate callback)
+ template <typename F>
+ std::enable_if_t<screen_update_rgb32_delegate::supports_callback<F>::value> set_screen_update(F &&callback, const char *name)
{
- m_screen_update_ind16 = screen_update_ind16_delegate();
- m_screen_update_rgb32 = callback;
+ m_screen_update_ind16 = screen_update_ind16_delegate(*this);
+ m_screen_update_rgb32.set(std::forward<F>(callback), name);
+ }
+ template <typename T, typename F>
+ std::enable_if_t<screen_update_ind16_delegate::supports_callback<F>::value> set_screen_update(T &&target, F &&callback, const char *name)
+ {
+ m_screen_update_ind16.set(std::forward<T>(target), std::forward<F>(callback), name);
+ m_screen_update_rgb32 = screen_update_rgb32_delegate(*this);
+ }
+ template <typename T, typename F>
+ std::enable_if_t<screen_update_rgb32_delegate::supports_callback<F>::value> set_screen_update(T &&target, F &&callback, const char *name)
+ {
+ m_screen_update_ind16 = screen_update_ind16_delegate(*this);
+ m_screen_update_rgb32.set(std::forward<T>(target), std::forward<F>(callback), name);
}
auto screen_vblank() { return m_screen_vblank.bind(); }
auto scanline() { m_video_attributes |= VIDEO_UPDATE_SCANLINE; return m_scanline_cb.bind(); }
- template<typename T> void set_palette(T &&tag) { m_palette.set_tag(std::forward<T>(tag)); }
- void set_video_attributes(u32 flags) { m_video_attributes = flags; }
- void set_color(rgb_t color) { m_color = color; }
- void set_svg_region(const char *region) { m_svg_region = region; } // default region is device tag
+ template <typename T> screen_device &set_palette(T &&tag) { m_palette.set_tag(std::forward<T>(tag)); return *this; }
+ screen_device &set_no_palette() { m_palette.set_tag(finder_base::DUMMY_TAG); return *this; }
+ screen_device &set_video_attributes(u32 flags) { m_video_attributes = flags; return *this; }
+ screen_device &set_color(rgb_t color) { m_color = color; return *this; }
+ template <typename T> screen_device &set_svg_region(T &&tag) { m_svg_region.set_tag(std::forward<T>(tag)); return *this; } // default region is device tag
// information getters
render_container &container() const { assert(m_container != nullptr); return *m_container; }
@@ -286,8 +385,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;
@@ -295,6 +394,7 @@ public:
attotime time_until_vblank_end() const;
attotime time_until_update() const { return (m_video_attributes & VIDEO_UPDATE_AFTER_VBLANK) ? time_until_vblank_end() : time_until_vblank_start(); }
attotime scan_period() const { return attotime(0, m_scantime); }
+ attotime pixel_period() const { return attotime(0, m_pixeltime); }
attotime frame_period() const { return attotime(0, m_frame_period); }
u64 frame_number() const { return m_frame_number; }
@@ -304,6 +404,7 @@ public:
// updating
int partial_updates() const { return m_partial_updates_this_frame; }
+ int partial_scan_hpos() const { return m_partial_scan_hpos; }
bool update_partial(int scanline);
void update_now();
void reset_partial_updates();
@@ -323,32 +424,29 @@ 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);
+ void pre_update_scanline(int y);
+ void create_composited_bitmap();
+ void destroy_scan_bitmaps();
+ void allocate_scan_bitmaps();
// inline configuration data
screen_type_enum m_type; // type of screen
@@ -363,27 +461,31 @@ 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
- const char * m_svg_region; // the region in which the svg data is in
+ optional_memory_region m_svg_region; // the region in which the svg data is in
// internal state
render_container * m_container; // pointer to our container
std::unique_ptr<svg_renderer> m_svg; // the svg renderer
// dimensions
+ int m_max_width; // maximum width encountered
int m_width; // current width (HTOTAL)
int m_height; // current height (VTOTAL)
rectangle m_visarea; // current visible area (HBLANK end/start, VBLANK end/start)
+ std::vector<int> m_scan_widths; // current width, in samples, of each individual scanline
// textures and bitmaps
texture_format m_texformat; // texture format
render_texture * m_texture[2]; // 2x textures for the screen bitmap
screen_bitmap m_bitmap[2]; // 2x bitmaps for rendering
+ std::vector<bitmap_t *> m_scan_bitmaps[2]; // 2x bitmaps for each individual scanline
bitmap_ind8 m_priority; // priority bitmap
bitmap_ind64 m_burnin; // burn-in bitmap
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
@@ -403,7 +505,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;
@@ -416,7 +518,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
@@ -437,81 +539,6 @@ private:
DECLARE_DEVICE_TYPE(SCREEN, screen_device)
// iterator helper
-typedef device_type_iterator<screen_device> screen_device_iterator;
-
-/*!
- @defgroup Screen device configuration functions
- @{
- @def set_type
- Modify the screen device type
- @see screen_type_enum
-
- @def set_raw
- Configures screen parameters for the given screen.
- @remark It's better than using @see set_refresh_hz and @see set_vblank_time but still not enough.
-
- @param _pixclock
- Pixel Clock frequency value
-
- @param _htotal
- Total number of horizontal pixels, including hblank period.
-
- @param _hbend
- Horizontal pixel position for HBlank end event, also first pixel where screen rectangle is visible.
-
- @param _hbstart
- Horizontal pixel position for HBlank start event, also last pixel where screen rectangle is visible.
-
- @param _vtotal
- Total number of vertical pixels, including vblank period.
-
- @param _vbend
- Vertical pixel position for VBlank end event, also first pixel where screen rectangle is visible.
-
- @param _vbstart
- Vertical pixel position for VBlank start event, also last pixel where screen rectangle is visible.
-
- @def set_refresh_hz
- Sets the number of Frames Per Second for this screen
- @remarks Please use @see set_raw instead. Gives imprecise timings.
-
- @param _rate
- FPS number
-
- @def set_vblank_time
- Sets the vblank time of the given screen
- @remarks Please use @see MCFG_SCREEN_RAW_PARAMS instead. Gives imprecise timings.
-
- @param _time
- Time parameter, in attotime value
-
- @def set_size
- Sets total screen size, including H/V-Blanks
- @remarks Please use @see set_raw instead. Gives imprecise timings.
-
- @param _width
- Screen horizontal size
-
- @param _height
- Screen vertical size
-
- @def set_visarea
- Sets screen visible area
- @remarks Please use @see set_raw instead. Gives imprecise timings.
-
- @param _minx
- Screen left border
-
- @param _maxx
- Screen right border, must be in N-1 format
-
- @param _miny
- Screen top border
-
- @param _maxx
- Screen bottom border, must be in N-1 format
-
- @}
- */
+typedef device_type_enumerator<screen_device> screen_device_enumerator;
#endif // MAME_EMU_SCREEN_H