Convert rendlay objects into C++, reduce the number of unused textures

allocated.

Fix texture leak in crsshair.c.
This commit is contained in:
Aaron Giles 2010-10-18 01:51:58 +00:00
parent d73bcf6e1c
commit d8edbd14f2
13 changed files with 2234 additions and 2262 deletions

View File

@ -154,8 +154,9 @@ static void create_bitmap(running_machine *machine, int player)
char filename[20];
rgb_t color = crosshair_colors[player];
/* if we have a bitmap for this player, kill it */
/* if we have a bitmap and texture for this player, kill it */
global_free(global.bitmap[player]);
machine->render().texture_free(global.texture[player]);
if (global.name[player][0] != 0)
{
@ -208,9 +209,6 @@ static void create_bitmap(running_machine *machine, int player)
void crosshair_init(running_machine *machine)
{
const input_port_config *port;
const input_field_config *field;
/* request a callback upon exiting */
machine->add_notifier(MACHINE_NOTIFY_EXIT, crosshair_exit);
@ -221,8 +219,8 @@ void crosshair_init(running_machine *machine)
global.auto_time = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
/* determine who needs crosshairs */
for (port = machine->m_portlist.first(); port != NULL; port = port->next())
for (field = port->fieldlist; field != NULL; field = field->next)
for (const input_port_config *port = machine->m_portlist.first(); port != NULL; port = port->next())
for (const input_field_config *field = port->fieldlist; field != NULL; field = field->next)
if (field->crossaxis != CROSSHAIR_AXIS_NONE)
{
int player = field->player;
@ -258,10 +256,8 @@ void crosshair_init(running_machine *machine)
static void crosshair_exit(running_machine &machine)
{
int player;
/* free bitmaps and textures for each player */
for (player = 0; player < MAX_PLAYERS; player++)
for (int player = 0; player < MAX_PLAYERS; player++)
{
machine.render().texture_free(global.texture[player]);
global.texture[player] = NULL;

View File

@ -374,6 +374,8 @@ public:
m_count(0) { }
virtual ~simple_list() { reset(); }
resource_pool &pool() const { return m_pool; }
T *first() const { return m_head; }
T *last() const { return m_tail; }

View File

@ -201,21 +201,19 @@ inline void normalize_bounds(render_bounds &bounds)
// appropriate layer index and blendmode
//-------------------------------------------------
inline int get_layer_and_blendmode(const layout_view &view, int index, int &blendmode)
inline item_layer get_layer_and_blendmode(const layout_view &view, int index, int &blendmode)
{
const int *layer_order = layer_order_standard;
int layer;
// if we have multiple backdrop pieces and no overlays, render:
// backdrop (add) + screens (add) + bezels (alpha)
// else render:
// screens (add) + overlays (RGB multiply) + backdrop (add) + bezels (alpha)
if (view.itemlist[ITEM_LAYER_BACKDROP] != NULL && view.itemlist[ITEM_LAYER_BACKDROP]->next != NULL && view.itemlist[ITEM_LAYER_OVERLAY] == NULL)
const int *layer_order = layer_order_standard;
if (view.first_item(ITEM_LAYER_BACKDROP) != NULL && view.first_item(ITEM_LAYER_BACKDROP)->next() != NULL && view.first_item(ITEM_LAYER_OVERLAY) == NULL)
layer_order = layer_order_alternate;
// select the layer
layer = layer_order[index];
int layer = layer_order[index];
// pick a blendmode
if (layer == ITEM_LAYER_SCREEN && layer_order == layer_order_standard)
@ -227,7 +225,7 @@ inline int get_layer_and_blendmode(const layout_view &view, int index, int &blen
else
blendmode = BLENDMODE_ALPHA;
return layer;
return item_layer(layer);
}
@ -1025,7 +1023,7 @@ render_target::render_target(render_manager &manager, const char *layoutfile, UI
: m_next(NULL),
m_manager(manager),
m_curview(NULL),
m_filelist(NULL),
m_filelist(*auto_alloc(&manager.machine(), simple_list<layout_file>(manager.machine().m_respool))),
m_flags(flags),
m_listindex(0),
m_width(640),
@ -1033,19 +1031,17 @@ render_target::render_target(render_manager &manager, const char *layoutfile, UI
m_pixel_aspect(0.0f),
m_max_refresh(0),
m_orientation(0),
m_layerconfig(LAYER_CONFIG_DEFAULT),
m_base_view(NULL),
m_base_orientation(ROT0),
m_base_layerconfig(LAYER_CONFIG_DEFAULT),
m_maxtexwidth(65536),
m_maxtexheight(65536),
m_debug_containers(manager.machine().m_respool)
{
// determine the base layer configuration based on options
if (!options_get_bool(manager.machine().options(), OPTION_USE_BACKDROPS)) m_base_layerconfig &= ~LAYER_CONFIG_ENABLE_BACKDROP;
if (!options_get_bool(manager.machine().options(), OPTION_USE_OVERLAYS)) m_base_layerconfig &= ~LAYER_CONFIG_ENABLE_OVERLAY;
if (!options_get_bool(manager.machine().options(), OPTION_USE_BEZELS)) m_base_layerconfig &= ~LAYER_CONFIG_ENABLE_BEZEL;
if (options_get_bool(manager.machine().options(), OPTION_ARTWORK_CROP)) m_base_layerconfig |= LAYER_CONFIG_ZOOM_TO_SCREEN;
m_base_layerconfig.set_backdrops_enabled(options_get_bool(manager.machine().options(), OPTION_USE_BACKDROPS));
m_base_layerconfig.set_overlays_enabled(options_get_bool(manager.machine().options(), OPTION_USE_OVERLAYS));
m_base_layerconfig.set_bezels_enabled(options_get_bool(manager.machine().options(), OPTION_USE_BEZELS));
m_base_layerconfig.set_zoom_to_screen(options_get_bool(manager.machine().options(), OPTION_ARTWORK_CROP));
// determine the base orientation based on options
m_orientation = ROT0;
@ -1086,13 +1082,7 @@ render_target::render_target(render_manager &manager, const char *layoutfile, UI
render_target::~render_target()
{
// free the layout files
while (m_filelist != NULL)
{
layout_file *temp = m_filelist;
m_filelist = temp->next;
layout_file_free(temp);
}
auto_free(&m_manager.machine(), &m_filelist);
}
@ -1133,18 +1123,6 @@ void render_target::set_bounds(INT32 width, INT32 height, float pixel_aspect)
}
//-------------------------------------------------
// set_layer_config - set the layer config of a
// target
//-------------------------------------------------
void render_target::set_layer_config(int layerconfig)
{
m_layerconfig = layerconfig;
layout_view_recompute(m_curview, layerconfig);
}
//-------------------------------------------------
// set_view - dynamically change the view for
// a target
@ -1156,7 +1134,7 @@ void render_target::set_view(int viewindex)
if (view != NULL)
{
m_curview = view;
layout_view_recompute(view, m_layerconfig);
view->recompute(m_layerconfig);
}
}
@ -1180,7 +1158,7 @@ void render_target::set_max_texture_size(int maxwidth, int maxheight)
const char *render_target::view_name(int viewindex)
{
layout_view *view = view_by_index(viewindex);
return (view != NULL) ? view->name : NULL;
return (view != NULL) ? view->name() : NULL;
}
@ -1190,10 +1168,10 @@ const char *render_target::view_name(int viewindex)
// given view
//-------------------------------------------------
UINT32 render_target::view_screens(int viewindex)
const render_screen_list &render_target::view_screens(int viewindex)
{
layout_view *view = view_by_index(viewindex);
return (view != NULL) ? view->screens : NULL;
return (view != NULL) ? view->screens() : s_empty_screen_list;
}
@ -1212,7 +1190,7 @@ void render_target::compute_visible_area(INT32 target_width, INT32 target_height
if (target_pixel_aspect != 0.0f)
{
// start with the aspect ratio of the square pixel layout
width = (zoom_to_screen() && m_curview->screens > 0) ? m_curview->scraspect : m_curview->aspect;
width = m_curview->effective_aspect(m_layerconfig);
height = 1.0f;
// first apply target orientation
@ -1254,44 +1232,43 @@ void render_target::compute_minimum_size(INT32 &minwidth, INT32 &minheight)
{
float maxxscale = 1.0f, maxyscale = 1.0f;
int screens_considered = 0;
// early exit in case we are called between device teardown and render teardown
if (m_manager.machine().m_devicelist.count() == 0)
{
minwidth = 640;
minheight = 480;
return;
}
// scan the current view for all screens
for (int layer = 0; layer < ITEM_LAYER_MAX; layer++)
for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; layer++)
// iterate over items in the layer
for (view_item *item = m_curview->itemlist[layer]; item != NULL; item = item->next)
if (item->element == NULL)
for (layout_view::item *curitem = m_curview->first_item(layer); curitem != NULL; curitem = curitem->next())
if (curitem->screen() != NULL)
{
const screen_device_config *scrconfig = downcast<const screen_device_config *>(m_manager.machine().config->m_devicelist.find(SCREEN, item->index));
screen_device *screendev = m_manager.machine().device<screen_device>(scrconfig->tag());
// we may be called very early, before machine->visible_area is initialized; handle that case
// use a hard-coded default visible area for vector screens
screen_device *screen = curitem->screen();
const rectangle vectorvis = { 0, 639, 0, 479 };
const rectangle *visarea = NULL;
if (scrconfig->screen_type() == SCREEN_TYPE_VECTOR)
visarea = &vectorvis;
else if (screendev != NULL && screendev->started())
visarea = &screendev->visible_area();
else
visarea = &scrconfig->visible_area();
const rectangle &visarea = (screen->screen_type() == SCREEN_TYPE_VECTOR) ? vectorvis : screen->visible_area();
// apply target orientation to the bounds
render_bounds bounds = item->bounds;
render_bounds bounds = curitem->bounds();
apply_orientation(bounds, m_orientation);
normalize_bounds(bounds);
// based on the orientation of the screen container, check the bitmap
render_container *container = m_manager.m_screen_container_list.find(item->index);
float xscale, yscale;
if (!(orientation_add(m_orientation, container->orientation()) & ORIENTATION_SWAP_XY))
if (!(orientation_add(m_orientation, screen->container().orientation()) & ORIENTATION_SWAP_XY))
{
xscale = (float)(visarea->max_x + 1 - visarea->min_x) / (bounds.x1 - bounds.x0);
yscale = (float)(visarea->max_y + 1 - visarea->min_y) / (bounds.y1 - bounds.y0);
xscale = (float)(visarea.max_x + 1 - visarea.min_x) / (bounds.x1 - bounds.x0);
yscale = (float)(visarea.max_y + 1 - visarea.min_y) / (bounds.y1 - bounds.y0);
}
else
{
xscale = (float)(visarea->max_y + 1 - visarea->min_y) / (bounds.x1 - bounds.x0);
yscale = (float)(visarea->max_x + 1 - visarea->min_x) / (bounds.y1 - bounds.y0);
xscale = (float)(visarea.max_y + 1 - visarea.min_y) / (bounds.x1 - bounds.x0);
yscale = (float)(visarea.max_x + 1 - visarea.min_x) / (bounds.y1 - bounds.y0);
}
// pick the greater
@ -1348,17 +1325,17 @@ render_primitive_list &render_target::get_primitives()
// iterate over layers back-to-front, but only if we're running
if (m_manager.machine().phase() >= MACHINE_PHASE_RESET)
for (int layernum = 0; layernum < ITEM_LAYER_MAX; layernum++)
for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; layernum++)
{
int blendmode;
int layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
if (m_curview->layenabled[layer])
item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
if (m_curview->layer_enabled(layer))
{
// iterate over items in the layer
for (view_item *item = m_curview->itemlist[layer]; item != NULL; item = item->next)
for (layout_view::item *curitem = m_curview->first_item(layer); curitem != NULL; curitem = curitem->next())
{
// first apply orientation to the bounds
render_bounds bounds = item->bounds;
render_bounds bounds = curitem->bounds();
apply_orientation(bounds, root_xform.orientation);
normalize_bounds(bounds);
@ -1368,32 +1345,18 @@ render_primitive_list &render_target::get_primitives()
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 = item->color.r * root_xform.color.r;
item_xform.color.g = item->color.g * root_xform.color.g;
item_xform.color.b = item->color.b * root_xform.color.b;
item_xform.color.a = item->color.a * root_xform.color.a;
item_xform.orientation = orientation_add(item->orientation, root_xform.orientation);
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 (item->element != NULL)
{
int state = 0;
if (item->output_name[0] != 0)
state = output_get_value(item->output_name);
else if (item->input_tag[0] != 0)
{
const input_field_config *field = input_field_by_tag_and_mask(m_manager.machine().m_portlist, item->input_tag, item->input_mask);
if (field != NULL)
state = ((input_port_read_safe(&m_manager.machine(), item->input_tag, 0) ^ field->defvalue) & item->input_mask) ? 1 : 0;
}
add_element_primitives(list, item_xform, *item->element, state, blendmode);
}
if (curitem->screen() != NULL)
add_container_primitives(list, item_xform, curitem->screen()->container(), blendmode);
else
{
render_container *container = m_manager.m_screen_container_list.find(item->index);
add_container_primitives(list, item_xform, *container, blendmode);
}
add_element_primitives(list, item_xform, *curitem->element(), curitem->state(), blendmode);
}
}
}
@ -1468,8 +1431,9 @@ render_primitive_list &render_target::get_primitives()
bool render_target::map_point_container(INT32 target_x, INT32 target_y, render_container &container, float &container_x, float &container_y)
{
view_item *item;
return map_point_internal(target_x, target_y, &container, container_x, container_y, item);
const char *input_tag;
UINT32 input_mask;
return map_point_internal(target_x, target_y, &container, container_x, container_y, input_tag, input_mask);
}
@ -1481,15 +1445,7 @@ bool render_target::map_point_container(INT32 target_x, INT32 target_y, render_c
bool render_target::map_point_input(INT32 target_x, INT32 target_y, const char *&input_tag, UINT32 &input_mask, float &input_x, float &input_y)
{
view_item *item = NULL;
bool result = map_point_internal(target_x, target_y, NULL, input_x, input_y, item);
if (result && item != NULL)
{
input_tag = item->input_tag;
input_mask = item->input_mask;
}
return result;
return map_point_internal(target_x, target_y, NULL, input_x, input_y, input_tag, input_mask);
}
@ -1547,6 +1503,17 @@ void render_target::debug_top(render_container &container)
}
//-------------------------------------------------
// update_layer_config - recompute after a layer
// config change
//-------------------------------------------------
void render_target::update_layer_config()
{
m_curview->recompute(m_layerconfig);
}
//-------------------------------------------------
// load_layout_files - load layout files for a
// given render target
@ -1554,16 +1521,10 @@ void render_target::debug_top(render_container &container)
void render_target::load_layout_files(const char *layoutfile, bool singlefile)
{
layout_file **nextfile = &m_filelist;
// if there's an explicit file, load that first
const char *basename = m_manager.machine().basename();
if (layoutfile != NULL)
{
*nextfile = layout_file_load(m_manager.machine(), basename, layoutfile);
if (*nextfile != NULL)
nextfile = &(*nextfile)->next;
}
load_layout_file(basename, layoutfile);
// if we're only loading this file, we know our final result
if (singlefile)
@ -1571,50 +1532,95 @@ void render_target::load_layout_files(const char *layoutfile, bool singlefile)
// try to load a file based on the driver name
const game_driver *gamedrv = m_manager.machine().gamedrv;
*nextfile = layout_file_load(m_manager.machine(), basename, gamedrv->name);
if (*nextfile == NULL)
*nextfile = layout_file_load(m_manager.machine(), basename, "default");
if (*nextfile != NULL)
nextfile = &(*nextfile)->next;
if (!load_layout_file(basename, gamedrv->name))
load_layout_file(basename, "default");
// if a default view has been specified, use that as a fallback
if (gamedrv->default_layout != NULL)
{
*nextfile = layout_file_load(m_manager.machine(), NULL, gamedrv->default_layout);
if (*nextfile != NULL)
nextfile = &(*nextfile)->next;
}
load_layout_file(NULL, gamedrv->default_layout);
if (m_manager.machine().m_config.m_default_layout != NULL)
{
*nextfile = layout_file_load(m_manager.machine(), NULL, m_manager.machine().m_config.m_default_layout);
if (*nextfile != NULL)
nextfile = &(*nextfile)->next;
}
load_layout_file(NULL, m_manager.machine().m_config.m_default_layout);
// try to load another file based on the parent driver name
const game_driver *cloneof = driver_get_clone(gamedrv);
if (cloneof != NULL)
{
*nextfile = layout_file_load(m_manager.machine(), cloneof->name, cloneof->name);
if (*nextfile == NULL)
*nextfile = layout_file_load(m_manager.machine(), cloneof->name, "default");
if (*nextfile != NULL)
nextfile = &(*nextfile)->next;
}
if (!load_layout_file(cloneof->name, cloneof->name))
load_layout_file(cloneof->name, "default");
// now do the built-in layouts for single-screen games
if (screen_count(m_manager.machine().m_config) == 1)
{
if (gamedrv->flags & ORIENTATION_SWAP_XY)
*nextfile = layout_file_load(m_manager.machine(), NULL, layout_vertical);
load_layout_file(NULL, layout_vertical);
else
*nextfile = layout_file_load(m_manager.machine(), NULL, layout_horizont);
assert_always(*nextfile != NULL, "Couldn't parse default layout??");
nextfile = &(*nextfile)->next;
load_layout_file(NULL, layout_horizont);
assert_always(m_filelist.count() > 0, "Couldn't parse default layout??");
}
}
//-------------------------------------------------
// load_layout_file - load a single layout file
// and append it to our list
//-------------------------------------------------
bool render_target::load_layout_file(const char *dirname, const char *filename)
{
// if the first character of the "file" is an open brace, assume it is an XML string
xml_data_node *rootnode;
if (filename[0] == '<')
rootnode = xml_string_read(filename, NULL);
// otherwise, assume it is a file
else
{
// build the path and optionally prepend the directory
astring fname(filename, ".lay");
if (dirname != NULL)
fname.ins(0, PATH_SEPARATOR).ins(0, dirname);
// attempt to open the file; bail if we can't
mame_file *layoutfile;
file_error filerr = mame_fopen(SEARCHPATH_ARTWORK, fname, OPEN_FLAG_READ, &layoutfile);
if (filerr != FILERR_NONE)
return false;
// read the file
rootnode = xml_file_read(mame_core_file(layoutfile), NULL);
mame_fclose(layoutfile);
}
// if we didn't get a properly-formatted XML file, record a warning and exit
if (rootnode == NULL)
{
if (filename[0] != '<')
mame_printf_warning("Improperly formatted XML file '%s', ignorning\n", filename);
else
mame_printf_warning("Improperly formatted XML string, ignorning");
return false;
}
// parse and catch any errors
bool result = true;
try
{
m_filelist.append(*auto_alloc(&m_manager.machine(), layout_file(m_manager.machine(), *rootnode, dirname)));
}
catch (emu_fatalerror &err)
{
if (filename[0] != '<')
mame_printf_warning("Error in XML file '%s': %s\n", filename, err.string());
else
mame_printf_warning("Error in XML string: %s", err.string());
result = false;
}
// free the root node
xml_file_free(rootnode);
return result;
}
//-------------------------------------------------
// add_container_primitives - add primitives
// based on the container
@ -1767,7 +1773,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const
}
// add the overlay if it exists
if (container.overlay() != NULL && screen_overlay_enabled())
if (container.overlay() != NULL && m_layerconfig.screen_overlay_enabled())
{
INT32 width, height;
@ -1801,16 +1807,16 @@ void render_target::add_container_primitives(render_primitive_list &list, const
// for an element in the current state
//-------------------------------------------------
void render_target::add_element_primitives(render_primitive_list &list, const object_transform &xform, const layout_element &element, int state, int blendmode)
void render_target::add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode)
{
// if we're out of range, bail
if (state > element.maxstate)
if (state > element.maxstate())
return;
if (state < 0)
state = 0;
// get a pointer to the relevant texture
render_texture *texture = element.elemtex[state].texture;
render_texture *texture = element.state_texture(state);
if (texture != NULL)
{
render_primitive *prim = list.alloc(render_primitive::QUAD);
@ -1856,11 +1862,13 @@ void render_target::add_element_primitives(render_primitive_list &list, const ob
// mapping points
//-------------------------------------------------
bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, view_item *&mapped_item)
bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, const char *&mapped_input_tag, UINT32 &mapped_input_mask)
{
// default to point not mapped
mapped_x = -1.0;
mapped_y = -1.0;
mapped_input_tag = NULL;
mapped_input_mask = 0;
// convert target coordinates to float
float target_fx = (float)target_x / m_width;
@ -1875,39 +1883,38 @@ bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_co
// this point was successfully mapped
mapped_x = target_fx;
mapped_y = target_fy;
mapped_item = NULL;
return true;
}
return false;
}
// loop through each layer
for (int layernum = 0; layernum < ITEM_LAYER_MAX; layernum++)
for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; layernum++)
{
int blendmode;
int layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
if (m_curview->layenabled[layer])
item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode);
if (m_curview->layer_enabled(layer))
{
// iterate over items in the layer
for (view_item *item = m_curview->itemlist[layer]; item != NULL; item = item->next)
for (layout_view::item *item = m_curview->first_item(layer); item != NULL; item = item->next())
{
bool checkit;
// if we're looking for a particular container, verify that we have the right one
if (container != NULL)
checkit = (item->element == NULL && container == m_manager.m_screen_container_list.find(item->index));
checkit = (item->screen() != NULL && &item->screen()->container() == container);
// otherwise, assume we're looking for an input
else
checkit = (item->input_tag[0] != 0);
checkit = item->has_input();
// this target is worth looking at; now check the point
if (checkit && target_fx >= item->bounds.x0 && target_fx < item->bounds.x1 && target_fy >= item->bounds.y0 && target_fy < item->bounds.y1)
if (checkit && target_fx >= item->bounds().x0 && target_fx < item->bounds().x1 && target_fy >= item->bounds().y0 && target_fy < item->bounds().y1)
{
// point successfully mapped
mapped_x = (target_fx - item->bounds.x0) / (item->bounds.x1 - item->bounds.x0);
mapped_y = (target_fy - item->bounds.y0) / (item->bounds.y1 - item->bounds.y0);
mapped_item = item;
mapped_x = (target_fx - item->bounds().x0) / (item->bounds().x1 - item->bounds().x0);
mapped_y = (target_fy - item->bounds().y0) / (item->bounds().y1 - item->bounds().y0);
mapped_input_tag = item->input_tag_and_mask(mapped_input_mask);
return true;
}
}
@ -1925,9 +1932,9 @@ bool render_target::map_point_internal(INT32 target_x, INT32 target_y, render_co
layout_view *render_target::view_by_index(int index) const
{
// scan the list of views within each layout, skipping those that don't apply
for (layout_file *file = m_filelist; file != NULL; file = file->next)
for (layout_view *view = file->viewlist; view != NULL; view = view->next)
if (!(m_flags & RENDER_CREATE_NO_ART) || !layout_view_has_art(view))
for (layout_file *file = m_filelist.first(); file != NULL; file = file->next())
for (layout_view *view = file->first_view(); view != NULL; view = view->next())
if (!(m_flags & RENDER_CREATE_NO_ART) || !view->has_art())
if (index-- == 0)
return view;
return NULL;
@ -1945,9 +1952,9 @@ int render_target::view_index(layout_view &targetview) const
int index = 0;
// scan the list of views within each layout, skipping those that don't apply
for (layout_file *file = m_filelist; file != NULL; file = file->next)
for (layout_view *view = file->viewlist; view != NULL; view = view->next)
if (!(m_flags & RENDER_CREATE_NO_ART) || !layout_view_has_art(view))
for (layout_file *file = m_filelist.first(); file != NULL; file = file->next())
for (layout_view *view = file->first_view(); view != NULL; view = view->next())
if (!(m_flags & RENDER_CREATE_NO_ART) || !view->has_art())
{
if (&targetview == view)
return index;
@ -2038,17 +2045,17 @@ bool render_target::config_save(xml_data_node &targetnode)
// output the view
if (m_curview != m_base_view)
{
xml_set_attribute(&targetnode, "view", m_curview->name);
xml_set_attribute(&targetnode, "view", m_curview->name());
changed = true;
}
// output the layer config
if (m_layerconfig != m_base_layerconfig)
{
xml_set_attribute_int(&targetnode, "backdrops", backdrops_enabled());
xml_set_attribute_int(&targetnode, "overlays", overlays_enabled());
xml_set_attribute_int(&targetnode, "bezels", bezels_enabled());
xml_set_attribute_int(&targetnode, "zoom", zoom_to_screen());
xml_set_attribute_int(&targetnode, "backdrops", m_layerconfig.backdrops_enabled());
xml_set_attribute_int(&targetnode, "overlays", m_layerconfig.overlays_enabled());
xml_set_attribute_int(&targetnode, "bezels", m_layerconfig.bezels_enabled());
xml_set_attribute_int(&targetnode, "zoom", m_layerconfig.zoom_to_screen());
changed = true;
}
@ -2360,7 +2367,7 @@ render_manager::render_manager(running_machine &machine)
// create one container per screen
for (screen_device *screen = screen_first(machine); screen != NULL; screen = screen_next(screen))
container_alloc(screen);
screen->set_container(*container_alloc(screen));
}
@ -2385,15 +2392,11 @@ render_manager::~render_manager()
bool render_manager::is_live(screen_device &screen) const
{
int screen_index = screen.machine->m_devicelist.index(SCREEN, screen.tag());
assert(screen_index != -1);
// iterate over all live targets and or together their screen masks
UINT32 bitmask = 0;
for (render_target *target = m_targetlist.first(); target != NULL; target = target->next())
bitmask |= target->view_screens(target->view());
return (bitmask & (1 << screen_index)) ? true : false;
if (target->view_screens(target->view()).contains(screen))
return true;
return false;
}
@ -2484,21 +2487,6 @@ float render_manager::ui_aspect()
}
//-------------------------------------------------
// container_for_screen - return the container
// allocated for the given screen device
//-------------------------------------------------
render_container *render_manager::container_for_screen(screen_device *screen)
{
// scan the list of screen containers for a match
for (render_container *container = m_screen_container_list.first(); container != NULL; container = container->next())
if (container->screen() == screen)
return container;
return NULL;
}
//-------------------------------------------------
// texture_alloc - allocate a new texture
//-------------------------------------------------

View File

@ -113,19 +113,6 @@ const UINT8 RENDER_CREATE_SINGLE_FILE = 0x02; // only load views from the file
const UINT8 RENDER_CREATE_HIDDEN = 0x04; // don't make this target visible
// layer config masks
const UINT8 LAYER_CONFIG_ENABLE_BACKDROP = 0x01; // enable backdrop layers
const UINT8 LAYER_CONFIG_ENABLE_OVERLAY = 0x02; // enable overlay layers
const UINT8 LAYER_CONFIG_ENABLE_BEZEL = 0x04; // enable bezel layers
const UINT8 LAYER_CONFIG_ZOOM_TO_SCREEN = 0x08; // zoom to screen area by default
const UINT8 LAYER_CONFIG_ENABLE_SCREEN_OVERLAY = 0x10; // enable screen overlays
const UINT8 LAYER_CONFIG_DEFAULT = (LAYER_CONFIG_ENABLE_BACKDROP |
LAYER_CONFIG_ENABLE_OVERLAY |
LAYER_CONFIG_ENABLE_BEZEL |
LAYER_CONFIG_ENABLE_SCREEN_OVERLAY);
// flags for primitives
const int PRIMFLAG_TEXORIENT_SHIFT = 0;
const UINT32 PRIMFLAG_TEXORIENT_MASK = 15 << PRIMFLAG_TEXORIENT_SHIFT;
@ -183,10 +170,9 @@ class render_manager;
typedef struct _xml_data_node xml_data_node;
typedef struct _render_font render_font;
struct object_transform;
typedef struct _layout_element layout_element;
typedef struct _layout_view layout_view;
typedef struct _view_item view_item;
typedef struct _layout_file layout_file;
class layout_element;
class layout_view;
class layout_file;
// texture scaling callback
@ -243,6 +229,90 @@ struct render_texinfo
};
// ======================> render_screen_list
// a render_screen_list is a list of screen_devices
class render_screen_list
{
// screen list item
class item
{
friend class simple_list<item>;
friend class render_screen_list;
public:
// construction/destruction
item(screen_device &screen)
: m_next(NULL),
m_screen(screen) { }
// state
item * m_next; // next screen in list
screen_device & m_screen; // reference to screen device
};
public:
// construction/destruction
render_screen_list(resource_pool &pool = global_resource_pool)
: m_list(pool) { }
// getters
int count() const { return m_list.count(); }
// operations
void add(screen_device &screen) { m_list.append(*pool_alloc(m_list.pool(), item(screen))); }
void reset() { m_list.reset(); }
// query
bool contains(screen_device &screen) const
{
for (item *curitem = m_list.first(); curitem != NULL; curitem = curitem->m_next)
if (&curitem->m_screen == &screen) return true;
return false;
}
private:
// internal state
simple_list<item> m_list;
};
// ======================> render_layer_config
// render_layer_config - describes the state of layers
class render_layer_config
{
static const UINT8 ENABLE_BACKDROP = 0x01; // enable backdrop layers
static const UINT8 ENABLE_OVERLAY = 0x02; // enable overlay layers
static const UINT8 ENABLE_BEZEL = 0x04; // enable bezel layers
static const UINT8 ZOOM_TO_SCREEN = 0x08; // zoom to screen area by default
static const UINT8 ENABLE_SCREEN_OVERLAY = 0x10; // enable screen overlays
static const UINT8 DEFAULT = ENABLE_BACKDROP | ENABLE_OVERLAY | ENABLE_BEZEL | ENABLE_SCREEN_OVERLAY;
public:
render_layer_config()
: m_state(DEFAULT) { }
bool operator==(const render_layer_config &rhs) const { return m_state == rhs.m_state; }
bool operator!=(const render_layer_config &rhs) const { return m_state != rhs.m_state; }
bool backdrops_enabled() const { return ((m_state & ENABLE_BACKDROP) != 0); }
bool overlays_enabled() const { return ((m_state & ENABLE_OVERLAY) != 0); }
bool bezels_enabled() const { return ((m_state & ENABLE_BEZEL) != 0); }
bool screen_overlay_enabled() const { return ((m_state & ENABLE_SCREEN_OVERLAY) != 0); }
bool zoom_to_screen() const { return ((m_state & ZOOM_TO_SCREEN) != 0); }
render_layer_config &set_backdrops_enabled(bool enable) { if (enable) m_state |= ENABLE_BACKDROP; else m_state &= ~ENABLE_BACKDROP; return *this; }
render_layer_config &set_overlays_enabled(bool enable) { if (enable) m_state |= ENABLE_OVERLAY; else m_state &= ~ENABLE_OVERLAY; return *this; }
render_layer_config &set_bezels_enabled(bool enable) { if (enable) m_state |= ENABLE_BEZEL; else m_state &= ~ENABLE_BEZEL; return *this; }
render_layer_config &set_screen_overlay_enabled(bool enable) { if (enable) m_state |= ENABLE_SCREEN_OVERLAY; else m_state &= ~ENABLE_SCREEN_OVERLAY; return *this; }
render_layer_config &set_zoom_to_screen(bool zoom) { if (zoom) m_state |= ZOOM_TO_SCREEN; else m_state &= ~ZOOM_TO_SCREEN; return *this; }
private:
UINT8 m_state;
};
// ======================> render_primitive
// render_primitive - a single low-level primitive for the rendering engine
@ -530,14 +600,9 @@ public:
float pixel_aspect() const { return m_pixel_aspect; }
float max_update_rate() const { return m_max_refresh; }
int orientation() const { return m_orientation; }
int layer_config() const { return m_layerconfig; }
render_layer_config layer_config() const { return m_layerconfig; }
int view() const { return view_index(*m_curview); }
bool hidden() const { return ((m_flags & RENDER_CREATE_HIDDEN) != 0); }
bool backdrops_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_BACKDROP) != 0; }
bool overlays_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_OVERLAY) != 0; }
bool bezels_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_BEZEL) != 0; }
bool screen_overlay_enabled() const { return (m_layerconfig & LAYER_CONFIG_ENABLE_SCREEN_OVERLAY) != 0; }
bool zoom_to_screen() const { return (m_layerconfig & LAYER_CONFIG_ZOOM_TO_SCREEN) != 0; }
bool is_ui_target() const;
int index() const;
@ -545,18 +610,26 @@ public:
void set_bounds(INT32 width, INT32 height, float pixel_aspect = 0);
void set_max_update_rate(float updates_per_second) { m_max_refresh = updates_per_second; }
void set_orientation(int orientation) { m_orientation = orientation; }
void set_layer_config(int layerconfig);
void set_view(int viewindex);
void set_max_texture_size(int maxwidth, int maxheight);
void set_backdrops_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_BACKDROP) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_BACKDROP)); }
void set_overlays_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_OVERLAY) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_OVERLAY)); }
void set_bezels_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_BEZEL) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_BEZEL)); }
void set_screen_overlay_enabled(bool enable) { set_layer_config(enable ? (m_layerconfig | LAYER_CONFIG_ENABLE_SCREEN_OVERLAY) : (m_layerconfig & ~LAYER_CONFIG_ENABLE_SCREEN_OVERLAY)); }
void set_zoom_to_screen(bool zoom) { set_layer_config(zoom ? (m_layerconfig | LAYER_CONFIG_ZOOM_TO_SCREEN) : (m_layerconfig & ~LAYER_CONFIG_ZOOM_TO_SCREEN)); }
// layer config getters
bool backdrops_enabled() const { return m_layerconfig.backdrops_enabled(); }
bool overlays_enabled() const { return m_layerconfig.overlays_enabled(); }
bool bezels_enabled() const { return m_layerconfig.bezels_enabled(); }
bool screen_overlay_enabled() const { return m_layerconfig.screen_overlay_enabled(); }
bool zoom_to_screen() const { return m_layerconfig.zoom_to_screen(); }
// layer config setters
void set_backdrops_enabled(bool enable) { m_layerconfig.set_backdrops_enabled(enable); update_layer_config(); }
void set_overlays_enabled(bool enable) { m_layerconfig.set_overlays_enabled(enable); update_layer_config(); }
void set_bezels_enabled(bool enable) { m_layerconfig.set_bezels_enabled(enable); update_layer_config(); }
void set_screen_overlay_enabled(bool enable) { m_layerconfig.set_screen_overlay_enabled(enable); update_layer_config(); }
void set_zoom_to_screen(bool zoom) { m_layerconfig.set_zoom_to_screen(zoom); update_layer_config(); }
// view information
const char *view_name(int viewindex);
UINT32 view_screens(int viewindex);
const render_screen_list &view_screens(int viewindex);
// bounds computations
void compute_visible_area(INT32 target_width, INT32 target_height, float target_pixel_aspect, int target_orientation, INT32 &visible_width, INT32 &visible_height);
@ -579,10 +652,12 @@ public:
private:
// internal helpers
void update_layer_config();
void load_layout_files(const char *layoutfile, bool singlefile);
bool load_layout_file(const char *dirname, const char *filename);
void add_container_primitives(render_primitive_list &list, const object_transform &xform, render_container &container, int blendmode);
void add_element_primitives(render_primitive_list &list, const object_transform &xform, const layout_element &element, int state, int blendmode);
bool map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, view_item *&mapped_item);
void add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode);
bool map_point_internal(INT32 target_x, INT32 target_y, render_container *container, float &mapped_x, float &mapped_y, const char *&mapped_input_tag, UINT32 &mapped_input_mask);
// config callbacks
void config_load(xml_data_node &targetnode);
@ -606,7 +681,7 @@ private:
render_target * m_next; // link to next target
render_manager & m_manager; // reference to our owning manager
layout_view * m_curview; // current view
layout_file * m_filelist; // list of layout files
simple_list<layout_file> &m_filelist; // list of layout files
UINT32 m_flags; // creation flags
render_primitive_list m_primlist[NUM_PRIMLISTS]; // list of primitives
int m_listindex; // index of next primlist to use
@ -616,15 +691,17 @@ private:
float m_pixel_aspect; // aspect ratio of individual pixels
float m_max_refresh; // maximum refresh rate, 0 or if none
int m_orientation; // orientation
int m_layerconfig; // layer configuration
render_layer_config m_layerconfig; // layer configuration
layout_view * m_base_view; // the view at the time of first frame
int m_base_orientation; // the orientation at the time of first frame
int m_base_layerconfig; // the layer configuration at the time of first frame
render_layer_config m_base_layerconfig; // the layer configuration at the time of first frame
int m_maxtexwidth; // maximum width of a texture
int m_maxtexheight; // maximum height of a texture
simple_list<render_container> m_debug_containers; // list of debug containers
INT32 m_clear_extent_count; // number of clear extents
INT32 m_clear_extents[MAX_CLEAR_EXTENTS]; // array of clear extents
static const render_screen_list s_empty_screen_list;
};
@ -658,9 +735,6 @@ public:
void set_ui_target(render_target &target) { m_ui_target = &target; }
float ui_aspect();
// screen containers
render_container *container_for_screen(screen_device *screen);
// UI containers
render_container &ui_container() const { assert(m_ui_container != NULL); return *m_ui_container; }

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,36 @@
Core rendering layout parser and manager.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
@ -14,206 +42,281 @@
#include "render.h"
#include <math.h>
//**************************************************************************
// CONSTANTS
//**************************************************************************
/***************************************************************************
Theory of operation
-------------------
A render "target" is described by 5 parameters:
- width = width, in pixels
- height = height, in pixels
- bpp = depth, in bits per pixel
- orientation = orientation of the target
- pixel_aspect = aspect ratio of the pixels
Width, height, and bpp are self-explanatory. The remaining parameters
need some additional explanation.
Regarding orientation, there are three orientations that need to be
dealt with: target orientation, UI orientation, and game orientation.
In the current model, the UI orientation tracks the target orientation
so that the UI is (in theory) facing the correct direction. The game
orientation is specified by the game driver and indicates how the
game and artwork are rotated.
Regarding pixel_aspect, this is the aspect ratio of the individual
pixels, not the aspect ratio of the screen. You can determine this by
dividing the aspect ratio of the screen by the aspect ratio of the
resolution. For example, a 4:3 screen displaying 640x480 gives a
pixel aspect ratio of (4/3)/(640/480) = 1.0, meaning the pixels are
square. That same screen displaying 1280x1024 would have a pixel
aspect ratio of (4/3)/(1280/1024) = 1.06666, meaning the pixels are
slightly wider than they are tall.
Artwork is always assumed to be a 1.0 pixel aspect ratio. The game
screens themselves can be variable aspect ratios.
***************************************************************************/
/***************************************************************************
CONSTANTS
***************************************************************************/
enum
enum item_layer
{
ITEM_LAYER_BACKDROP = 0,
ITEM_LAYER_FIRST = 0,
ITEM_LAYER_BACKDROP = ITEM_LAYER_FIRST,
ITEM_LAYER_SCREEN,
ITEM_LAYER_OVERLAY,
ITEM_LAYER_BEZEL,
ITEM_LAYER_MAX
};
DECLARE_ENUM_OPERATORS(item_layer);
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
typedef struct _element_component element_component;
typedef struct _element_texture element_texture;
typedef struct _layout_element layout_element;
typedef struct _view_item_state view_item_state;
typedef struct _view_item view_item;
typedef struct _layout_view layout_view;
typedef struct _layout_file layout_file;
/* an element_texture encapsulates a texture for a given element in a given state */
struct _element_texture
// ======================> layout_element
// a layout_element is a single named element, which may have multiple components
class layout_element
{
layout_element * element; /* pointer back to the element */
render_texture * texture; /* texture for this state */
int state; /* associated state number */
friend class simple_list<layout_element>;
public:
// construction/destruction
layout_element(running_machine &machine, xml_data_node &elemnode, const char *dirname);
virtual ~layout_element();
// getters
layout_element *next() const { return m_next; }
const char *name() const { return m_name; }
running_machine &machine() const { return m_machine; }
int default_state() const { return m_defstate; }
int maxstate() const { return m_maxstate; }
render_texture *state_texture(int state);
private:
// a component represents an image, rectangle, or disk in an element
class component
{
friend class layout_element;
friend class simple_list<component>;
public:
// construction/destruction
component(running_machine &machine, xml_data_node &compnode, const char *dirname);
~component();
// getters
component *next() const { return m_next; }
const render_bounds &bounds() const { return m_bounds; }
// operations
void draw(running_machine &machine, bitmap_t &dest, const rectangle &bounds, int state);
private:
// component types
enum component_type
{
CTYPE_INVALID = 0,
CTYPE_IMAGE,
CTYPE_RECT,
CTYPE_DISK,
CTYPE_TEXT,
CTYPE_LED7SEG,
CTYPE_LED14SEG,
CTYPE_LED16SEG,
CTYPE_LED14SEGSC,
CTYPE_LED16SEGSC,
CTYPE_DOTMATRIX,
CTYPE_MAX
};
// helpers
void draw_rect(bitmap_t &dest, const rectangle &bounds);
void draw_disk(bitmap_t &dest, const rectangle &bounds);
void draw_text(running_machine &machine, bitmap_t &dest, const rectangle &bounds);
bitmap_t *load_bitmap();
void draw_led7seg(bitmap_t &dest, const rectangle &bounds, int pattern);
void draw_led14seg(bitmap_t &dest, const rectangle &bounds, int pattern);
void draw_led14segsc(bitmap_t &dest, const rectangle &bounds, int pattern);
void draw_led16seg(bitmap_t &dest, const rectangle &bounds, int pattern);
void draw_led16segsc(bitmap_t &dest, const rectangle &bounds, int pattern);
void draw_dotmatrix(bitmap_t &dest, const rectangle &bounds, int pattern);
void draw_segment_horizontal_caps(bitmap_t &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color);
void draw_segment_horizontal(bitmap_t &dest, int minx, int maxx, int midy, int width, rgb_t color);
void draw_segment_vertical_caps(bitmap_t &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color);
void draw_segment_vertical(bitmap_t &dest, int miny, int maxy, int midx, int width, rgb_t color);
void draw_segment_diagonal_1(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
void draw_segment_diagonal_2(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
void draw_segment_decimal(bitmap_t &dest, int midx, int midy, int width, rgb_t color);
void draw_segment_comma(bitmap_t &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
void apply_skew(bitmap_t &dest, int skewwidth);
// internal state
component * m_next; // link to next component
component_type m_type; // type of component
int m_state; // state where this component is visible (-1 means all states)
render_bounds m_bounds; // bounds of the element
render_color m_color; // color of the element
astring m_string; // string for text components
bitmap_t * m_bitmap; // source bitmap for images
astring m_dirname; // directory name of image file (for lazy loading)
astring m_imagefile; // name of the image file (for lazy loading)
astring m_alphafile; // name of the alpha file (for lazy loading)
bool m_hasalpha; // is there any alpha component present?
};
// a texture encapsulates a texture for a given element in a given state
class texture
{
public:
texture();
~texture();
layout_element * m_element; // pointer back to the element
render_texture * m_texture; // texture for this state
int m_state; // associated state number
};
// internal helpers
static void element_scale(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
// internal state
layout_element * m_next; // link to next element
running_machine & m_machine; // reference to the owning machine
astring m_name; // name of this element
simple_list<component> m_complist; // list of components
int m_defstate; // default state of this element
int m_maxstate; // maximum state value for all components
texture * m_elemtex; // array of element textures used for managing the scaled bitmaps
};
/* a layout_element is a single named element, which may have multiple components */
struct _layout_element
// ======================> layout_view
// a layout_view encapsulates a named list of items
class layout_view
{
layout_element * next; /* link to next element */
running_machine * machine;
const char * name; /* name of this element */
element_component * complist; /* head of the list of components */
int defstate; /* default state of this element */
int maxstate; /* maximum state value for all components */
element_texture * elemtex; /* array of element textures used for managing the scaled bitmaps */
friend class simple_list<layout_view>;
public:
// an item is a single backdrop, screen, overlay, or bezel item
class item
{
friend class layout_view;
friend class simple_list<item>;
public:
// construction/destruction
item(running_machine &machine, xml_data_node &itemnode, simple_list<layout_element> &elemlist);
virtual ~item();
// getters
item *next() const { return m_next; }
layout_element *element() const { return m_element; }
screen_device *screen() { return m_screen; }
const render_bounds &bounds() const { return m_bounds; }
const render_color &color() const { return m_color; }
int orientation() const { return m_orientation; }
render_container *screen_container(running_machine &machine) const { return (m_screen != NULL) ? &m_screen->container() : NULL; }
bool has_input() const { return bool(m_input_tag); }
const char *input_tag_and_mask(UINT32 &mask) const { mask = m_input_mask; return m_input_tag; }
// fetch state based on configured source
int state() const;
private:
// internal state
item * m_next; // link to next item
layout_element * m_element; // pointer to the associated element (non-screens only)
astring m_output_name; // name of this item
astring m_input_tag; // input tag of this item
UINT32 m_input_mask; // input mask of this item
screen_device * m_screen; // pointer to screen
int m_orientation; // orientation of this item
render_bounds m_bounds; // bounds of the item
render_bounds m_rawbounds; // raw (original) bounds of the item
render_color m_color; // color of the item
};
// construction/destruction
layout_view(running_machine &machine, xml_data_node &viewnode, simple_list<layout_element> &elemlist);
virtual ~layout_view();
// getters
layout_view *next() const { return m_next; }
item *first_item(item_layer layer) const;
const char *name() const { return m_name; }
const render_screen_list &screens() const { return m_screens; }
bool layer_enabled(item_layer layer) const { return m_layenabled[layer]; }
//
bool has_art() const { return (m_backdrop_list.count() + m_overlay_list.count() + m_bezel_list.count() != 0); }
float effective_aspect(render_layer_config config) const { return (config.zoom_to_screen() && m_screens.count() != 0) ? m_scraspect : m_aspect; }
// operations
void recompute(render_layer_config layerconfig);
private:
// internal state
layout_view * m_next; // pointer to next layout in the list
astring m_name; // name of the layout
float m_aspect; // X/Y of the layout
float m_scraspect; // X/Y of the screen areas
render_screen_list m_screens; // list of active screens
render_bounds m_bounds; // computed bounds of the view
render_bounds m_scrbounds; // computed bounds of the screens within the view
render_bounds m_expbounds; // explicit bounds of the view
bool m_layenabled[ITEM_LAYER_MAX]; // is this layer enabled?
simple_list<item> m_backdrop_list; // list of backdrop items
simple_list<item> m_screen_list; // list of screen items
simple_list<item> m_overlay_list; // list of overlay items
simple_list<item> m_bezel_list; // list of bezel items
};
/* a view_item_state contains the string-tagged state of a view item */
struct _view_item_state
// ======================> layout_file
// a layout_file consists of a list of elements and a list of views
class layout_file
{
view_item_state * next; /* pointer to the next one */
const char * name; /* string that was set */
int curstate; /* current state */
};
friend class simple_list<layout_file>;
public:
// construction/destruction
layout_file(running_machine &machine, xml_data_node &rootnode, const char *dirname);
virtual ~layout_file();
// getters
layout_file *next() const { return m_next; }
layout_element *first_element() const { return m_elemlist.first(); }
layout_view *first_view() const { return m_viewlist.first(); }
/* a view_item is a single backdrop, screen, overlay, or bezel item */
struct _view_item
{
view_item * next; /* link to next item */
layout_element * element; /* pointer to the associated element (non-screens only) */
const char * output_name; /* name of this item */
const char * input_tag; /* input tag of this item */
UINT32 input_mask; /* input mask of this item */
int index; /* index for this item (screens only) */
int orientation; /* orientation of this item */
render_bounds bounds; /* bounds of the item */
render_bounds rawbounds; /* raw (original) bounds of the item */
render_color color; /* color of the item */
};
/* a layout_view encapsulates a named list of items */
struct _layout_view
{
layout_view * next; /* pointer to next layout in the list */
const char * name; /* name of the layout */
float aspect; /* X/Y of the layout */
float scraspect; /* X/Y of the screen areas */
UINT32 screens; /* bitmask of screens used */
render_bounds bounds; /* computed bounds of the view */
render_bounds scrbounds; /* computed bounds of the screens within the view */
render_bounds expbounds; /* explicit bounds of the view */
UINT8 layenabled[ITEM_LAYER_MAX]; /* is this layer enabled? */
view_item * itemlist[ITEM_LAYER_MAX]; /* list of layout items for each layer */
};
/* a layout_file consists of a list of elements and a list of views */
struct _layout_file
{
layout_file * next; /* pointer to the next file in the list */
layout_element * elemlist; /* list of shared layout elements */
layout_view * viewlist; /* list of views */
private:
// internal state
layout_file * m_next; // pointer to the next file in the list
simple_list<layout_element> m_elemlist; // list of shared layout elements
simple_list<layout_view> m_viewlist; // list of views
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
/* ----- layout views ----- */
void layout_view_recompute(layout_view *view, int layerconfig);
// single screen layouts
extern const char layout_horizont[]; // horizontal 4:3 screens
extern const char layout_vertical[]; // vertical 4:3 screens
// dual screen layouts
extern const char layout_dualhsxs[]; // dual 4:3 screens side-by-side
extern const char layout_dualhovu[]; // dual 4:3 screens above and below
extern const char layout_dualhuov[]; // dual 4:3 screens below and above
// triple screen layouts
extern const char layout_triphsxs[]; // triple 4:3 screens side-by-side
// generic color overlay layouts
extern const char layout_ho20ffff[]; // horizontal 4:3 with 20,FF,FF color overlay
extern const char layout_ho2eff2e[]; // horizontal 4:3 with 2E,FF,2E color overlay
extern const char layout_ho4f893d[]; // horizontal 4:3 with 4F,89,3D color overlay
extern const char layout_ho88ffff[]; // horizontal 4:3 with 88,FF,FF color overlay
extern const char layout_hoa0a0ff[]; // horizontal 4:3 with A0,A0,FF color overlay
extern const char layout_hoffe457[]; // horizontal 4:3 with FF,E4,57 color overlay
extern const char layout_hoffff20[]; // horizontal 4:3 with FF,FF,20 color overlay
extern const char layout_voffff20[]; // vertical 4:3 with FF,FF,20 color overlay
/* ----- layout file parsing ----- */
layout_file *layout_file_load(running_machine &machine, const char *dirname, const char *filename);
void layout_file_free(layout_file *file);
/***************************************************************************
GLOBAL VARIABLES
***************************************************************************/
/* single screen layouts */
extern const char layout_horizont[]; /* horizontal 4:3 screens */
extern const char layout_vertical[]; /* vertical 4:3 screens */
/* dual screen layouts */
extern const char layout_dualhsxs[]; /* dual 4:3 screens side-by-side */
extern const char layout_dualhovu[]; /* dual 4:3 screens above and below */
extern const char layout_dualhuov[]; /* dual 4:3 screens below and above */
/* triple screen layouts */
extern const char layout_triphsxs[]; /* triple 4:3 screens side-by-side */
/* generic color overlay layouts */
extern const char layout_ho20ffff[]; /* horizontal 4:3 with 20,FF,FF color overlay */
extern const char layout_ho2eff2e[]; /* horizontal 4:3 with 2E,FF,2E color overlay */
extern const char layout_ho4f893d[]; /* horizontal 4:3 with 4F,89,3D color overlay */
extern const char layout_ho88ffff[]; /* horizontal 4:3 with 88,FF,FF color overlay */
extern const char layout_hoa0a0ff[]; /* horizontal 4:3 with A0,A0,FF color overlay */
extern const char layout_hoffe457[]; /* horizontal 4:3 with FF,E4,57 color overlay */
extern const char layout_hoffff20[]; /* horizontal 4:3 with FF,FF,20 color overlay */
extern const char layout_voffff20[]; /* vertical 4:3 with FF,FF,20 color overlay */
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
layout_view_has_art - true if a render_view contains
any non-screen elements
-------------------------------------------------*/
INLINE int layout_view_has_art(layout_view *view)
{
return (view->itemlist[ITEM_LAYER_BACKDROP] != 0 ||
view->itemlist[ITEM_LAYER_OVERLAY] != 0 ||
view->itemlist[ITEM_LAYER_BEZEL] != 0);
}
#endif /* __RENDLAY_H__ */
#endif // __RENDLAY_H__

View File

@ -23,8 +23,8 @@
/* utilities */
static void resample_argb_bitmap_average(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy);
static void resample_argb_bitmap_bilinear(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color *color, UINT32 dx, UINT32 dy);
static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha);
static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha);
static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha);
static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha);
@ -560,7 +560,7 @@ void render_line_to_quad(const render_bounds *bounds, float width, render_bounds
bitmap_t
-------------------------------------------------*/
bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha)
bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, bool *hasalpha)
{
bitmap_t *bitmap = NULL;
file_error filerr;
@ -636,7 +636,7 @@ bitmap_t *render_load_png(const char *path, const char *dirname, const char *fil
bitmap
-------------------------------------------------*/
static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha)
static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha)
{
UINT8 accumalpha = 0xff;
UINT8 *src;
@ -701,7 +701,7 @@ static void copy_png_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasal
to the alpha channel of a bitmap
-------------------------------------------------*/
static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, int *hasalpha)
static void copy_png_alpha_to_bitmap(bitmap_t *bitmap, const png_info *png, bool *hasalpha)
{
UINT8 accumalpha = 0xff;
UINT8 *src;

View File

@ -28,7 +28,7 @@ void render_resample_argb_bitmap_hq(void *dest, UINT32 drowpixels, UINT32 dwidth
int render_clip_line(render_bounds *bounds, const render_bounds *clip);
int render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords);
void render_line_to_quad(const render_bounds *bounds, float width, render_bounds *bounds0, render_bounds *bounds1);
bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha);
bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, bool *hasalpha);

View File

@ -312,7 +312,11 @@ void video_init(running_machine *machine)
if (global.snap_native)
{
global.snap_target = machine->render().target_alloc(layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN);
global.snap_target->set_layer_config(0);
global.snap_target->set_backdrops_enabled(false);
global.snap_target->set_overlays_enabled(false);
global.snap_target->set_bezels_enabled(false);
global.snap_target->set_screen_overlay_enabled(false);
global.snap_target->set_zoom_to_screen(false);
}
/* other targets select the specified view and turn off effects */
@ -1603,13 +1607,19 @@ int video_get_view_for_target(running_machine *machine, render_target *target, c
/* if we have enough targets to be one per screen, assign in order */
if (numtargets >= scrcount)
{
int index = target->index() % scrcount;
screen_device *screen;
for (screen = screen_first(*machine); screen != NULL; screen = screen_next(screen))
if (index-- == 0)
break;
/* find the first view with this screen and this screen only */
for (viewindex = 0; ; viewindex++)
{
UINT32 viewscreens = target->view_screens(viewindex);
if (viewscreens == (1 << targetindex))
const render_screen_list &viewscreens = target->view_screens(viewindex);
if (viewscreens.count() == 1 && viewscreens.contains(*screen))
break;
if (viewscreens == 0)
if (viewscreens.count() == 0)
{
viewindex = -1;
break;
@ -1622,11 +1632,18 @@ int video_get_view_for_target(running_machine *machine, render_target *target, c
{
for (viewindex = 0; ; viewindex++)
{
UINT32 viewscreens = target->view_screens(viewindex);
if (viewscreens == (1 << scrcount) - 1)
break;
if (viewscreens == 0)
const render_screen_list &viewscreens = target->view_screens(viewindex);
if (viewscreens.count() == 0)
break;
if (viewscreens.count() >= scrcount)
{
screen_device *screen;
for (screen = screen_first(*machine); screen != NULL; screen = screen_next(screen))
if (!viewscreens.contains(*screen))
break;
if (screen == NULL)
break;
}
}
}
}
@ -1942,9 +1959,6 @@ screen_device::~screen_device()
void screen_device::device_start()
{
// get and validate that the container for this screen exists
m_container = m_machine.render().container_for_screen(this);
// configure the default cliparea
render_container::user_settings settings;
m_container->get_user_settings(settings);

View File

@ -141,6 +141,7 @@ private:
class screen_device : public device_t
{
friend class screen_device_config;
friend class render_manager;
friend resource_pool_object<screen_device>::~resource_pool_object();
// construction/destruction
@ -199,6 +200,7 @@ private:
virtual void device_post_load();
// internal helpers
void set_container(render_container &container) { m_container = &container; }
void realloc_screen_bitmaps();
static TIMER_CALLBACK( static_vblank_begin_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_begin_callback(); }

View File

@ -42,6 +42,8 @@
#ifndef __WIN_VIDEO__
#define __WIN_VIDEO__
#include "render.h"
//============================================================
// CONSTANTS
@ -90,7 +92,7 @@ struct _win_video_config
int prescale; // prescale factor
int keepaspect; // keep aspect ratio
int numscreens; // number of screens
int layerconfig; // default configuration of layers
render_layer_config layerconfig; // default configuration of layers
// per-window configuration
win_window_config window[MAX_WINDOWS]; // configuration data per-window

View File

@ -718,7 +718,8 @@ static void winwindow_video_window_destroy(win_window_info *window)
void winwindow_video_window_update(win_window_info *window)
{
int targetview, targetorient, targetlayerconfig;
int targetview, targetorient;
render_layer_config targetlayerconfig;
assert(GetCurrentThreadId() == main_threadid);

View File

@ -100,7 +100,7 @@ struct _win_window_info
render_target * target;
int targetview;
int targetorient;
int targetlayerconfig;
render_layer_config targetlayerconfig;
render_primitive_list *primlist;
// input info