summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-10-03 22:46:40 +1000
committer Vas Crabb <vas@vastheman.com>2020-10-03 22:46:40 +1000
commit0c6d1a7b51ccc7310d42bc1bb99af69ae7c537b6 (patch)
tree37b1189a5472465ad4a1f99f83588a77d5f2314a
parent7066028be11e3af3cd80c24a00a2aa84ec9867b3 (diff)
emu/rendlay.cpp: Pre-load image components when changing video options.
-rw-r--r--src/emu/render.cpp59
-rw-r--r--src/emu/render.h41
-rw-r--r--src/emu/rendlay.cpp109
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 (&current_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 (&current_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