diff options
author | 2020-10-03 22:46:40 +1000 | |
---|---|---|
committer | 2020-10-03 22:46:40 +1000 | |
commit | 0c6d1a7b51ccc7310d42bc1bb99af69ae7c537b6 (patch) | |
tree | 37b1189a5472465ad4a1f99f83588a77d5f2314a | |
parent | 7066028be11e3af3cd80c24a00a2aa84ec9867b3 (diff) |
emu/rendlay.cpp: Pre-load image components when changing video options.
-rw-r--r-- | src/emu/render.cpp | 59 | ||||
-rw-r--r-- | src/emu/render.h | 41 | ||||
-rw-r--r-- | src/emu/rendlay.cpp | 109 |
3 files changed, 141 insertions, 68 deletions
diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 83cd3524532..4ffa4f0a2ba 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -1018,6 +1018,7 @@ void render_target::set_view(unsigned viewindex) { m_curview = viewindex; current_view().recompute(visibility_mask(), m_layerconfig.zoom_to_screen()); + current_view().preload(); } } @@ -1047,6 +1048,7 @@ void render_target::set_visibility_toggle(unsigned index, bool enable) else m_views[m_curview].second &= ~(u32(1) << index); current_view().recompute(visibility_mask(), m_layerconfig.zoom_to_screen()); + current_view().preload(); } @@ -1341,34 +1343,31 @@ render_primitive_list &render_target::get_primitives() if (m_manager.machine().phase() >= machine_phase::RESET) { // we're running - iterate over items in the view - for (layout_view::item &curitem : current_view().items()) + for (layout_view::item &curitem : current_view().visible_items()) { - if ((visibility_mask() & curitem.visibility_mask()) == curitem.visibility_mask()) - { - // first apply orientation to the bounds - render_bounds bounds = curitem.bounds(); - apply_orientation(bounds, root_xform.orientation); - normalize_bounds(bounds); - - // apply the transform to the item - object_transform item_xform; - item_xform.xoffs = root_xform.xoffs + bounds.x0 * root_xform.xscale; - item_xform.yoffs = root_xform.yoffs + bounds.y0 * root_xform.yscale; - item_xform.xscale = (bounds.x1 - bounds.x0) * root_xform.xscale; - item_xform.yscale = (bounds.y1 - bounds.y0) * root_xform.yscale; - item_xform.color.r = curitem.color().r * root_xform.color.r; - item_xform.color.g = curitem.color().g * root_xform.color.g; - item_xform.color.b = curitem.color().b * root_xform.color.b; - item_xform.color.a = curitem.color().a * root_xform.color.a; - item_xform.orientation = orientation_add(curitem.orientation(), root_xform.orientation); - item_xform.no_center = false; - - // if there is no associated element, it must be a screen element - if (curitem.screen()) - add_container_primitives(list, root_xform, item_xform, curitem.screen()->container(), curitem.blend_mode()); - else - add_element_primitives(list, item_xform, *curitem.element(), curitem.state(), curitem.blend_mode()); - } + // first apply orientation to the bounds + render_bounds bounds = curitem.bounds(); + apply_orientation(bounds, root_xform.orientation); + normalize_bounds(bounds); + + // apply the transform to the item + object_transform item_xform; + item_xform.xoffs = root_xform.xoffs + bounds.x0 * root_xform.xscale; + item_xform.yoffs = root_xform.yoffs + bounds.y0 * root_xform.yscale; + item_xform.xscale = (bounds.x1 - bounds.x0) * root_xform.xscale; + item_xform.yscale = (bounds.y1 - bounds.y0) * root_xform.yscale; + item_xform.color.r = curitem.color().r * root_xform.color.r; + item_xform.color.g = curitem.color().g * root_xform.color.g; + item_xform.color.b = curitem.color().b * root_xform.color.b; + item_xform.color.a = curitem.color().a * root_xform.color.a; + item_xform.orientation = orientation_add(curitem.orientation(), root_xform.orientation); + item_xform.no_center = false; + + // if there is no associated element, it must be a screen element + if (curitem.screen()) + add_container_primitives(list, root_xform, item_xform, curitem.screen()->container(), curitem.blend_mode()); + else + add_element_primitives(list, item_xform, *curitem.element(), curitem.state(), curitem.blend_mode()); } } else @@ -1619,7 +1618,10 @@ void render_target::resolve_tags() { view.resolve_tags(); if (¤t_view() == &view) + { view.recompute(visibility_mask(), m_layerconfig.zoom_to_screen()); + view.preload(); + } } } } @@ -2687,7 +2689,10 @@ void render_target::config_load(util::xml::data_node const &targetnode) } if (¤t_view() == &view->first.get()) + { current_view().recompute(visibility_mask(), m_layerconfig.zoom_to_screen()); + current_view().preload(); + } } } diff --git a/src/emu/render.h b/src/emu/render.h index 5ca922b408a..e1be1baf8c4 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -581,7 +581,26 @@ public: int default_state() const { return m_defstate; } render_texture *state_texture(int state); + // operations + void preload(); + private: + struct bounds_step + { + int state; + render_bounds bounds; + render_bounds delta; + }; + using bounds_vector = std::vector<bounds_step>; + + struct color_step + { + int state; + render_color color; + render_color delta; + }; + using color_vector = std::vector<color_step>; + /// \brief An image, rectangle, or disk in an element /// /// Each layout_element contains one or more components. Each @@ -610,11 +629,12 @@ private: render_color color(int state) const; // operations + virtual void preload(running_machine &machine); virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) = 0; protected: // helper - virtual int maxstate() const { return -1; } + virtual int maxstate() const; // drawing helpers void draw_text(render_font &font, bitmap_argb32 &dest, const rectangle &bounds, const char *str, int align, const render_color &color); @@ -629,22 +649,6 @@ private: void apply_skew(bitmap_argb32 &dest, int skewwidth); private: - struct bounds_step - { - int state; - render_bounds bounds; - render_bounds delta; - }; - using bounds_vector = std::vector<bounds_step>; - - struct color_step - { - int state; - render_color color; - render_color delta; - }; - using color_vector = std::vector<color_step>; - // internal state int const m_statemask; // bits of state used to control visibility int const m_stateval; // masked state value to make component visible @@ -907,6 +911,7 @@ public: float effective_aspect() const { return m_effaspect; } const render_bounds &bounds() const { return m_bounds; } bool has_visible_screen(screen_device &screen) const; + const item_ref_vector &visible_items() const { return m_visible_items; } const item_ref_vector &visible_screen_items() const { return m_screen_items; } const item_ref_vector &interactive_items() const { return m_interactive_items; } const edge_vector &interactive_edges_x() const { return m_interactive_edges_x; } @@ -918,6 +923,7 @@ public: // operations void recompute(u32 visibility_mask, bool zoom_to_screens); + void preload(); // resolve tags, if any void resolve_tags(); @@ -946,6 +952,7 @@ private: float m_effaspect; // X/Y of the layout in current configuration render_bounds m_bounds; // computed bounds of the view in current configuration item_list m_items; // list of layout items + item_ref_vector m_visible_items; // all visible items item_ref_vector m_screen_items; // visible items that represent screens to draw item_ref_vector m_interactive_items;// visible items that can accept pointer input edge_vector m_interactive_edges_x; diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp index 4c76c72a0c1..d877131492f 100644 --- a/src/emu/rendlay.cpp +++ b/src/emu/rendlay.cpp @@ -36,8 +36,9 @@ #define LOG_GROUP_BOUNDS_RESOLUTION (1U << 1) #define LOG_INTERACTIVE_ITEMS (1U << 2) +#define LOG_IMAGE_LOAD (1U << 3) -//#define VERBOSE (LOG_GROUP_BOUNDS_RESOLUTION | LOG_INTERACTIVE_ITEMS) +//#define VERBOSE (LOG_GROUP_BOUNDS_RESOLUTION | LOG_INTERACTIVE_ITEMS | LOG_IMAGE_LOAD) #define LOG_OUTPUT_FUNC osd_printf_verbose #include "logmacro.h" @@ -1302,6 +1303,18 @@ render_texture *layout_element::state_texture(int state) //------------------------------------------------- +// preload - perform expensive loading upfront +// for all components +//------------------------------------------------- + +void layout_element::preload() +{ + for (component::ptr const &curcomp : m_complist) + curcomp->preload(machine()); +} + + +//------------------------------------------------- // element_scale - scale an element by rendering // all the components at the appropriate // resolution @@ -1345,8 +1358,13 @@ public: { } -protected: // overrides + virtual void preload(running_machine &machine) override + { + if (!m_bitmap.valid()) + load_bitmap(machine); + } + virtual void draw(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state) override { if (!m_bitmap.valid()) @@ -1401,28 +1419,37 @@ private: // internal helpers void load_bitmap(running_machine &machine) { + LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load image file '%s/%s'\n", m_dirname, m_imagefile); emu_file file(machine.options().art_path(), OPEN_FLAG_READ); ru_imgformat const format = render_detect_image(file, m_dirname.c_str(), m_imagefile.c_str()); switch (format) { case RENDUTIL_IMGFORMAT_ERROR: + LOGMASKED(LOG_IMAGE_LOAD, "Image component error detecting image file format\n"); break; case RENDUTIL_IMGFORMAT_PNG: // load the basic bitmap + LOGMASKED(LOG_IMAGE_LOAD, "Image component detected PNG file format\n"); m_hasalpha = render_load_png(m_bitmap, file, m_dirname.c_str(), m_imagefile.c_str()); break; default: // try JPG + LOGMASKED(LOG_IMAGE_LOAD, "Image component failed to detect image file format, trying JPEG\n"); render_load_jpeg(m_bitmap, file, m_dirname.c_str(), m_imagefile.c_str()); break; } // load the alpha bitmap if specified if (m_bitmap.valid() && !m_alphafile.empty()) - render_load_png(m_bitmap, file, m_dirname.c_str(), m_alphafile.c_str(), true); + { + // TODO: no way to detect corner case where we had alpha from the image but the alpha PNG makes it entirely opaque + LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load alpha channel from file '%s/%s'\n", m_dirname, m_alphafile); + if (render_load_png(m_bitmap, file, m_dirname.c_str(), m_alphafile.c_str(), true)) + m_hasalpha = true; + } // if we can't load the bitmap, allocate a dummy one and report an error if (!m_bitmap.valid()) @@ -2884,6 +2911,36 @@ layout_element::component::component(environment &env, util::xml::data_node cons //------------------------------------------------- +// normalize_bounds - normalize component bounds +//------------------------------------------------- + +void layout_element::component::normalize_bounds(float xoffs, float yoffs, float xscale, float yscale) +{ + auto i(m_bounds.begin()); + i->bounds.x0 = (i->bounds.x0 - xoffs) * xscale; + i->bounds.x1 = (i->bounds.x1 - xoffs) * xscale; + i->bounds.y0 = (i->bounds.y0 - yoffs) * yscale; + i->bounds.y1 = (i->bounds.y1 - yoffs) * yscale; + + auto j(i); + while (m_bounds.end() != ++j) + { + j->bounds.x0 = (j->bounds.x0 - xoffs) * xscale; + j->bounds.x1 = (j->bounds.x1 - xoffs) * xscale; + j->bounds.y0 = (j->bounds.y0 - yoffs) * yscale; + j->bounds.y1 = (j->bounds.y1 - yoffs) * yscale; + + i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state); + i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state); + i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state); + i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state); + + i = j; + } +} + + +//------------------------------------------------- // statewrap - get state wraparound requirements //------------------------------------------------- @@ -2999,32 +3056,20 @@ render_color layout_element::component::color(int state) const //------------------------------------------------- -// normalize_bounds - normalize component bounds +// preload - perform expensive operations upfront //------------------------------------------------- -void layout_element::component::normalize_bounds(float xoffs, float yoffs, float xscale, float yscale) +void layout_element::component::preload(running_machine &machine) { - auto i(m_bounds.begin()); - i->bounds.x0 = (i->bounds.x0 - xoffs) * xscale; - i->bounds.x1 = (i->bounds.x1 - xoffs) * xscale; - i->bounds.y0 = (i->bounds.y0 - yoffs) * yscale; - i->bounds.y1 = (i->bounds.y1 - yoffs) * yscale; - - auto j(i); - while (m_bounds.end() != ++j) - { - j->bounds.x0 = (j->bounds.x0 - xoffs) * xscale; - j->bounds.x1 = (j->bounds.x1 - xoffs) * xscale; - j->bounds.y0 = (j->bounds.y0 - yoffs) * yscale; - j->bounds.y1 = (j->bounds.y1 - yoffs) * yscale; +} - i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state); - i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state); - i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state); - i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state); +//------------------------------------------------- +// maxstate - maximum state drawn differently +//------------------------------------------------- - i = j; - } +int layout_element::component::maxstate() const +{ + return -1; } @@ -3473,6 +3518,7 @@ void layout_view::recompute(u32 visibility_mask, bool zoom_to_screen) // reset the bounds and collected active items render_bounds scrbounds{ 0.0f, 0.0f, 0.0f, 0.0f }; m_bounds = scrbounds; + m_visible_items.clear(); m_screen_items.clear(); m_interactive_items.clear(); m_interactive_edges_x.clear(); @@ -3487,6 +3533,7 @@ void layout_view::recompute(u32 visibility_mask, bool zoom_to_screen) if ((visibility_mask & curitem.visibility_mask()) == curitem.visibility_mask()) { // accumulate bounds + m_visible_items.emplace_back(curitem); if (first) m_bounds = curitem.m_rawbounds; else @@ -3577,6 +3624,20 @@ void layout_view::recompute(u32 visibility_mask, bool zoom_to_screen) } } +//------------------------------------------------- +// preload - perform expensive loading upfront +// for visible elements +//------------------------------------------------- + +void layout_view::preload() +{ + for (item &curitem : m_visible_items) + { + if (curitem.element()) + curitem.element()->preload(); + } +} + //------------------------------------------------- // resolve_tags - resolve tags |