summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/render/drawbgfx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/render/drawbgfx.cpp')
-rw-r--r--src/osd/modules/render/drawbgfx.cpp1196
1 files changed, 655 insertions, 541 deletions
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index 35a50609cf4..f2d58f4e4d5 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
@@ -14,11 +14,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#if defined(SDLMAME_WIN32)
-#if (SDLMAME_SDL2)
#include <SDL2/SDL_syswm.h>
-#else
-#include <SDL/SDL_syswm.h>
-#endif
#endif
#else
#include "sdlinc.h"
@@ -32,6 +28,16 @@
#include <bgfx/bgfx.h>
#include <bx/fpumath.h>
#include <bx/readerwriter.h>
+#include <algorithm>
+
+#include "drawbgfx.h"
+#include "bgfx/texturemanager.h"
+#include "bgfx/targetmanager.h"
+#include "bgfx/shadermanager.h"
+#include "bgfx/effectmanager.h"
+#include "bgfx/effect.h"
+#include "bgfx/texture.h"
+#include "bgfx/target.h"
//============================================================
// DEBUGGING
@@ -45,6 +51,8 @@
// MACROS
//============================================================
+#define GIBBERISH (0)
+
//============================================================
// INLINES
//============================================================
@@ -55,87 +63,9 @@
//============================================================
-/* 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
-//============================================================
-
-// core functions
-static void drawbgfx_exit(void);
-
-//============================================================
-// drawnone_create
-//============================================================
-
-static osd_renderer *drawbgfx_create(osd_window *window)
-{
- return global_alloc(renderer_bgfx(window));
-}
-
-//============================================================
-// drawbgfx_init
-//============================================================
-
-int drawbgfx_init(running_machine &machine, osd_draw_callbacks *callbacks)
-{
- // fill in the callbacks
- //memset(callbacks, 0, sizeof(*callbacks));
- callbacks->exit = drawbgfx_exit;
- callbacks->create = drawbgfx_create;
-
- return 0;
-}
-
-//============================================================
-// drawbgfx_exit
-//============================================================
-
-static void drawbgfx_exit(void)
-{
- // Shutdown bgfx.
- bgfx::shutdown();
-}
-
//============================================================
// renderer_bgfx::create
//============================================================
-bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName);
-
#ifdef OSD_SDL
static void* sdlNativeWindowHandle(SDL_Window* _window)
@@ -144,7 +74,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
@@ -153,6 +83,10 @@ static void* sdlNativeWindowHandle(SDL_Window* _window)
return wmi.info.cocoa.window;
# elif BX_PLATFORM_WINDOWS
return wmi.info.win.window;
+# elif BX_PLATFORM_STEAMLINK
+ return wmi.info.vivante.window;
+# elif BX_PLATFORM_EMSCRIPTEN
+ return nullptr;
# endif // BX_PLATFORM_
}
#endif
@@ -162,6 +96,8 @@ int renderer_bgfx::create()
// create renderer
osd_dim wdim = window().get_size();
+ m_width[window().m_index] = wdim.width();
+ m_height[window().m_index] = wdim.height();
if (window().m_index == 0)
{
#ifdef OSD_WINDOWS
@@ -170,43 +106,62 @@ int renderer_bgfx::create()
bgfx::sdlSetWindow(window().sdl_window());
#endif
bgfx::init();
- bgfx::reset(wdim.width(), wdim.height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
+ bgfx::reset(m_width[window().m_index], m_height[window().m_index], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
// Enable debug text.
bgfx::setDebug(BGFX_DEBUG_TEXT); //BGFX_DEBUG_STATS
- m_dimensions = osd_dim(wdim.width(), wdim.height());
+ m_dimensions = osd_dim(m_width[0], m_height[0]);
+
+ ScreenVertex::init();
}
- else {
+
+ m_textures = new texture_manager();
+ m_targets = new target_manager(*m_textures);
+ m_shaders = new shader_manager();
+ m_effects = new effect_manager(*m_shaders);
+
+ if (window().m_index != 0)
+ {
#ifdef OSD_WINDOWS
- fbh = bgfx::createFrameBuffer(window().m_hwnd, wdim.width(), wdim.height());
+ m_framebuffer = m_targets->create_target("backbuffer", window().m_hwnd, m_width[window().m_index], m_height[window().m_index]);
#else
- fbh = bgfx::createFrameBuffer(sdlNativeWindowHandle(window().sdl_window()), wdim.width(), wdim.height());
+ m_framebuffer = m_targets->create_target("backbuffer", sdlNativeWindowHandle(window().sdl_window()), m_width[window().m_index], m_height[window().m_index]);
#endif
- bgfx::touch(window().m_index);
- }
+ bgfx::touch(window().m_index);
+ }
+
// 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);
+ m_gui_effect[0] = m_effects->effect("gui_opaque");
+ m_gui_effect[1] = m_effects->effect("gui_blend");
+ m_gui_effect[2] = m_effects->effect("gui_multiply");
+ m_gui_effect[3] = m_effects->effect("gui_add");
+
+ m_screen_effect[0] = m_effects->effect("screen_opaque");
+ m_screen_effect[1] = m_effects->effect("screen_blend");
+ m_screen_effect[2] = m_effects->effect("screen_multiply");
+ m_screen_effect[3] = m_effects->effect("screen_add");
+
+ uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT;
+ m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::RGBA8, CACHE_SIZE, CACHE_SIZE, nullptr, flags);
+
+ memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16);
+ m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white));
return 0;
}
//============================================================
-// drawbgfx_window_destroy
+// destructor
//============================================================
-void renderer_bgfx::destroy()
+renderer_bgfx::~renderer_bgfx()
{
- if (window().m_index > 0)
- {
- bgfx::destroyFrameBuffer(fbh);
- }
- bgfx::destroyUniform(m_s_texColor);
// Cleanup.
- bgfx::destroyProgram(m_progQuad);
- bgfx::destroyProgram(m_progQuadTexture);
- bgfx::destroyProgram(m_progLine);
+ delete m_targets;
+ delete m_textures;
+ delete m_effects;
+ delete m_shaders;
+
+ bgfx::shutdown();
}
@@ -227,198 +182,180 @@ int renderer_bgfx::xy_to_render_target(int x, int y, int *xt, int *yt)
}
#endif
-static const bgfx::Memory* loadMem(bx::FileReaderI* _reader, const char* _filePath)
+//============================================================
+// drawbgfx_window_draw
+//============================================================
+
+bgfx::VertexDecl renderer_bgfx::ScreenVertex::ms_decl;
+
+void renderer_bgfx::put_packed_quad(render_primitive *prim, UINT32 hash, ScreenVertex* vertex)
{
- if (bx::open(_reader, _filePath))
+ 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);
+ u1 -= 0.5f / float(CACHE_SIZE);
+ v1 -= 0.5f / float(CACHE_SIZE);
+ u0 += 0.5f / float(CACHE_SIZE);
+ v0 += 0.5f / float(CACHE_SIZE);
+ UINT32 rgba = u32Color(prim->color.r * 255, prim->color.g * 255, prim->color.b * 255, prim->color.a * 255);
+
+ float x[4] = { prim->bounds.x0, prim->bounds.x1, prim->bounds.x0, prim->bounds.x1 };
+ float y[4] = { prim->bounds.y0, prim->bounds.y0, prim->bounds.y1, prim->bounds.y1 };
+ float u[4] = { u0, u1, u0, u1 };
+ float v[4] = { v0, v0, v1, v1 };
+
+ if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_SWAP_XY)
{
- uint32_t size = (uint32_t)bx::getSize(_reader);
- const bgfx::Memory* mem = bgfx::alloc(size + 1);
- bx::read(_reader, mem->data, size);
- bx::close(_reader);
- mem->data[mem->size - 1] = '\0';
- return mem;
+ std::swap(u[1], u[2]);
+ std::swap(v[1], v[2]);
}
- return NULL;
-}
-static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader, const char* _name)
-{
- char filePath[512];
-
- const char* shaderPath = "shaders/dx9/";
-
- switch (bgfx::getRendererType())
+ if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_FLIP_X)
{
- case bgfx::RendererType::Direct3D11:
- case bgfx::RendererType::Direct3D12:
- shaderPath = "shaders/dx11/";
- break;
-
- case bgfx::RendererType::OpenGL:
- shaderPath = "shaders/glsl/";
- break;
-
- case bgfx::RendererType::Metal:
- shaderPath = "shaders/metal/";
- break;
-
- case bgfx::RendererType::OpenGLES:
- shaderPath = "shaders/gles/";
- break;
-
- default:
- break;
+ std::swap(u[0], u[1]);
+ std::swap(v[0], v[1]);
+ std::swap(u[2], u[3]);
+ std::swap(v[2], v[3]);
}
- strcpy(filePath, shaderPath);
- strcat(filePath, _name);
- strcat(filePath, ".bin");
-
- return bgfx::createShader(loadMem(_reader, filePath));
-}
-
-bgfx::ProgramHandle 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 (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_FLIP_Y)
{
- fsh = loadShader(_reader, _fsName);
+ std::swap(u[0], u[2]);
+ std::swap(v[0], v[2]);
+ std::swap(u[1], u[3]);
+ std::swap(v[1], v[3]);
}
- return bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */);
+ vertex[0].m_x = x[0]; // 0
+ vertex[0].m_y = y[0];
+ vertex[0].m_z = 0;
+ vertex[0].m_rgba = rgba;
+ vertex[0].m_u = u[0];
+ vertex[0].m_v = v[0];
+
+ vertex[1].m_x = x[1]; // 1
+ vertex[1].m_y = y[1];
+ vertex[1].m_z = 0;
+ vertex[1].m_rgba = rgba;
+ vertex[1].m_u = u[1];
+ vertex[1].m_v = v[1];
+
+ vertex[2].m_x = x[3]; // 3
+ vertex[2].m_y = y[3];
+ vertex[2].m_z = 0;
+ vertex[2].m_rgba = rgba;
+ vertex[2].m_u = u[3];
+ vertex[2].m_v = v[3];
+
+ vertex[3].m_x = x[3]; // 3
+ vertex[3].m_y = y[3];
+ vertex[3].m_z = 0;
+ vertex[3].m_rgba = rgba;
+ vertex[3].m_u = u[3];
+ vertex[3].m_v = v[3];
+
+ vertex[4].m_x = x[2]; // 2
+ vertex[4].m_y = y[2];
+ vertex[4].m_z = 0;
+ vertex[4].m_rgba = rgba;
+ vertex[4].m_u = u[2];
+ vertex[4].m_v = v[2];
+
+ vertex[5].m_x = x[0]; // 0
+ vertex[5].m_y = y[0];
+ vertex[5].m_z = 0;
+ vertex[5].m_rgba = rgba;
+ vertex[5].m_u = u[0];
+ vertex[5].m_v = v[0];
}
-static auto s_fileReader = new bx::CrtFileReader;
-bgfx::ProgramHandle loadProgram(const char* _vsName, const char* _fsName)
+void renderer_bgfx::render_textured_quad(int view, render_primitive* prim, bgfx::TransientVertexBuffer* buffer)
{
-
- return loadProgram(s_fileReader, _vsName, _fsName);
-}
-//============================================================
-// drawbgfx_window_draw
-//============================================================
+ ScreenVertex* vertex = (ScreenVertex*)buffer->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[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(buffer);
-struct PosColorTexCoord0Vertex
-{
- 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
- )
-{
- if (bgfx::checkAvailTransientVertexBuffer(6, PosColorTexCoord0Vertex::ms_decl))
- {
- bgfx::TransientVertexBuffer vb;
- 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;
- 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::RGBA8, 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_effect** effects = PRIMFLAG_GET_SCREENTEX(prim->flags) ? m_screen_effect : m_gui_effect;
+ UINT32 blend = PRIMFLAG_GET_BLENDMODE(prim->flags);
+ bgfx::setTexture(0, effects[blend]->uniform("s_tex")->handle(), texture);
+ effects[blend]->submit(view);
- static bgfx::VertexDecl ms_decl;
-};
-bgfx::VertexDecl PosColorVertex::ms_decl;
+ bgfx::destroyTexture(texture);
+}
#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, ScreenVertex* 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;
+ rectangle_packer::packed_rectangle& rect = m_hash_to_entry[WHITE_HASH];
+ float u0 = float(rect.x()) / float(CACHE_SIZE);
+ float v0 = float(rect.y()) / float(CACHE_SIZE);
- for (uint32_t ii = 0, jj = _numCoords - 1; ii < _numCoords; jj = ii++)
+ num_coords = num_coords < MAX_TEMP_COORDS ? num_coords : MAX_TEMP_COORDS;
+
+ 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 +370,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 +391,96 @@ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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;
+ vertex[vertIndex].m_u = u0;
+ vertex[vertIndex].m_v = v0;
+ 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, ScreenVertex* 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 +491,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;
-
- verts[0] = _x0 - dx - nx;
- verts[1] = _y0 - dy - ny;
+ dx *= r;
+ dy *= r;
+ nx *= r;
+ ny *= r;
- verts[2] = _x0 - dx + nx;
- verts[3] = _y0 - dy + ny;
+ verts[0] = x0 - dx - nx;
+ verts[1] = y0 - dy - ny;
+ verts[2] = 0;
- verts[4] = _x1 + dx + nx;
- verts[5] = _y1 + dy + ny;
+ verts[3] = x0 - dx + nx;
+ verts[4] = y0 - dy + ny;
+ verts[5] = 0;
- verts[6] = _x1 + dx - nx;
- verts[7] = _y1 + dy - ny;
+ verts[6] = x1 + dx + nx;
+ verts[7] = y1 + dy + ny;
+ verts[8] = 0;
- drawPolygon(verts, 4, _fth, _abgr);
-}
+ verts[9] = x1 + dx - nx;
+ verts[10] = y1 + dy - ny;
+ verts[11] = 0;
-void initVertexDecls()
-{
- PosColorTexCoord0Vertex::init();
- PosColorVertex::init();
+ put_polygon(verts, 4, fth, rgba, vertex);
}
-static inline
-uint32_t u32Color(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a = 255)
+uint32_t renderer_bgfx::u32Color(uint32_t r, uint32_t g, uint32_t b, uint32_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;
}
//============================================================
@@ -587,7 +535,10 @@ uint32_t u32Color(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a = 255)
static inline void copyline_palette16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette)
{
for (int x = 0; x < width; x++)
- *dst++ = 0xff000000 | palette[*src++];
+ {
+ rgb_t srcpixel = palette[*src++];
+ *dst++ = 0xff000000 | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r();
+ }
}
@@ -598,7 +549,10 @@ static inline void copyline_palette16(UINT32 *dst, const UINT16 *src, int width,
static inline void copyline_palettea16(UINT32 *dst, const UINT16 *src, int width, const rgb_t *palette)
{
for (int x = 0; x < width; x++)
- *dst++ = palette[*src++];
+ {
+ rgb_t srcpixel = palette[*src++];
+ *dst++ = (srcpixel.a() << 24) | (srcpixel.b() << 16) | (srcpixel.g() << 8) | srcpixel.r();
+ }
}
@@ -609,14 +563,14 @@ 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++)
{
rgb_t srcpix = *src++;
- *dst++ = 0xff000000 | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
+ *dst++ = 0xff000000 | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()];
}
}
@@ -624,7 +578,10 @@ static inline void copyline_rgb32(UINT32 *dst, const UINT32 *src, int width, con
else
{
for (x = 0; x < width; x++)
- *dst++ = 0xff000000 | *src++;
+ {
+ rgb_t srcpix = *src++;
+ *dst++ = 0xff000000 | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r();
+ }
}
}
@@ -637,12 +594,12 @@ 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++)
{
rgb_t srcpix = *src++;
- *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.r()] | palette[0x100 + srcpix.g()] | palette[srcpix.b()];
+ *dst++ = (srcpix & 0xff000000) | palette[0x200 + srcpix.b()] | palette[0x100 + srcpix.g()] | palette[srcpix.r()];
}
}
@@ -650,7 +607,10 @@ static inline void copyline_argb32(UINT32 *dst, const UINT32 *src, int width, co
else
{
for (x = 0; x < width; x++)
- *dst++ = *src++;
+ {
+ rgb_t srcpix = *src++;
+ *dst++ = (srcpix.a() << 24) | (srcpix.b() << 16) | (srcpix.g() << 8) | srcpix.r();
+ }
}
}
@@ -692,7 +652,7 @@ static inline UINT32 ycc_to_rgb(UINT8 y, UINT8 cb, UINT8 cr)
if (b < 0) b = 0;
else if (b > 255) b = 255;
- return rgb_t(0xff, r, g, b);
+ return 0xff000000 | (b << 16) | (g << 8) | r;
}
//============================================================
@@ -706,7 +666,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,35 +697,64 @@ 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();
- int width = wdim.width();
- int height = wdim.height();
+ m_width[index] = wdim.width();
+ m_height[index] = wdim.height();
if (index == 0)
{
- if ((m_dimensions != osd_dim(width, height))) {
- bgfx::reset(width, height, video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
- m_dimensions = osd_dim(width, height);
+ if ((m_dimensions != osd_dim(m_width[index], m_height[index])))
+ {
+ bgfx::reset(m_width[index], m_height[index], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
+ m_dimensions = osd_dim(m_width[index], m_height[index]);
}
}
- else {
- if ((m_dimensions != osd_dim(width, height))) {
+ else
+ {
+ if ((m_dimensions != osd_dim(m_width[index], m_height[index])))
+ {
bgfx::reset(window().m_main->get_size().width(), window().m_main->get_size().height(), video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
- if (bgfx::isValid(fbh))
- {
- bgfx::destroyFrameBuffer(fbh);
- }
+ delete m_framebuffer;
#ifdef OSD_WINDOWS
- fbh = bgfx::createFrameBuffer(window().m_hwnd, width, height);
+ m_framebuffer = m_targets->create_target("backbuffer", window().m_hwnd, m_width[index], m_height[index]);
#else
- fbh = bgfx::createFrameBuffer(sdlNativeWindowHandle(window().sdl_window()), width, height);
+ m_framebuffer = m_targets->create_target("backbuffer", sdlNativeWindowHandle(window().sdl_window()), m_width[index], m_height[index]);
#endif
- bgfx::setViewFrameBuffer(index, fbh);
- m_dimensions = osd_dim(width, height);
+ bgfx::setViewFrameBuffer(index, m_framebuffer->target());
+ m_dimensions = osd_dim(m_width[index], m_height[index]);
bgfx::setViewClear(index
, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
, 0x000000ff
@@ -777,9 +766,13 @@ int renderer_bgfx::draw(int update)
return 0;
}
}
- if (index != 0) bgfx::setViewFrameBuffer(index, fbh);
- bgfx::setViewSeq(index, true);
- bgfx::setViewRect(index, 0, 0, width, height);
+
+ if (index != 0)
+ {
+ bgfx::setViewFrameBuffer(index, m_framebuffer->target());
+ }
+ bgfx::setViewSeq(index, true);
+ bgfx::setViewRect(index, 0, 0, m_width[index], m_height[index]);
// Setup view transform.
{
@@ -788,8 +781,8 @@ int renderer_bgfx::draw(int update)
float left = 0.0f;
float top = 0.0f;
- float right = width;
- float bottom = height;
+ float right = m_width[index];
+ float bottom = m_height[index];
float proj[16];
bx::mtxOrtho(proj, left, right, bottom, top, 0.0f, 100.0f);
bgfx::setViewTransform(index, view, proj);
@@ -801,171 +794,292 @@ int renderer_bgfx::draw(int update)
, 0
);
+ window().m_primlist->acquire_lock();
+
+ // Mark our texture atlas as dirty if we need to do so
+ bool atlas_valid = update_atlas();
+
+ render_primitive *prim = window().m_primlist->first();
+ while (prim != nullptr)
+ {
+ UINT32 blend = PRIMFLAG_GET_BLENDMODE(prim->flags);
+
+ bgfx::TransientVertexBuffer buffer;
+ allocate_buffer(prim, blend, &buffer);
+
+ buffer_status status = buffer_primitives(index, atlas_valid, &prim, &buffer);
+
+ if (status != BUFFER_EMPTY)
+ {
+ bgfx::setVertexBuffer(&buffer);
+ bgfx::setTexture(0, m_gui_effect[blend]->uniform("s_tex")->handle(), m_texture_cache->handle());
+ m_gui_effect[blend]->submit(index);
+ }
+
+ if (status != BUFFER_DONE && status != BUFFER_PRE_FLUSH)
+ {
+ prim = prim->next();
+ }
+ }
+
+ window().m_primlist->release_lock();
+
// This dummy draw call is here to make sure that view 0 is cleared
// if no other draw calls are submitted to view 0.
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())
+ // Advance to next frame. Rendering thread will be kicked to
+ // process submitted rendering primitives.
+ if (index==0) bgfx::frame();
+
+ return 0;
+}
+
+renderer_bgfx::buffer_status renderer_bgfx::buffer_primitives(int view, bool atlas_valid, render_primitive** prim, bgfx::TransientVertexBuffer* buffer)
+{
+ int vertices = 0;
+
+ UINT32 blend = PRIMFLAG_GET_BLENDMODE((*prim)->flags);
+ while (*prim != nullptr)
{
- uint64_t flags = BGFX_STATE_RGB_WRITE;
- switch (prim->flags & PRIMFLAG_BLENDMODE_MASK)
+ switch ((*prim)->type)
+ {
+ case render_primitive::LINE:
+ 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), (ScreenVertex*)buffer->data + vertices, 1.0f);
+ vertices += 30;
+ break;
+
+ case render_primitive::QUAD:
+ if ((*prim)->texture.base == nullptr)
+ {
+ put_packed_quad(*prim, WHITE_HASH, (ScreenVertex*)buffer->data + vertices);
+ vertices += 6;
+ }
+ else
+ {
+ const UINT32 hash = get_texture_hash(*prim);
+ if (atlas_valid && (*prim)->packable(PACKABLE_SIZE) && hash != 0 && m_hash_to_entry[hash].hash())
+ {
+ put_packed_quad(*prim, hash, (ScreenVertex*)buffer->data + vertices);
+ vertices += 6;
+ }
+ else
+ {
+ if (vertices > 0)
+ {
+ return BUFFER_PRE_FLUSH;
+ }
+ render_textured_quad(view, *prim, buffer);
+ return BUFFER_EMPTY;
+ }
+ }
+ break;
+
+ default:
+ // Unhandled
+ break;
+ }
+
+ if ((*prim)->next() != nullptr && PRIMFLAG_GET_BLENDMODE((*prim)->next()->flags) != blend)
{
- 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);
+ }
+
+ *prim = (*prim)->next();
+ }
+
+ if (*prim == nullptr)
+ {
+ return BUFFER_DONE;
+ }
+ if (vertices == 0)
+ {
+ return BUFFER_EMPTY;
+ }
+ return BUFFER_FLUSH;
+}
+
+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 PRIMFLAG_BLENDMODE(BLENDMODE_RGB_MULTIPLY):
- flags |= BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO);
+ case BLENDMODE_RGB_MULTIPLY:
+ bgfx::setState(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);
+ case BLENDMODE_ADD:
+ bgfx::setState(flags | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE));
+ break;
+ }
+}
+
+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, CACHE_SIZE))
+ {
+ process_atlas_packs(packed);
}
- bool alpha = false;
- switch (prim->type)
+ else
{
- /**
- * 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);
- break;
+ packed.clear();
+
+ m_texinfo.clear();
+ m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white));
+
+ m_packer.pack(m_texinfo, packed, CACHE_SIZE);
+ process_atlas_packs(packed);
+
+ return false;
+ }
+ }
+ return true;
+}
+
+void renderer_bgfx::process_atlas_packs(std::vector<std::vector<rectangle_packer::packed_rectangle>>& packed)
+{
+ 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->handle(), 0, rect.x(), rect.y(), rect.width(), rect.height(), mem);
+ }
+ }
+}
+
+UINT32 renderer_bgfx::get_texture_hash(render_primitive *prim)
+{
+#if GIBBERISH
+ UINT32 xor_value = 0x87;
+ UINT32 hash = 0xdabeefed;
- 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);
+ int bpp = 2;
+ UINT32 format = PRIMFLAG_GET_TEXFORMAT(prim->flags);
+ if (format == TEXFORMAT_ARGB32 || format == TEXFORMAT_RGB32)
+ {
+ bpp = 4;
+ }
+
+ for (int y = 0; y < prim->texture.height; y++)
+ {
+ UINT8 *base = reinterpret_cast<UINT8*>(prim->texture.base) + prim->texture.rowpixels * y;
+ for (int x = 0; x < prim->texture.width * bpp; x++)
+ {
+ hash += base[x] ^ xor_value;
+ }
+ }
+ return hash;
+#else
+ return (reinterpret_cast<size_t>(prim->texture.base)) & 0xffffffff;
+#endif
+}
+
+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->packable(PACKABLE_SIZE);
+ if (prim->type == render_primitive::QUAD && prim->texture.base != nullptr && pack)
+ {
+ const UINT32 hash = get_texture_hash(prim);
+ // 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)
+ || (hash != 0 && m_hash_to_entry[hash].hash() != hash && 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];
}
- 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)
- {
- 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):
+ if (m_texinfo.size() == 1)
+ {
+ atlas_dirty = true;
+ }
+
+ return atlas_dirty;
+}
+
+void renderer_bgfx::allocate_buffer(render_primitive *prim, UINT32 blend, bgfx::TransientVertexBuffer *buffer)
+{
+ int vertices = 0;
+
+ bool mode_switched = false;
+ while (prim != nullptr && !mode_switched)
+ {
+ switch (prim->type)
+ {
+ case render_primitive::LINE:
+ vertices += 30;
+ break;
+
+ case render_primitive::QUAD:
+ if (!prim->packable(PACKABLE_SIZE))
+ {
+ if (prim->texture.base == nullptr)
{
- 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
- );
+ vertices += 6;
}
- break;
- case PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32):
- alpha = true;
- case PRIMFLAG_TEXFORMAT(TEXFORMAT_RGB32):
+ else
{
- if (prim->texture.rowpixels!=prim->texture.width)
+ mode_switched = true;
+ if (vertices == 0)
{
- 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)
- );
+ vertices += 6;
}
}
- break;
-
- default:
- break;
}
- bgfx::setTexture(0, m_s_texColor, m_texture);
- bgfx::setState(flags);
- bgfx::submit(index, m_progQuadTexture);
- bgfx::destroyTexture(m_texture);
- }
- break;
+ else
+ {
+ vertices += 6;
+ }
+ break;
+ default:
+ // Do nothing
+ break;
+ }
- default:
- throw emu_fatalerror("Unexpected render_primitive type");
+ prim = prim->next();
+
+ if (prim != nullptr && PRIMFLAG_GET_BLENDMODE(prim->flags) != blend)
+ {
+ mode_switched = true;
}
}
- window().m_primlist->release_lock();
- // Advance to next frame. Rendering thread will be kicked to
- // process submitted rendering primitives.
- if (index==0) bgfx::frame();
-
- return 0;
+ if (vertices > 0 && bgfx::checkAvailTransientVertexBuffer(vertices, ScreenVertex::ms_decl))
+ {
+ bgfx::allocTransientVertexBuffer(buffer, vertices, ScreenVertex::ms_decl);
+ }
}
+
+slider_state* renderer_bgfx::get_slider_list()
+{
+ return nullptr;
+} \ No newline at end of file