summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author therealmogminer@gmail.com <therealmogminer@gmail.com>2016-02-15 17:57:16 +0100
committer therealmogminer@gmail.com <therealmogminer@gmail.com>2016-02-15 17:57:28 +0100
commitb0a7bcd3468fa309d3761742be7f69c671d7a1fc (patch)
treebb75aac1faac0b980ddcf9d0de2599478cc504e4
parenta95323026cceddedb09eac64eedf8daef1dfd580 (diff)
Significant speed improvements to the BGFX renderer. [MooglyGuy]
-rw-r--r--scripts/src/osd/modules.lua1
-rw-r--r--src/emu/render.cpp21
-rw-r--r--src/emu/render.h10
-rw-r--r--src/emu/ui/menu.cpp36
-rw-r--r--src/osd/modules/render/binpacker.cpp195
-rw-r--r--src/osd/modules/render/binpacker.h183
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.cpp11
-rw-r--r--src/osd/modules/render/drawbgfx.cpp871
-rw-r--r--src/osd/modules/render/drawbgfx.h115
9 files changed, 1025 insertions, 418 deletions
diff --git a/scripts/src/osd/modules.lua b/scripts/src/osd/modules.lua
index 87e684a50f6..14d344fee09 100644
--- a/scripts/src/osd/modules.lua
+++ b/scripts/src/osd/modules.lua
@@ -104,6 +104,7 @@ function osdmodulesbuild()
if USE_BGFX == 1 then
files {
MAME_DIR .. "src/osd/modules/render/drawbgfx.cpp",
+ MAME_DIR .. "src/osd/modules/render/binpacker.cpp",
}
defines {
"USE_BGFX"
diff --git a/src/emu/render.cpp b/src/emu/render.cpp
index e25f62a8e13..cbcfd6b16b3 100644
--- a/src/emu/render.cpp
+++ b/src/emu/render.cpp
@@ -442,8 +442,10 @@ void render_texture::hq_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const
// get_scaled - get a scaled bitmap (if we can)
//-------------------------------------------------
-void render_texture::get_scaled(UINT32 dwidth, UINT32 dheight, render_texinfo &texinfo, render_primitive_list &primlist)
+void render_texture::get_scaled(UINT32 dwidth, UINT32 dheight, render_texinfo &texinfo, render_primitive_list &primlist, bool packable)
{
+ texinfo.hash = 0;
+
// source width/height come from the source bounds
int swidth = m_sbounds.width();
int sheight = m_sbounds.height();
@@ -520,6 +522,17 @@ void render_texture::get_scaled(UINT32 dwidth, UINT32 dheight, render_texinfo &t
// palette will be set later
texinfo.seqid = scaled->seqid;
}
+
+ UINT32 hash = 0;
+ if (packable)
+ {
+ //printf("Packable, %d, %d\n", texinfo.width, texinfo.height);
+ }
+ if (packable && texinfo.width <= 128 && texinfo.height <= 128)
+ {
+ hash = reinterpret_cast<UINT64>(texinfo.base) & 0xffffffff;
+ }
+ texinfo.hash = hash;
}
@@ -677,7 +690,7 @@ void render_container::add_char(float x0, float y0, float height, float aspect,
// add it like a quad
item &newitem = add_generic(CONTAINER_ITEM_QUAD, bounds.x0, bounds.y0, bounds.x1, bounds.y1, argb);
newitem.m_texture = texture;
- newitem.m_flags = PRIMFLAG_TEXORIENT(ROT0) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA);
+ newitem.m_flags = PRIMFLAG_TEXORIENT(ROT0) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE;
newitem.m_internal = INTERNAL_FLAG_CHAR;
}
@@ -1751,7 +1764,7 @@ void render_target::add_container_primitives(render_primitive_list &list, const
width = MIN(width, m_maxtexwidth);
height = MIN(height, m_maxtexheight);
- curitem->texture()->get_scaled(width, height, prim->texture, list);
+ curitem->texture()->get_scaled(width, height, prim->texture, list, (curitem->flags() & PRIMFLAG_PACKABLE) ? true : false);
// set the palette
prim->texture.palette = curitem->texture()->get_adjusted_palette(container);
@@ -1854,7 +1867,7 @@ void render_target::add_element_primitives(render_primitive_list &list, const ob
// get the scaled texture and append it
- texture->get_scaled(width, height, prim->texture, list);
+ texture->get_scaled(width, height, prim->texture, list, (prim->flags & PRIMFLAG_PACKABLE) ? true : false);
// compute the clip rect
render_bounds cliprect;
diff --git a/src/emu/render.h b/src/emu/render.h
index e40c86b1c3c..0fda591381a 100644
--- a/src/emu/render.h
+++ b/src/emu/render.h
@@ -62,7 +62,9 @@ enum
BLENDMODE_NONE = 0, // no blending
BLENDMODE_ALPHA, // standard alpha blend
BLENDMODE_RGB_MULTIPLY, // apply source alpha to source pix, then multiply RGB values
- BLENDMODE_ADD // apply source alpha to source pix, then add to destination
+ BLENDMODE_ADD, // apply source alpha to source pix, then add to destination
+
+ BLENDMODE_COUNT
};
@@ -105,6 +107,9 @@ const UINT32 PRIMFLAG_TYPE_MASK = 3 << PRIMFLAG_TYPE_SHIFT;
const UINT32 PRIMFLAG_TYPE_LINE = 0 << PRIMFLAG_TYPE_SHIFT;
const UINT32 PRIMFLAG_TYPE_QUAD = 1 << PRIMFLAG_TYPE_SHIFT;
+const int PRIMFLAG_PACKABLE_SHIFT = 1;
+const UINT32 PRIMFLAG_PACKABLE = 1 << PRIMFLAG_PACKABLE_SHIFT;
+
//**************************************************************************
// MACROS
//**************************************************************************
@@ -206,6 +211,7 @@ struct render_texinfo
UINT32 height; // height of the image
UINT32 seqid; // sequence ID
UINT64 osddata; // aux data to pass to osd
+ UINT32 hash; // hash (where applicable)
const rgb_t * palette; // palette for PALETTE16 textures, bcg lookup table for RGB32/YUY16
};
@@ -430,7 +436,7 @@ public:
private:
// internal helpers
- void get_scaled(UINT32 dwidth, UINT32 dheight, render_texinfo &texinfo, render_primitive_list &primlist);
+ void get_scaled(UINT32 dwidth, UINT32 dheight, render_texinfo &texinfo, render_primitive_list &primlist, bool packable = false);
const rgb_t *get_adjusted_palette(render_container &container);
static const int MAX_TEXTURE_SCALES = 16;
diff --git a/src/emu/ui/menu.cpp b/src/emu/ui/menu.cpp
index a06fb5e62ca..fbe7d46e541 100644
--- a/src/emu/ui/menu.cpp
+++ b/src/emu/ui/menu.cpp
@@ -59,12 +59,12 @@ static const ui_arts_info arts_info[] =
{ nullptr }
};
-static const char *hover_msg[] = {
- "Add or remove favorites",
- "Export displayed list to file",
- "Show DATs view",
- "Setup directories",
- "Configure options"
+static const char *hover_msg[] = {
+ "Add or remove favorites",
+ "Export displayed list to file",
+ "Show DATs view",
+ "Setup directories",
+ "Configure options"
};
/***************************************************************************
@@ -1258,7 +1258,7 @@ void ui_menu::render_triangle(bitmap_argb32 &dest, bitmap_argb32 &source, const
void ui_menu::highlight(render_container *container, float x0, float y0, float x1, float y1, rgb_t bgcolor)
{
- container->add_quad(x0, y0, x1, y1, bgcolor, hilight_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
+ container->add_quad(x0, y0, x1, y1, bgcolor, hilight_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE) | PRIMFLAG_PACKABLE);
}
@@ -1268,7 +1268,7 @@ void ui_menu::highlight(render_container *container, float x0, float y0, float x
void ui_menu::draw_arrow(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, UINT32 orientation)
{
- container->add_quad(x0, y0, x1, y1, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation));
+ container->add_quad(x0, y0, x1, y1, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation) | PRIMFLAG_PACKABLE);
}
//-------------------------------------------------
@@ -1350,7 +1350,7 @@ void ui_menu::init_ui(running_machine &machine)
toolbar_texture[x]->set_bitmap(*toolbar_bitmap[x], toolbar_bitmap[x]->cliprect(), TEXFORMAT_ARGB32);
else
toolbar_bitmap[x]->reset();
-
+
if (x == 0 || x == 2)
{
dst = &sw_toolbar_bitmap[x]->pix32(0);
@@ -1487,7 +1487,7 @@ void ui_menu::draw_select_game(bool noinput)
// if we have some background hilighting to do, add a quad behind everything else
if (bgcolor != UI_TEXT_BG_COLOR)
- mui.draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(255, 43, 43, 43),
+ mui.draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(255, 43, 43, 43),
hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
// if we're on the top line, display the up arrow
@@ -1531,7 +1531,7 @@ void ui_menu::draw_select_game(bool noinput)
space = mui.get_line_height() * container->manager().ui_aspect() * 1.5f;
}
- mui.draw_text_full(container, itemtext, effective_left + space, line_y, effective_width - space, JUSTIFY_LEFT, WRAP_TRUNCATE,
+ mui.draw_text_full(container, itemtext, effective_left + space, line_y, effective_width - space, JUSTIFY_LEFT, WRAP_TRUNCATE,
DRAW_NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr);
}
else
@@ -1591,7 +1591,7 @@ void ui_menu::draw_select_game(bool noinput)
container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height,
UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
else
- mui.draw_text_full(container, itemtext, effective_left, line, effective_width, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ mui.draw_text_full(container, itemtext, effective_left, line, effective_width, JUSTIFY_CENTER, WRAP_TRUNCATE,
DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr);
line += line_height;
}
@@ -2116,7 +2116,7 @@ void ui_menu::draw_star(float x0, float y0)
{
float y1 = y0 + machine().ui().get_line_height();
float x1 = x0 + machine().ui().get_line_height() * container->manager().ui_aspect();
- container->add_quad(x0, y0, x1, y1, ARGB_WHITE, star_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_quad(x0, y0, x1, y1, ARGB_WHITE, star_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE);
}
//-------------------------------------------------
@@ -2298,13 +2298,13 @@ void ui_menu::draw_common_arrow(float origx1, float origy1, float origx2, float
// apply arrow
if (current == dmin)
- container->add_quad(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90));
+ container->add_quad(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90) | PRIMFLAG_PACKABLE);
else if (current == dmax)
- container->add_quad(al_x0, al_y0, al_x1, al_y1, fgcolor_left, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X));
+ container->add_quad(al_x0, al_y0, al_x1, al_y1, fgcolor_left, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X) | PRIMFLAG_PACKABLE);
else
{
- container->add_quad(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90));
- container->add_quad(al_x0, al_y0, al_x1, al_y1, fgcolor_left, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X));
+ container->add_quad(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90) | PRIMFLAG_PACKABLE);
+ container->add_quad(al_x0, al_y0, al_x1, al_y1, fgcolor_left, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X) | PRIMFLAG_PACKABLE);
}
}
@@ -2409,7 +2409,7 @@ void ui_menu::draw_icon(int linenum, void *selectedref, float x0, float y0)
}
if (icons_bitmap[linenum]->valid())
- container->add_quad(x0, y0, x1, y1, ARGB_WHITE, icons_texture[linenum], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_quad(x0, y0, x1, y1, ARGB_WHITE, icons_texture[linenum], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE);
}
//-------------------------------------------------
diff --git a/src/osd/modules/render/binpacker.cpp b/src/osd/modules/render/binpacker.cpp
new file mode 100644
index 00000000000..2054dfa54cf
--- /dev/null
+++ b/src/osd/modules/render/binpacker.cpp
@@ -0,0 +1,195 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+//============================================================
+//
+// binpacker.cpp - Simple texture packer for dynamic atlasing
+//
+//============================================================
+
+#include "binpacker.h"
+#include <algorithm>
+
+bool rectangle_packer::pack(const std::vector<packable_rectangle>& rects, std::vector<std::vector<packed_rectangle>>& packs, int pack_size)
+{
+ clear();
+
+ m_pack_size = pack_size;
+
+ // Add rects to member array, and check to make sure none is too big
+ for (size_t rect = 0; rect < rects.size(); rect++)
+ {
+ m_rects.push_back(rectangle(0, 0, rects[rect].width(), rects[rect].height(), rects[rect].hash(), rects[rect].format(), rects[rect].rowpixels(), rects[rect].palette(), rects[rect].base()));
+ }
+
+ // Sort from greatest to least area
+ std::sort(m_rects.rbegin(), m_rects.rend());
+
+ // Pack
+ while (m_num_packed < (int)m_rects.size())
+ {
+ int i = m_packs.size();
+ m_packs.push_back(rectangle(m_pack_size));
+ m_roots.push_back(i);
+ if (!fill(i))
+ {
+ return false;
+ }
+ }
+
+ // Write out
+ packs.resize(m_roots.size());
+ for (size_t i = 0; i < m_roots.size(); ++i)
+ {
+ packs[i].clear();
+ add_pack_to_array(m_roots[i], packs[i]);
+ }
+
+ return true;
+}
+
+void rectangle_packer::clear()
+{
+ m_pack_size = 0;
+ m_num_packed = 0;
+ m_rects.clear();
+ m_packs.clear();
+ m_roots.clear();
+}
+
+bool rectangle_packer::fill(int pack)
+{
+ // For each rect
+ for (size_t rect = 0; rect < m_rects.size(); ++rect)
+ {
+ // If it's not already packed
+ if (!m_rects[rect].packed)
+ {
+ // If it fits in the current working area
+ if (fits(m_rects[rect], m_packs[pack]))
+ {
+ // Store in lower-left of working area, split, and recurse
+ m_num_packed++;
+ split(pack, rect);
+ fill(m_packs[pack].children[0]);
+ fill(m_packs[pack].children[1]);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void rectangle_packer::split(int pack, int rect)
+{
+ // Split the working area either horizontally or vertically with respect
+ // to the rect we're storing, such that we get the largest possible child
+ // area.
+
+ rectangle left = m_packs[pack];
+ rectangle right = m_packs[pack];
+ rectangle bottom = m_packs[pack];
+ rectangle top = m_packs[pack];
+
+ left.y += m_rects[rect].h;
+ left.w = m_rects[rect].w;
+ left.h -= m_rects[rect].h;
+
+ right.x += m_rects[rect].w;
+ right.w -= m_rects[rect].w;
+
+ bottom.x += m_rects[rect].w;
+ bottom.h = m_rects[rect].h;
+ bottom.w -= m_rects[rect].w;
+
+ top.y += m_rects[rect].h;
+ top.h -= m_rects[rect].h;
+
+ int max_lr_area = left.get_area();
+ if (right.get_area() > max_lr_area)
+ {
+ max_lr_area = right.get_area();
+ }
+
+ int max_bt_area = bottom.get_area();
+ if (top.get_area() > max_bt_area)
+ {
+ max_bt_area = top.get_area();
+ }
+
+ if (max_lr_area > max_bt_area)
+ {
+ if (left.get_area() > right.get_area())
+ {
+ m_packs.push_back(left);
+ m_packs.push_back(right);
+ }
+ else
+ {
+ m_packs.push_back(right);
+ m_packs.push_back(left);
+ }
+ }
+ else
+ {
+ if (bottom.get_area() > top.get_area())
+ {
+ m_packs.push_back(bottom);
+ m_packs.push_back(top);
+ }
+ else
+ {
+ m_packs.push_back(top);
+ m_packs.push_back(bottom);
+ }
+ }
+
+ // This pack area now represents the rect we've just stored, so save the
+ // relevant info to it, and assign children.
+ m_packs[pack].w = m_rects[rect].w;
+ m_packs[pack].h = m_rects[rect].h;
+ m_packs[pack].hash = m_rects[rect].hash;
+ m_packs[pack].format = m_rects[rect].format;
+ m_packs[pack].rowpixels = m_rects[rect].rowpixels;
+ m_packs[pack].palette = m_rects[rect].palette;
+ m_packs[pack].base = m_rects[rect].base;
+ m_packs[pack].children[0] = m_packs.size() - 2;
+ m_packs[pack].children[1] = m_packs.size() - 1;
+
+ // Done with the rect
+ m_rects[rect].packed = true;
+
+}
+
+bool rectangle_packer::fits(rectangle& rect1, const rectangle& rect2)
+{
+ // Check to see if rect1 fits in rect2
+
+ if (rect1.w <= rect2.w && rect1.h <= rect2.h)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void rectangle_packer::add_pack_to_array(int pack, std::vector<packed_rectangle>& array) const
+{
+ if (m_packs[pack].hash != 0)
+ {
+ array.push_back(packed_rectangle(m_packs[pack].hash, m_packs[pack].format,
+ m_packs[pack].w, m_packs[pack].h, m_packs[pack].x, m_packs[pack].y,
+ m_packs[pack].rowpixels, m_packs[pack].palette, m_packs[pack].base));
+
+ if (m_packs[pack].children[0] != -1)
+ {
+ add_pack_to_array(m_packs[pack].children[0], array);
+ }
+
+ if (m_packs[pack].children[1] != -1)
+ {
+ add_pack_to_array(m_packs[pack].children[1], array);
+ }
+ }
+}
diff --git a/src/osd/modules/render/binpacker.h b/src/osd/modules/render/binpacker.h
new file mode 100644
index 00000000000..677083b5c09
--- /dev/null
+++ b/src/osd/modules/render/binpacker.h
@@ -0,0 +1,183 @@
+#pragma once
+
+#ifndef __RECTPACKER_H__
+#define __RECTPACKER_H__
+
+#include "emu.h"
+
+#include <vector>
+
+class rectangle_packer
+{
+public:
+ // The input and output are in terms of vectors of ints to avoid
+ // dependencies (although I suppose a public member struct could have been
+ // used). The parameters are:
+
+ // packs : After packing, the outer array contains the packs (therefore
+ // the number of packs is packs.size()). Each inner array contains a
+ // sequence of sets of 3 ints. Each set represents a rectangle in the
+ // pack. The elements in the set are 1) the rect ID, 2) the x position
+ // of the rect with respect to the pack, and 3) the y position of the rect
+ // with respect to the pack. The widths and heights of the rects are not
+ // included, as it's assumed they are stored on the caller's side (they
+ // were after all the input to the function).
+
+ class packable_rectangle
+ {
+ public:
+ packable_rectangle() : m_hash(0), m_width(-1), m_height(-1) { }
+ packable_rectangle(UINT32 hash, UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base)
+ : m_hash(hash)
+ , m_format(format)
+ , m_width(width)
+ , m_height(height)
+ , m_rowpixels(rowpixels)
+ , m_palette(palette)
+ , m_base(base)
+ {
+ }
+
+ UINT32 hash() const { return m_hash; }
+ UINT32 format() const { return m_format; }
+ int width() const { return m_width; }
+ int height() const { return m_height; }
+ int rowpixels() const { return m_rowpixels; }
+ const rgb_t* palette() const { return m_palette; }
+ void* base() const { return m_base; }
+
+ private:
+ UINT32 m_hash;
+ UINT32 m_format;
+ int m_width;
+ int m_height;
+ int m_rowpixels;
+ const rgb_t* m_palette;
+ void* m_base;
+ };
+
+ class packed_rectangle
+ {
+ public:
+ packed_rectangle() : m_hash(0), m_format(0), m_width(-1), m_height(-1), m_x(-1), m_y(-1), m_rowpixels(0), m_palette(nullptr), m_base(nullptr) { }
+ packed_rectangle(const packed_rectangle& rect)
+ : m_hash(rect.m_hash)
+ , m_format(rect.m_format)
+ , m_width(rect.m_width)
+ , m_height(rect.m_height)
+ , m_x(rect.m_x)
+ , m_y(rect.m_y)
+ , m_rowpixels(rect.m_rowpixels)
+ , m_palette(rect.m_palette)
+ , m_base(rect.m_base)
+ {
+ }
+ packed_rectangle(UINT32 hash, UINT32 format, int width, int height, int x, int y, int rowpixels, const rgb_t *palette, void *base)
+ : m_hash(hash)
+ , m_format(format)
+ , m_width(width)
+ , m_height(height)
+ , m_x(x)
+ , m_y(y)
+ , m_rowpixels(rowpixels)
+ , m_palette(palette)
+ , m_base(base)
+ {
+ }
+
+ UINT32 hash() const { return m_hash; }
+ UINT32 format() const { return m_format; }
+ int width() const { return m_width; }
+ int height() const { return m_height; }
+ int x() const { return m_x; }
+ int y() const { return m_y; }
+ int rowpixels() const { return m_rowpixels; }
+ const rgb_t* palette() const { return m_palette; }
+ void* base() const { return m_base; }
+
+ private:
+ UINT32 m_hash;
+ UINT32 m_format;
+ int m_width;
+ int m_height;
+ int m_x;
+ int m_y;
+ int m_rowpixels;
+ const rgb_t* m_palette;
+ void* m_base;
+ };
+
+ bool pack(const std::vector<packable_rectangle>& rects, std::vector<std::vector<packed_rectangle>>& packs, int pack_size);
+
+private:
+ struct rectangle
+ {
+ rectangle(int size)
+ : x(0)
+ , y(0)
+ , w(size)
+ , h(size)
+ , hash(-1)
+ , format(0)
+ , rowpixels(0)
+ , palette(nullptr)
+ , base(nullptr)
+ , packed(false)
+ {
+ children[0] = -1;
+ children[1] = -1;
+ }
+
+ rectangle(int x, int y, int w, int h, int hash, UINT32 format, int rowpixels, const rgb_t *palette, void *base)
+ : x(x)
+ , y(y)
+ , w(w)
+ , h(h)
+ , hash(hash)
+ , format(format)
+ , rowpixels(rowpixels)
+ , palette(palette)
+ , base(base)
+ , packed(false)
+ {
+ children[0] = -1;
+ children[1] = -1;
+ }
+
+ int get_area() const
+ {
+ return w * h;
+ }
+
+ bool operator<(const rectangle& rect) const
+ {
+ return get_area() < rect.get_area();
+ }
+
+ int x;
+ int y;
+ int w;
+ int h;
+ int hash;
+ UINT32 format;
+ int rowpixels;
+ const rgb_t* palette;
+ void* base;
+ int children[2];
+ bool packed;
+ };
+
+ void clear();
+ bool fill(int pack);
+ void split(int pack, int rect);
+ bool fits(rectangle& rect1, const rectangle& rect2);
+ void add_pack_to_array(int pack, std::vector<packed_rectangle>& array) const;
+
+ int m_pack_size;
+ int m_num_packed;
+ std::vector<rectangle> m_rects;
+ std::vector<rectangle> m_packs;
+ std::vector<int> m_roots;
+};
+
+#endif // __RECTPACKER_H__ \ No newline at end of file
diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp
index 43d6ec9bc48..4cc53f2e41d 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.cpp
+++ b/src/osd/modules/render/d3d/d3dhlsl.cpp
@@ -1416,14 +1416,9 @@ int shaders::post_pass(render_target *rt, int source_index, poly_info *poly, int
float screen_scale[2] = { xscale, yscale };
float screen_offset[2] = { xoffset, yoffset };
- rgb_t back_color_rgb = !machine->first_screen()->has_palette()
- ? rgb_t(0, 0, 0)
- : machine->first_screen()->palette().palette()->entry_color(0);
+ rgb_t back_color_rgb = !machine->first_screen()->has_palette() ? rgb_t(0, 0, 0) : machine->first_screen()->palette().palette()->entry_color(0);
back_color_rgb = apply_color_convolution(back_color_rgb);
- float back_color[3] = {
- static_cast<float>(back_color_rgb.r()) / 255.0f,
- static_cast<float>(back_color_rgb.g()) / 255.0f,
- static_cast<float>(back_color_rgb.b()) / 255.0f };
+ float back_color[3] = { static_cast<float>(back_color_rgb.r()) / 255.0f, static_cast<float>(back_color_rgb.g()) / 255.0f, static_cast<float>(back_color_rgb.b()) / 255.0f };
curr_effect = post_effect;
curr_effect->update_uniforms();
@@ -1463,9 +1458,9 @@ int shaders::downsample_pass(render_target *rt, int source_index, poly_info *pol
curr_effect->set_bool("PrepareVector", prepare_vector);
int bloom_index = 0;
- float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height();
float bloom_width = prepare_vector ? rt->target_width : rt->target_width / hlsl_prescale_x;
float bloom_height = prepare_vector ? rt->target_height : rt->target_height / hlsl_prescale_y;
+ float bloom_size = (bloom_width < bloom_height) ? bloom_width : bloom_height;
for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f)
{
bloom_dims[bloom_index][0] = (float)(int)bloom_width;
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index 35a50609cf4..707360053aa 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
-// copyright-holders:Miodrag Milanovic,Dario Manesku,Branimir Karadzic,Aaron Giles
+// copyright-holders:Miodrag Milanovic,Ryan Holtz,Dario Manesku,Branimir Karadzic,Aaron Giles
//============================================================
//
-// drawbgfx.c - BGFX drawer
+// drawbgfx.cpp - BGFX renderer
//
//============================================================
#define __STDC_LIMIT_MACROS
@@ -32,6 +32,9 @@
#include <bgfx/bgfx.h>
#include <bx/fpumath.h>
#include <bx/readerwriter.h>
+#include <algorithm>
+
+#include "drawbgfx.h"
//============================================================
// DEBUGGING
@@ -55,42 +58,6 @@
//============================================================
-/* sdl_info is the information about SDL for the current screen */
-class renderer_bgfx : public osd_renderer
-{
-public:
- renderer_bgfx(osd_window *w)
- : osd_renderer(w, FLAG_NONE),
- m_dimensions(0,0)
- {}
-
- virtual int create() override;
- virtual int draw(const int update) override;
-#ifdef OSD_SDL
- virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
-#else
- virtual void save() override { }
- virtual void record() override { }
- virtual void toggle_fsfx() override { }
-#endif
- virtual void destroy() override;
- virtual render_primitive_list *get_primitives() override
- {
- osd_dim wdim = window().get_size();
- window().target()->set_bounds(wdim.width(), wdim.height(), window().aspect());
- return &window().target()->get_primitives();
- }
-
- bgfx::ProgramHandle m_progQuad;
- bgfx::ProgramHandle m_progQuadTexture;
- bgfx::ProgramHandle m_progLine;
- bgfx::UniformHandle m_s_texColor;
- bgfx::FrameBufferHandle fbh;
- // Original display_mode
- osd_dim m_dimensions;
-};
-
-
//============================================================
// PROTOTYPES
//============================================================
@@ -144,7 +111,7 @@ static void* sdlNativeWindowHandle(SDL_Window* _window)
SDL_VERSION(&wmi.version);
if (!SDL_GetWindowWMInfo(_window, &wmi))
{
- return NULL;
+ return nullptr;
}
# if BX_PLATFORM_LINUX || BX_PLATFORM_BSD
@@ -175,7 +142,8 @@ int renderer_bgfx::create()
bgfx::setDebug(BGFX_DEBUG_TEXT); //BGFX_DEBUG_STATS
m_dimensions = osd_dim(wdim.width(), wdim.height());
}
- else {
+ else
+ {
#ifdef OSD_WINDOWS
fbh = bgfx::createFrameBuffer(window().m_hwnd, wdim.width(), wdim.height());
#else
@@ -183,12 +151,18 @@ int renderer_bgfx::create()
#endif
bgfx::touch(window().m_index);
}
+
+ PosColorTexCoord0Vertex::init();
+ PosColorVertex::init();
+
// Create program from shaders.
m_progQuad = loadProgram("vs_quad", "fs_quad");
m_progQuadTexture = loadProgram("vs_quad_texture", "fs_quad_texture");
- m_progLine = loadProgram("vs_line", "fs_line");
m_s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
+ uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_ANISOTROPIC | BGFX_TEXTURE_MAG_ANISOTROPIC;
+ m_texture_cache = bgfx::createTexture2D(CACHE_SIZE, CACHE_SIZE, 1, bgfx::TextureFormat::BGRA8, flags);
+
return 0;
}
@@ -198,7 +172,7 @@ int renderer_bgfx::create()
void renderer_bgfx::destroy()
{
- if (window().m_index > 0)
+ if (window().m_index > 0)
{
bgfx::destroyFrameBuffer(fbh);
}
@@ -206,7 +180,6 @@ void renderer_bgfx::destroy()
// Cleanup.
bgfx::destroyProgram(m_progQuad);
bgfx::destroyProgram(m_progQuadTexture);
- bgfx::destroyProgram(m_progLine);
}
@@ -239,7 +212,7 @@ static const bgfx::Memory* loadMem(bx::FileReaderI* _reader, const char* _filePa
return mem;
}
- return NULL;
+ return nullptr;
}
static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader, const char* _name)
{
@@ -277,11 +250,11 @@ static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader, const char* _name
return bgfx::createShader(loadMem(_reader, filePath));
}
-bgfx::ProgramHandle loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName)
+bgfx::ProgramHandle renderer_bgfx::loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName)
{
bgfx::ShaderHandle vsh = loadShader(_reader, _vsName);
bgfx::ShaderHandle fsh = BGFX_INVALID_HANDLE;
- if (NULL != _fsName)
+ if (nullptr != _fsName)
{
fsh = loadShader(_reader, _fsName);
}
@@ -290,44 +263,70 @@ bgfx::ProgramHandle loadProgram(bx::FileReaderI* _reader, const char* _vsName, c
}
static auto s_fileReader = new bx::CrtFileReader;
-bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName)
+bgfx::ProgramHandle renderer_bgfx::loadProgram(const char* _vsName, const char* _fsName)
{
-
return loadProgram(s_fileReader, _vsName, _fsName);
}
+
//============================================================
// drawbgfx_window_draw
//============================================================
-struct PosColorTexCoord0Vertex
+bgfx::VertexDecl renderer_bgfx::PosColorTexCoord0Vertex::ms_decl;
+
+void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, PosColorTexCoord0Vertex* vertex)
{
- float m_x;
- float m_y;
- float m_z;
- uint32_t m_rgba;
- float m_u;
- float m_v;
-
- static void init()
- {
- ms_decl.begin()
- .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
- .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
- .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
- .end();
- }
-
- static bgfx::VertexDecl ms_decl;
-};
-bgfx::VertexDecl PosColorTexCoord0Vertex::ms_decl;
-
-void screenQuad(float _x1
- , float _y1
- , float _x2
- , float _y2
- , uint32_t _abgr
- , render_quad_texuv uv
- )
+ rectangle_packer::packed_rectangle& rect = m_hash_to_entry[hash];
+ float u0 = float(rect.x()) / float(CACHE_SIZE);
+ float v0 = float(rect.y()) / float(CACHE_SIZE);
+ float u1 = u0 + float(rect.width()) / float(CACHE_SIZE);
+ float v1 = v0 + float(rect.height()) / float(CACHE_SIZE);
+ UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
+
+ vertex[0].m_x = prim->bounds.x0;
+ vertex[0].m_y = prim->bounds.y0;
+ vertex[0].m_z = 0;
+ vertex[0].m_rgba = rgba;
+ vertex[0].m_u = u0;
+ vertex[0].m_v = v0;
+
+ vertex[1].m_x = prim->bounds.x1;
+ vertex[1].m_y = prim->bounds.y0;
+ vertex[1].m_z = 0;
+ vertex[1].m_rgba = rgba;
+ vertex[1].m_u = u1;
+ vertex[1].m_v = v0;
+
+ vertex[2].m_x = prim->bounds.x1;
+ vertex[2].m_y = prim->bounds.y1;
+ vertex[2].m_z = 0;
+ vertex[2].m_rgba = rgba;
+ vertex[2].m_u = u1;
+ vertex[2].m_v = v1;
+
+ vertex[3].m_x = prim->bounds.x1;
+ vertex[3].m_y = prim->bounds.y1;
+ vertex[3].m_z = 0;
+ vertex[3].m_rgba = rgba;
+ vertex[3].m_u = u1;
+ vertex[3].m_v = v1;
+
+ vertex[4].m_x = prim->bounds.x0;
+ vertex[4].m_y = prim->bounds.y1;
+ vertex[4].m_z = 0;
+ vertex[4].m_rgba = rgba;
+ vertex[4].m_u = u0;
+ vertex[4].m_v = v1;
+
+ vertex[5].m_x = prim->bounds.x0;
+ vertex[5].m_y = prim->bounds.y0;
+ vertex[5].m_z = 0;
+ vertex[5].m_rgba = rgba;
+ vertex[5].m_u = u0;
+ vertex[5].m_v = v0;
+}
+
+void renderer_bgfx::render_textured_quad(int view, render_primitive* prim)
{
if (bgfx::checkAvailTransientVertexBuffer(6, PosColorTexCoord0Vertex::ms_decl))
{
@@ -335,90 +334,86 @@ void screenQuad(float _x1
bgfx::allocTransientVertexBuffer(&vb, 6, PosColorTexCoord0Vertex::ms_decl);
PosColorTexCoord0Vertex* vertex = (PosColorTexCoord0Vertex*)vb.data;
- const float minx = _x1;
- const float miny = _y1;
- const float maxx = _x2;
- const float maxy = _y2;
- const float zz = 0.0f;
-
- vertex[0].m_x = minx;
- vertex[0].m_y = miny;
- vertex[0].m_z = zz;
- vertex[0].m_rgba = _abgr;
- vertex[0].m_u = uv.tl.u;
- vertex[0].m_v = uv.tl.v;
-
- vertex[1].m_x = maxx;
- vertex[1].m_y = miny;
- vertex[1].m_z = zz;
- vertex[1].m_rgba = _abgr;
- vertex[1].m_u = uv.tr.u;
- vertex[1].m_v = uv.tr.v;
-
- vertex[2].m_x = maxx;
- vertex[2].m_y = maxy;
- vertex[2].m_z = zz;
- vertex[2].m_rgba = _abgr;
- vertex[2].m_u = uv.br.u;
- vertex[2].m_v = uv.br.v;
-
- vertex[3].m_x = maxx;
- vertex[3].m_y = maxy;
- vertex[3].m_z = zz;
- vertex[3].m_rgba = _abgr;
- vertex[3].m_u = uv.br.u;
- vertex[3].m_v = uv.br.v;
-
- vertex[4].m_x = minx;
- vertex[4].m_y = maxy;
- vertex[4].m_z = zz;
- vertex[4].m_rgba = _abgr;
- vertex[4].m_u = uv.bl.u;
- vertex[4].m_v = uv.bl.v;
-
- vertex[5].m_x = minx;
- vertex[5].m_y = miny;
- vertex[5].m_z = zz;
- vertex[5].m_rgba = _abgr;
- vertex[5].m_u = uv.tl.u;
- vertex[5].m_v = uv.tl.v;
+ UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
+
+ vertex[0].m_x = prim->bounds.x0;
+ vertex[0].m_y = prim->bounds.y0;
+ vertex[0].m_z = 0;
+ vertex[0].m_rgba = rgba;
+ vertex[0].m_u = prim->texcoords.tl.u;
+ vertex[0].m_v = prim->texcoords.tl.v;
+
+ vertex[1].m_x = prim->bounds.x1;
+ vertex[1].m_y = prim->bounds.y0;
+ vertex[1].m_z = 0;
+ vertex[1].m_rgba = rgba;
+ vertex[1].m_u = prim->texcoords.tr.u;
+ vertex[1].m_v = prim->texcoords.tr.v;
+
+ vertex[2].m_x = prim->bounds.x1;
+ vertex[2].m_y = prim->bounds.y1;
+ vertex[2].m_z = 0;
+ vertex[2].m_rgba = rgba;
+ vertex[2].m_u = prim->texcoords.br.u;
+ vertex[2].m_v = prim->texcoords.br.v;
+
+ vertex[3].m_x = prim->bounds.x1;
+ vertex[3].m_y = prim->bounds.y1;
+ vertex[3].m_z = 0;
+ vertex[3].m_rgba = rgba;
+ vertex[3].m_u = prim->texcoords.br.u;
+ vertex[3].m_v = prim->texcoords.br.v;
+
+ vertex[4].m_x = prim->bounds.x0;
+ vertex[4].m_y = prim->bounds.y1;
+ vertex[4].m_z = 0;
+ vertex[4].m_rgba = rgba;
+ vertex[4].m_u = prim->texcoords.bl.u;
+ vertex[4].m_v = prim->texcoords.bl.v;
+
+ vertex[5].m_x = prim->bounds.x0;
+ vertex[5].m_y = prim->bounds.y0;
+ vertex[5].m_z = 0;
+ vertex[5].m_rgba = rgba;
+ vertex[5].m_u = prim->texcoords.tl.u;
+ vertex[5].m_v = prim->texcoords.tl.v;
bgfx::setVertexBuffer(&vb);
- }
-}
+ uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP;
+ if (video_config.filter == 0)
+ {
+ texture_flags |= BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT;
+ }
+
+ const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(prim->flags & PRIMFLAG_TEXFORMAT_MASK,
+ prim->texture.width, prim->texture.height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base);
-struct PosColorVertex
-{
- float m_x;
- float m_y;
- uint32_t m_abgr;
+ bgfx::TextureHandle texture = bgfx::createTexture2D((uint16_t)prim->texture.width, (uint16_t)prim->texture.height, 1, bgfx::TextureFormat::BGRA8, texture_flags, mem);
- static void init()
- {
- ms_decl
- .begin()
- .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
- .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
- .end();
+ bgfx::setTexture(0, m_s_texColor, texture);
+
+ set_bgfx_state(PRIMFLAG_GET_BLENDMODE(prim->flags));
+ bgfx::submit(view, m_progQuadTexture);
+
+ bgfx::destroyTexture(texture);
}
+}
- static bgfx::VertexDecl ms_decl;
-};
-bgfx::VertexDecl PosColorVertex::ms_decl;
+bgfx::VertexDecl renderer_bgfx::PosColorVertex::ms_decl;
#define MAX_TEMP_COORDS 100
-void drawPolygon(const float* _coords, uint32_t _numCoords, float _r, uint32_t _abgr)
+void renderer_bgfx::put_polygon(const float* coords, UINT32 num_coords, float r, UINT32 rgba, PosColorVertex* vertex)
{
- float tempCoords[MAX_TEMP_COORDS * 2];
+ float tempCoords[MAX_TEMP_COORDS * 3];
float tempNormals[MAX_TEMP_COORDS * 2];
- _numCoords = _numCoords < MAX_TEMP_COORDS ? _numCoords : MAX_TEMP_COORDS;
+ num_coords = num_coords < MAX_TEMP_COORDS ? num_coords : MAX_TEMP_COORDS;
- for (uint32_t ii = 0, jj = _numCoords - 1; ii < _numCoords; jj = ii++)
+ for (uint32_t ii = 0, jj = num_coords - 1; ii < num_coords; jj = ii++)
{
- const float* v0 = &_coords[jj * 2];
- const float* v1 = &_coords[ii * 2];
+ const float* v0 = &coords[jj * 3];
+ const float* v1 = &coords[ii * 3];
float dx = v1[0] - v0[0];
float dy = v1[1] - v0[1];
float d = sqrtf(dx * dx + dy * dy);
@@ -433,7 +428,7 @@ void drawPolygon(const float* _coords, uint32_t _numCoords, float _r, uint32_t _
tempNormals[jj * 2 + 1] = -dx;
}
- for (uint32_t ii = 0, jj = _numCoords - 1; ii < _numCoords; jj = ii++)
+ for (uint32_t ii = 0, jj = num_coords - 1; ii < num_coords; jj = ii++)
{
float dlx0 = tempNormals[jj * 2 + 0];
float dly0 = tempNormals[jj * 2 + 1];
@@ -454,77 +449,78 @@ void drawPolygon(const float* _coords, uint32_t _numCoords, float _r, uint32_t _
dmy *= scale;
}
- tempCoords[ii * 2 + 0] = _coords[ii * 2 + 0] + dmx * _r;
- tempCoords[ii * 2 + 1] = _coords[ii * 2 + 1] + dmy * _r;
+ tempCoords[ii * 3 + 0] = coords[ii * 3 + 0] + dmx * r;
+ tempCoords[ii * 3 + 1] = coords[ii * 3 + 1] + dmy * r;
+ tempCoords[ii * 3 + 2] = coords[ii * 3 + 2];
}
- uint32_t numVertices = _numCoords * 6 + (_numCoords - 2) * 3;
- if (bgfx::checkAvailTransientVertexBuffer(numVertices, PosColorVertex::ms_decl))
+ int vertIndex = 0;
+ UINT32 trans = rgba & 0x00ffffff;
+ for (uint32_t ii = 0, jj = num_coords - 1; ii < num_coords; jj = ii++)
{
- bgfx::TransientVertexBuffer tvb;
- bgfx::allocTransientVertexBuffer(&tvb, numVertices, PosColorVertex::ms_decl);
- uint32_t trans = _abgr & 0xffffff;
-
- PosColorVertex* vertex = (PosColorVertex*)tvb.data;
- for (uint32_t ii = 0, jj = _numCoords - 1; ii < _numCoords; jj = ii++)
- {
- vertex->m_x = _coords[ii * 2 + 0];
- vertex->m_y = _coords[ii * 2 + 1];
- vertex->m_abgr = _abgr;
- ++vertex;
-
- vertex->m_x = _coords[jj * 2 + 0];
- vertex->m_y = _coords[jj * 2 + 1];
- vertex->m_abgr = _abgr;
- ++vertex;
-
- vertex->m_x = tempCoords[jj * 2 + 0];
- vertex->m_y = tempCoords[jj * 2 + 1];
- vertex->m_abgr = trans;
- ++vertex;
-
- vertex->m_x = tempCoords[jj * 2 + 0];
- vertex->m_y = tempCoords[jj * 2 + 1];
- vertex->m_abgr = trans;
- ++vertex;
-
- vertex->m_x = tempCoords[ii * 2 + 0];
- vertex->m_y = tempCoords[ii * 2 + 1];
- vertex->m_abgr = trans;
- ++vertex;
-
- vertex->m_x = _coords[ii * 2 + 0];
- vertex->m_y = _coords[ii * 2 + 1];
- vertex->m_abgr = _abgr;
- ++vertex;
- }
-
- for (uint32_t ii = 2; ii < _numCoords; ++ii)
- {
- vertex->m_x = _coords[0];
- vertex->m_y = _coords[1];
- vertex->m_abgr = _abgr;
- ++vertex;
-
- vertex->m_x = _coords[(ii - 1) * 2 + 0];
- vertex->m_y = _coords[(ii - 1) * 2 + 1];
- vertex->m_abgr = _abgr;
- ++vertex;
-
- vertex->m_x = _coords[ii * 2 + 0];
- vertex->m_y = _coords[ii * 2 + 1];
- vertex->m_abgr = _abgr;
- ++vertex;
- }
+ vertex[vertIndex].m_x = coords[ii * 3 + 0];
+ vertex[vertIndex].m_y = coords[ii * 3 + 1];
+ vertex[vertIndex].m_z = coords[ii * 3 + 2];
+ vertex[vertIndex].m_rgba = rgba;
+ vertIndex++;
+
+ vertex[vertIndex].m_x = coords[jj * 3 + 0];
+ vertex[vertIndex].m_y = coords[jj * 3 + 1];
+ vertex[vertIndex].m_z = coords[jj * 3 + 2];
+ vertex[vertIndex].m_rgba = rgba;
+ vertIndex++;
+
+ vertex[vertIndex].m_x = tempCoords[jj * 3 + 0];
+ vertex[vertIndex].m_y = tempCoords[jj * 3 + 1];
+ vertex[vertIndex].m_z = tempCoords[jj * 3 + 2];
+ vertex[vertIndex].m_rgba = trans;
+ vertIndex++;
+
+ vertex[vertIndex].m_x = tempCoords[jj * 3 + 0];
+ vertex[vertIndex].m_y = tempCoords[jj * 3 + 1];
+ vertex[vertIndex].m_z = tempCoords[jj * 3 + 2];
+ vertex[vertIndex].m_rgba = trans;
+ vertIndex++;
+
+ vertex[vertIndex].m_x = tempCoords[ii * 3 + 0];
+ vertex[vertIndex].m_y = tempCoords[ii * 3 + 1];
+ vertex[vertIndex].m_z = tempCoords[ii * 3 + 2];
+ vertex[vertIndex].m_rgba = trans;
+ vertIndex++;
+
+ vertex[vertIndex].m_x = coords[ii * 3 + 0];
+ vertex[vertIndex].m_y = coords[ii * 3 + 1];
+ vertex[vertIndex].m_z = coords[ii * 3 + 2];
+ vertex[vertIndex].m_rgba = rgba;
+ vertIndex++;
+ }
- bgfx::setVertexBuffer(&tvb);
+ for (uint32_t ii = 2; ii < num_coords; ++ii)
+ {
+ vertex[vertIndex].m_x = coords[0];
+ vertex[vertIndex].m_y = coords[1];
+ vertex[vertIndex].m_z = coords[2];
+ vertex[vertIndex].m_rgba = rgba;
+ vertIndex++;
+
+ vertex[vertIndex].m_x = coords[(ii - 1) * 3 + 0];
+ vertex[vertIndex].m_y = coords[(ii - 1) * 3 + 1];
+ vertex[vertIndex].m_z = coords[(ii - 1) * 3 + 2];
+ vertex[vertIndex].m_rgba = rgba;
+ vertIndex++;
+
+ vertex[vertIndex].m_x = coords[ii * 3 + 0];
+ vertex[vertIndex].m_y = coords[ii * 3 + 1];
+ vertex[vertIndex].m_z = coords[ii * 3 + 2];
+ vertex[vertIndex].m_rgba = rgba;
+ vertIndex++;
}
}
-void drawLine(float _x0, float _y0, float _x1, float _y1, float _r, uint32_t _abgr, float _fth = 1.0f)
+void renderer_bgfx::put_line(float x0, float y0, float x1, float y1, float r, UINT32 rgba, PosColorVertex* vertex, float fth)
{
- float dx = _x1 - _x0;
- float dy = _y1 - _y0;
+ float dx = x1 - x0;
+ float dy = y1 - y0;
float d = sqrtf(dx * dx + dy * dy);
if (d > 0.0001f)
{
@@ -535,49 +531,41 @@ void drawLine(float _x0, float _y0, float _x1, float _y1, float _r, uint32_t _ab
float nx = dy;
float ny = -dx;
- float verts[4 * 2];
- _r -= _fth;
- _r *= 0.5f;
- if (_r < 0.01f)
+ float verts[4 * 3];
+ r -= fth;
+ r *= 0.5f;
+ if (r < 0.01f)
{
- _r = 0.01f;
+ r = 0.01f;
}
- dx *= _r;
- dy *= _r;
- nx *= _r;
- ny *= _r;
+ dx *= r;
+ dy *= r;
+ nx *= r;
+ ny *= r;
- verts[0] = _x0 - dx - nx;
- verts[1] = _y0 - dy - ny;
+ verts[0] = x0 - dx - nx;
+ verts[1] = y0 - dy - ny;
+ verts[2] = 0;
- verts[2] = _x0 - dx + nx;
- verts[3] = _y0 - dy + ny;
+ verts[3] = x0 - dx + nx;
+ verts[4] = y0 - dy + ny;
+ verts[5] = 0;
- verts[4] = _x1 + dx + nx;
- verts[5] = _y1 + dy + ny;
+ verts[6] = x1 + dx + nx;
+ verts[7] = y1 + dy + ny;
+ verts[8] = 0;
- verts[6] = _x1 + dx - nx;
- verts[7] = _y1 + dy - ny;
+ verts[9] = x1 + dx - nx;
+ verts[10] = y1 + dy - ny;
+ verts[11] = 0;
- drawPolygon(verts, 4, _fth, _abgr);
+ put_polygon(verts, 4, fth, rgba, vertex);
}
-void initVertexDecls()
+uint32_t renderer_bgfx::u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a = 255)
{
- PosColorTexCoord0Vertex::init();
- PosColorVertex::init();
-}
-
-static inline
-uint32_t u32Color(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a = 255)
-{
- return 0
- | (uint32_t(_r) << 0)
- | (uint32_t(_g) << 8)
- | (uint32_t(_b) << 16)
- | (uint32_t(_a) << 24)
- ;
+ return (a << 24) | (b << 16) | (g << 8) | r;
}
//============================================================
@@ -609,9 +597,9 @@ static inline void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width
static inline void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, const rgb_t *palette)
{
int x;
-
+
// palette (really RGB map) case
- if (palette != NULL)
+ if (palette != nullptr)
{
for (x = 0; x < width; x++)
{
@@ -637,7 +625,7 @@ static inline void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, co
{
int x;
// palette (really RGB map) case
- if (palette != NULL)
+ if (palette != nullptr)
{
for (x = 0; x < width; x++)
{
@@ -706,7 +694,7 @@ static inline void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int wi
assert(width % 2 == 0);
// palette (really RGB map) case
- if (palette != NULL)
+ if (palette != nullptr)
{
for (x = 0; x < width / 2; x++)
{
@@ -737,9 +725,38 @@ static inline void copyline_yuy16_to_argb(UINT32 *dst, const UINT16 *src, int wi
}
}
}
+
+const bgfx::Memory* renderer_bgfx::mame_texture_data_to_bgfx_texture_data(UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base)
+{
+ const bgfx::Memory* mem = bgfx::alloc(width * height * 4);
+ for (int y = 0; y < height; y++)
+ {
+ switch (format)
+ {
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16):
+ copyline_palette16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette);
+ break;
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTEA16):
+ copyline_palettea16((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette);
+ break;
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16):
+ copyline_yuy16_to_argb((UINT32*)mem->data + y * width, (UINT16*)base + y * rowpixels, width, palette, 1);
+ break;
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32):
+ copyline_argb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette);
+ break;
+ case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32):
+ copyline_rgb32((UINT32*)mem->data + y * width, (UINT32*)base + y * rowpixels, width, palette);
+ break;
+ default:
+ break;
+ }
+ }
+ return mem;
+}
+
int renderer_bgfx::draw(int update)
{
- initVertexDecls();
int index = window().m_index;
// Set view 0 default viewport.
osd_dim wdim = window().get_size();
@@ -806,154 +823,48 @@ int renderer_bgfx::draw(int update)
bgfx::touch(index);
window().m_primlist->acquire_lock();
- // Draw quad.
- // now draw
- uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP;
- if (video_config.filter==0) texture_flags |= BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT;
-
- for (render_primitive *prim = window().m_primlist->first(); prim != NULL; prim = prim->next())
- {
- uint64_t flags = BGFX_STATE_RGB_WRITE;
- switch (prim->flags & PRIMFLAG_BLENDMODE_MASK)
- {
- case PRIMFLAG_BLENDMODE(BLENDMODE_NONE):
- break;
- case PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA):
- flags |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA);
- break;
- case PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
- flags |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO);
- break;
- case PRIMFLAG_BLENDMODE(BLENDMODE_ADD):
- flags |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE);
- }
- bool alpha = false;
+
+ bgfx::TransientVertexBuffer flat_buffer[4];
+ bgfx::TransientVertexBuffer textured_buffer[4];
+
+ allocate_buffers(flat_buffer, textured_buffer);
+
+ int flat_vertices[4] = { 0, 0, 0, 0 };
+ int textured_vertices[4] = { 0, 0, 0, 0 };
+
+ // Mark our texture atlas as dirty if we need to do so
+ bool atlas_valid = update_atlas();
+
+ memset(flat_vertices, 0, sizeof(int) * 4);
+ memset(textured_vertices, 0, sizeof(int) * 4);
+
+ for (render_primitive *prim = window().m_primlist->first(); prim != nullptr; prim = prim->next())
+ {
+ UINT32 blend = PRIMFLAG_GET_BLENDMODE(prim->flags);
+
switch (prim->type)
{
- /**
- * Try to stay in one Begin/End block as long as possible,
- * since entering and leaving one is most expensive..
- */
case render_primitive::LINE:
-
- drawLine(prim->bounds.x0, prim->bounds.y0, prim->bounds.x1, prim->bounds.y1,
- 1.0f,
- u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255),
- 1.0f);
- bgfx::setState(flags);
- bgfx::submit(index, m_progLine);
+ put_line(prim->bounds.x0, prim->bounds.y0, prim->bounds.x1, prim->bounds.y1, 1.0f, u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255), (PosColorVertex*)flat_buffer[blend].data + flat_vertices[blend], 1.0f);
+ flat_vertices[blend] += 30;
break;
case render_primitive::QUAD:
- if (prim->texture.base == nullptr) {
- render_quad_texuv uv;
- uv.tl.u = uv.tl.v = uv.tr.u = uv.tr.v = 0;
- uv.bl.u = uv.bl.v = uv.br.u = uv.br.v = 0;
- screenQuad(prim->bounds.x0, prim->bounds.y0, prim->bounds.x1, prim->bounds.y1,
- u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255), uv);
- bgfx::setState(flags);
- bgfx::submit(index, m_progQuad);
+ if (prim->texture.base == nullptr)
+ {
+ render_flat_quad(index, prim);
}
- else {
- screenQuad(prim->bounds.x0, prim->bounds.y0, prim->bounds.x1, prim->bounds.y1,
- u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255), prim->texcoords);
- bgfx::TextureHandle m_texture;
- // render based on the texture coordinates
- switch (prim->flags & PRIMFLAG_TEXFORMAT_MASK)
+ else
+ {
+ if (atlas_valid && (prim->flags & PRIMFLAG_PACKABLE) && prim->texture.hash != 0 && m_hash_to_entry[prim->texture.hash].hash())
{
- case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTEA16):
- alpha = true;
- case PRIMFLAG_TEXFORMAT(TEXFORMAT_PALETTE16):
- {
- auto mem = bgfx::alloc(prim->texture.width*prim->texture.height * 4);
- if (alpha)
- {
- for (int y = 0; y < prim->texture.height; y++)
- {
- copyline_palettea16((UINT32*)mem->data + y*prim->texture.width, (UINT16*)prim->texture.base + y*prim->texture.rowpixels, prim->texture.width, prim->texture.palette);
- }
- }
- else
- {
- for (int y = 0; y < prim->texture.height; y++)
- {
- copyline_palette16((UINT32*)mem->data + y*prim->texture.width, (UINT16*)prim->texture.base + y*prim->texture.rowpixels, prim->texture.width, prim->texture.palette);
- }
- }
-
- m_texture = bgfx::createTexture2D((uint16_t)prim->texture.width
- , (uint16_t)prim->texture.height
- , 1
- , bgfx::TextureFormat::BGRA8
- , texture_flags
- , mem
- );
- }
- break;
- case PRIMFLAG_TEXFORMAT(TEXFORMAT_YUY16):
- {
- auto mem = bgfx::alloc(prim->texture.width*prim->texture.height * 4);
- for (int y = 0; y < prim->texture.height; y++)
- {
- copyline_yuy16_to_argb((UINT32*)mem->data + y*prim->texture.width, (UINT16*)prim->texture.base + y*prim->texture.rowpixels, prim->texture.width, prim->texture.palette, 1);
- }
- m_texture = bgfx::createTexture2D((uint16_t)prim->texture.width
- , (uint16_t)prim->texture.height
- , 1
- , bgfx::TextureFormat::BGRA8
- , texture_flags
- , mem
- );
- }
- break;
- case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32):
- alpha = true;
- case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32):
- {
- if (prim->texture.rowpixels!=prim->texture.width)
- {
- auto mem = bgfx::alloc(prim->texture.width*prim->texture.height * 4);
- if (alpha)
- {
- for (int y = 0; y < prim->texture.height; y++)
- {
- copyline_argb32((UINT32*)mem->data + y*prim->texture.width, (UINT32*)prim->texture.base + y*prim->texture.rowpixels, prim->texture.width, prim->texture.palette);
- }
- }
- else
- {
- for (int y = 0; y < prim->texture.height; y++)
- {
- copyline_rgb32((UINT32*)mem->data + y*prim->texture.width, (UINT32*)prim->texture.base + y*prim->texture.rowpixels, prim->texture.width, prim->texture.palette);
- }
- }
-
- m_texture = bgfx::createTexture2D((uint16_t)prim->texture.width
- , (uint16_t)prim->texture.height
- , 1
- , bgfx::TextureFormat::BGRA8
- , texture_flags
- , mem
- );
- } else {
- m_texture = bgfx::createTexture2D((uint16_t)prim->texture.width
- , (uint16_t)prim->texture.height
- , 1
- , bgfx::TextureFormat::BGRA8
- , texture_flags
- , bgfx::copy(prim->texture.base, prim->texture.width*prim->texture.height*4)
- );
- }
- }
- break;
-
- default:
- break;
+ put_packed_quad(prim, prim->texture.hash, (PosColorTexCoord0Vertex*)textured_buffer[blend].data + textured_vertices[blend]);
+ textured_vertices[blend] += 6;
+ }
+ else
+ {
+ render_textured_quad(index, prim);
}
- bgfx::setTexture(0, m_s_texColor, m_texture);
- bgfx::setState(flags);
- bgfx::submit(index, m_progQuadTexture);
- bgfx::destroyTexture(m_texture);
}
break;
@@ -962,6 +873,27 @@ int renderer_bgfx::draw(int update)
}
}
+ for (UINT32 blend_mode = 0; blend_mode < BLENDMODE_COUNT; blend_mode++)
+ {
+ if (flat_vertices[blend_mode] > 0)
+ {
+ set_bgfx_state(blend_mode);
+ bgfx::setVertexBuffer(&flat_buffer[blend_mode]);
+ bgfx::submit(index, m_progQuad);
+ }
+ }
+
+ for (UINT32 blend_mode = 0; blend_mode < BLENDMODE_COUNT; blend_mode++)
+ {
+ if (textured_vertices[blend_mode] > 0)
+ {
+ set_bgfx_state(blend_mode);
+ bgfx::setVertexBuffer(&textured_buffer[blend_mode]);
+ bgfx::setTexture(0, m_s_texColor, m_texture_cache);
+ bgfx::submit(index, m_progQuadTexture);
+ }
+ }
+
window().m_primlist->release_lock();
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
@@ -969,3 +901,170 @@ int renderer_bgfx::draw(int update)
return 0;
}
+
+void renderer_bgfx::set_bgfx_state(UINT32 blend)
+{
+ uint64_t flags = BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_TEST_ALWAYS;
+
+ switch (blend)
+ {
+ case BLENDMODE_NONE:
+ bgfx::setState(flags);
+ break;
+ case BLENDMODE_ALPHA:
+ bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA));
+ break;
+ case BLENDMODE_RGB_MULTIPLY:
+ bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO));
+ break;
+ case BLENDMODE_ADD:
+ bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE));
+ break;
+ }
+}
+
+void renderer_bgfx::render_flat_quad(int view, render_primitive *prim)
+{
+ if (bgfx::checkAvailTransientVertexBuffer(6, PosColorVertex::ms_decl))
+ {
+ bgfx::TransientVertexBuffer vb;
+ bgfx::allocTransientVertexBuffer(&vb, 6, PosColorVertex::ms_decl);
+ PosColorVertex* vertex = (PosColorVertex*)vb.data;
+
+ UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
+
+ vertex[0].m_x = prim->bounds.x0;
+ vertex[0].m_y = prim->bounds.y0;
+ vertex[0].m_z = 0;
+ vertex[0].m_rgba = rgba;
+
+ vertex[1].m_x = prim->bounds.x1;
+ vertex[1].m_y = prim->bounds.y0;
+ vertex[1].m_z = 0;
+ vertex[1].m_rgba = rgba;
+
+ vertex[2].m_x = prim->bounds.x1;
+ vertex[2].m_y = prim->bounds.y1;
+ vertex[2].m_z = 0;
+ vertex[2].m_rgba = rgba;
+
+ vertex[3].m_x = prim->bounds.x1;
+ vertex[3].m_y = prim->bounds.y1;
+ vertex[3].m_z = 0;
+ vertex[3].m_rgba = rgba;
+
+ vertex[4].m_x = prim->bounds.x0;
+ vertex[4].m_y = prim->bounds.y1;
+ vertex[4].m_z = 0;
+ vertex[4].m_rgba = rgba;
+
+ vertex[5].m_x = prim->bounds.x0;
+ vertex[5].m_y = prim->bounds.y0;
+ vertex[5].m_z = 0;
+ vertex[5].m_rgba = rgba;
+ bgfx::setVertexBuffer(&vb);
+
+ set_bgfx_state(PRIMFLAG_GET_BLENDMODE(prim->flags));
+ bgfx::submit(view, m_progQuad);
+ }
+}
+
+bool renderer_bgfx::update_atlas()
+{
+ bool atlas_dirty = check_for_dirty_atlas();
+
+ if (atlas_dirty)
+ {
+ m_hash_to_entry.clear();
+
+ std::vector<std::vector<rectangle_packer::packed_rectangle>> packed;
+ if (m_packer.pack(m_texinfo, packed, 1024))
+ {
+ for (std::vector<rectangle_packer::packed_rectangle> pack : packed)
+ {
+ for (rectangle_packer::packed_rectangle rect : pack)
+ {
+ if (rect.hash() == 0xffffffff)
+ {
+ continue;
+ }
+ m_hash_to_entry[rect.hash()] = rect;
+ const bgfx::Memory* mem = mame_texture_data_to_bgfx_texture_data(rect.format(), rect.width(), rect.height(), rect.rowpixels(), rect.palette(), rect.base());
+ bgfx::updateTexture2D(m_texture_cache, 0, rect.x(), rect.y(), rect.width(), rect.height(), mem);
+ }
+ }
+ }
+ else
+ {
+ m_texinfo.clear();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool renderer_bgfx::check_for_dirty_atlas()
+{
+ bool atlas_dirty = false;
+
+ std::map<UINT32, rectangle_packer::packable_rectangle> acquired_infos;
+ for (render_primitive *prim = window().m_primlist->first(); prim != nullptr; prim = prim->next())
+ {
+ bool pack = prim->flags & PRIMFLAG_PACKABLE;
+ if (prim->type == render_primitive::QUAD && prim->texture.base != nullptr && pack)
+ {
+ const UINT32 hash = prim->texture.hash;
+
+ // If this texture is packable and not currently in the atlas, prepare the texture for putting in the atlas
+ if (hash != 0 && m_hash_to_entry[hash].hash() == 0 && acquired_infos[hash].hash() == 0)
+ { // Create create the texture and mark the atlas dirty
+ atlas_dirty = true;
+
+ m_texinfo.push_back(rectangle_packer::packable_rectangle(hash, prim->flags & PRIMFLAG_TEXFORMAT_MASK,
+ prim->texture.width, prim->texture.height,
+ prim->texture.rowpixels, prim->texture.palette, prim->texture.base));
+ acquired_infos[hash] = m_texinfo[m_texinfo.size() - 1];
+ }
+ }
+ }
+
+ return atlas_dirty;
+}
+
+void renderer_bgfx::allocate_buffers(bgfx::TransientVertexBuffer *flat_buffer, bgfx::TransientVertexBuffer *textured_buffer)
+{
+ int flat_vertices[4] = { 0, 0, 0, 0 };
+ int textured_vertices[4] = { 0, 0, 0, 0 };
+
+ for (render_primitive *prim = window().m_primlist->first(); prim != nullptr; prim = prim->next())
+ {
+ switch (prim->type)
+ {
+ case render_primitive::LINE:
+ flat_vertices[PRIMFLAG_GET_BLENDMODE(prim->flags)] += 30;
+ break;
+
+ case render_primitive::QUAD:
+ if (prim->flags & PRIMFLAG_PACKABLE && prim->texture.base != nullptr && prim->texture.hash != 0)
+ {
+ textured_vertices[PRIMFLAG_GET_BLENDMODE(prim->flags)] += 6;
+ }
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ }
+
+ for (int blend_mode = 0; blend_mode < 4; blend_mode++)
+ {
+ if (flat_vertices[blend_mode] > 0 && bgfx::checkAvailTransientVertexBuffer(flat_vertices[blend_mode], PosColorVertex::ms_decl))
+ {
+ bgfx::allocTransientVertexBuffer(&flat_buffer[blend_mode], flat_vertices[blend_mode], PosColorVertex::ms_decl);
+ }
+ if (textured_vertices[blend_mode] > 0 && bgfx::checkAvailTransientVertexBuffer(textured_vertices[blend_mode], PosColorTexCoord0Vertex::ms_decl))
+ {
+ bgfx::allocTransientVertexBuffer(&textured_buffer[blend_mode], textured_vertices[blend_mode], PosColorTexCoord0Vertex::ms_decl);
+ }
+ }
+}
diff --git a/src/osd/modules/render/drawbgfx.h b/src/osd/modules/render/drawbgfx.h
new file mode 100644
index 00000000000..b0cab8c8193
--- /dev/null
+++ b/src/osd/modules/render/drawbgfx.h
@@ -0,0 +1,115 @@
+#pragma once
+
+#ifndef __RENDER_BGFX__
+#define __RENDER_BGFX__
+
+#include <map>
+#include <vector>
+
+#include "binpacker.h"
+
+/* sdl_info is the information about SDL for the current screen */
+class renderer_bgfx : public osd_renderer
+{
+public:
+ renderer_bgfx(osd_window *w)
+ : osd_renderer(w, FLAG_NONE)
+ , m_dimensions(0, 0)
+ {
+ }
+
+ virtual int create() override;
+ virtual int draw(const int update) override;
+#ifdef OSD_SDL
+ virtual int xy_to_render_target(const int x, const int y, int *xt, int *yt) override;
+#else
+ virtual void save() override { }
+ virtual void record() override { }
+ virtual void toggle_fsfx() override { }
+#endif
+ virtual void destroy() override;
+ virtual render_primitive_list *get_primitives() override
+ {
+ osd_dim wdim = window().get_size();
+ window().target()->set_bounds(wdim.width(), wdim.height(), window().aspect());
+ return &window().target()->get_primitives();
+ }
+
+private:
+ struct PosColorTexCoord0Vertex
+ {
+ float m_x;
+ float m_y;
+ float m_z;
+ UINT32 m_rgba;
+ float m_u;
+ float m_v;
+
+ static void init()
+ {
+ ms_decl.begin()
+ .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
+ .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
+ .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
+ .end();
+ }
+
+ static bgfx::VertexDecl ms_decl;
+ };
+
+ struct PosColorVertex
+ {
+ float m_x;
+ float m_y;
+ float m_z;
+ UINT32 m_rgba;
+
+ static void init()
+ {
+ ms_decl
+ .begin()
+ .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
+ .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
+ .end();
+ }
+
+ static bgfx::VertexDecl ms_decl;
+ };
+
+ void allocate_buffers(bgfx::TransientVertexBuffer *flat_buffer, bgfx::TransientVertexBuffer *textured_buffer);
+
+ void render_textured_quad(int view, render_primitive* prim);
+ void render_flat_quad(int view, render_primitive *prim);
+
+ void put_packed_quad(render_primitive *prim, UINT32 hash, PosColorTexCoord0Vertex* vertex);
+ void put_polygon(const float* coords, UINT32 num_coords, float r, UINT32 rgba, PosColorVertex* vertex);
+ void put_line(float x0, float y0, float x1, float y1, float r, UINT32 rgba, PosColorVertex* vertex, float fth = 1.0f);
+
+ void set_bgfx_state(UINT32 blend);
+
+ uint32_t u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_t a);
+
+ bool check_for_dirty_atlas();
+ bool update_atlas();
+ const bgfx::Memory* mame_texture_data_to_bgfx_texture_data(UINT32 format, int width, int height, int rowpixels, const rgb_t *palette, void *base);
+
+ bgfx::ProgramHandle loadProgram(bx::FileReaderI* _reader, const char* _vsName, const char* _fsName);
+ bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName);
+
+ bgfx::ProgramHandle m_progQuad;
+ bgfx::ProgramHandle m_progQuadTexture;
+ bgfx::UniformHandle m_s_texColor;
+ bgfx::FrameBufferHandle fbh;
+ bgfx::TextureHandle m_texture_cache;
+
+ // Original display_mode
+ osd_dim m_dimensions;
+
+ std::map<UINT32, rectangle_packer::packed_rectangle> m_hash_to_entry;
+ std::vector<rectangle_packer::packable_rectangle> m_texinfo;
+ rectangle_packer m_packer;
+
+ static const uint16_t CACHE_SIZE = 1024;
+};
+
+#endif \ No newline at end of file