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