branches/bgfx_shader/src/osd/modules/render/bgfx/target.cpp
r255105 | r255106 | |
6 | 6 | // |
7 | 7 | //============================================================ |
8 | 8 | |
| 9 | #include "emu.h" |
| 10 | |
9 | 11 | #include "target.h" |
10 | 12 | |
11 | | bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, bool double_buffer, bool filter, bool init, bool output) |
| 13 | bgfx_target::bgfx_target(std::string name, bgfx::TextureFormat::Enum format, uint16_t width, uint16_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, int32_t index, bool double_buffer, bool filter, bool init, bool output) |
12 | 14 | : m_name(name) |
13 | 15 | , m_format(format) |
14 | 16 | , m_targets(nullptr) |
r255105 | r255106 | |
21 | 23 | , m_style(style) |
22 | 24 | , m_filter(filter) |
23 | 25 | , m_output(output) |
24 | | , m_current_page(0) |
| 26 | , m_index(index) |
| 27 | , m_current_page(0) |
25 | 28 | , m_initialized(false) |
26 | 29 | , m_page_count(double_buffer ? 2 : 1) |
27 | 30 | { |
r255105 | r255106 | |
35 | 38 | for (int page = 0; page < m_page_count; page++) |
36 | 39 | { |
37 | 40 | m_textures[page] = bgfx::createTexture2D(width * prescale_x, height * prescale_y, 1, format, wrap_mode | filter_mode | BGFX_TEXTURE_RT); |
| 41 | assert(m_textures[page].idx != 0xffff); |
38 | 42 | m_targets[page] = bgfx::createFrameBuffer(1, &m_textures[page], false); |
39 | | } |
| 43 | assert(m_targets[page].idx != 0xffff); |
| 44 | } |
40 | 45 | |
41 | 46 | m_initialized = true; |
42 | 47 | } |
r255105 | r255106 | |
55 | 60 | , m_style(TARGET_STYLE_CUSTOM) |
56 | 61 | , m_filter(false) |
57 | 62 | , m_current_page(0) |
58 | | , m_initialized(true) |
| 63 | , m_index(-1) |
| 64 | , m_initialized(true) |
59 | 65 | , m_page_count(0) |
60 | 66 | { |
61 | 67 | m_targets = new bgfx::FrameBufferHandle[1]; |
r255105 | r255106 | |
66 | 72 | |
67 | 73 | bgfx_target::~bgfx_target() |
68 | 74 | { |
69 | | if (!m_initialized) return; |
| 75 | if (!m_initialized) |
| 76 | { |
| 77 | return; |
| 78 | } |
70 | 79 | |
71 | 80 | if (m_page_count > 0) |
72 | 81 | { |
73 | 82 | for (int page = 0; page < m_page_count; page++) |
74 | 83 | { |
75 | 84 | bgfx::destroyFrameBuffer(m_targets[page]); |
76 | | bgfx::destroyTexture(m_textures[page]); |
77 | | } |
| 85 | bgfx::destroyTexture(m_textures[page]); |
| 86 | } |
78 | 87 | delete [] m_textures; |
79 | 88 | delete [] m_targets; |
80 | 89 | } |
branches/bgfx_shader/src/osd/modules/render/bgfx/targetmanager.cpp
r255105 | r255106 | |
19 | 19 | |
20 | 20 | #include "target.h" |
21 | 21 | |
| 22 | const int32_t target_manager::MAX_SCREENS = 100; |
| 23 | |
| 24 | target_manager::target_manager(osd_options& options, texture_manager& textures) |
| 25 | : m_textures(textures) |
| 26 | , m_options(options) |
| 27 | , m_screen_count(0) |
| 28 | { |
| 29 | m_guest_width = new uint16_t[MAX_SCREENS]; |
| 30 | m_guest_height = new uint16_t[MAX_SCREENS]; |
| 31 | memset(m_guest_width, 0, sizeof(uint16_t) * MAX_SCREENS); |
| 32 | memset(m_guest_height, 0, sizeof(uint16_t) * MAX_SCREENS); |
| 33 | } |
| 34 | |
22 | 35 | target_manager::~target_manager() |
23 | 36 | { |
24 | 37 | for (std::pair<std::string, bgfx_target*> target : m_targets) |
25 | 38 | { |
26 | | delete target.second; |
| 39 | if (target.second != nullptr) |
| 40 | { |
| 41 | delete target.second; |
| 42 | } |
27 | 43 | } |
28 | 44 | m_targets.clear(); |
| 45 | delete [] m_guest_width; |
| 46 | delete [] m_guest_height; |
29 | 47 | } |
30 | 48 | |
31 | 49 | bgfx_target* target_manager::create_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, bool double_buffer, bool filter, bool output) |
32 | 50 | { |
33 | | bgfx_target* target = new bgfx_target(name, format, width, height, prescale_x, prescale_y, style, double_buffer, filter, width > 0 && height > 0, output); |
| 51 | bgfx_target* target = new bgfx_target(name, format, width, height, prescale_x, prescale_y, style, -1, double_buffer, filter, width > 0 && height > 0, output); |
34 | 52 | m_targets[name] = target; |
35 | 53 | |
36 | 54 | m_textures.add_provider(name, target); |
r255105 | r255106 | |
55 | 73 | return nullptr; |
56 | 74 | } |
57 | 75 | |
58 | | void target_manager::update_guest_targets(uint16_t width, uint16_t height) |
| 76 | void target_manager::update_guest_targets(int32_t screen, uint16_t width, uint16_t height) |
59 | 77 | { |
60 | | if (width != m_guest_width || height != m_guest_height) |
| 78 | if (screen < 0 || screen >= MAX_SCREENS) |
| 79 | { |
| 80 | return; |
| 81 | } |
| 82 | |
| 83 | if (width != m_guest_width[screen] || height != m_guest_height[screen]) |
61 | 84 | { |
62 | | m_guest_width = width; |
63 | | m_guest_height = height; |
| 85 | m_guest_width[screen] = width; |
| 86 | m_guest_height[screen] = height; |
| 87 | ensure_guest_targets(); |
| 88 | rebuild_guest_targets(screen); |
| 89 | } |
| 90 | } |
64 | 91 | |
65 | | std::vector<bgfx_target*> to_resize; |
66 | | for (std::pair<std::string, bgfx_target*> target : m_targets) |
67 | | { |
68 | | if ((target.second)->style() == TARGET_STYLE_GUEST) |
69 | | { |
70 | | to_resize.push_back(target.second); |
71 | | } |
72 | | } |
| 92 | void target_manager::ensure_guest_targets() |
| 93 | { |
| 94 | // Build a list of all guest targets that end in 0 *or* don't end in a number |
| 95 | std::vector<std::string> existing_names; |
| 96 | for (std::pair<std::string, bgfx_target*> target_pair : m_targets) |
| 97 | { |
| 98 | bgfx_target* target = target_pair.second; |
| 99 | if (target == nullptr || target->style() != TARGET_STYLE_GUEST) |
| 100 | { |
| 101 | continue; |
| 102 | } |
73 | 103 | |
74 | | for (bgfx_target* target : to_resize) |
75 | | { |
76 | | std::string name = target->name(); |
77 | | const bgfx::TextureFormat::Enum format = target->format(); |
78 | | const bool double_buffered = target->double_buffered(); |
79 | | const bool filter = target->filter(); |
80 | | const uint32_t prescale_x = target->prescale_x(); |
81 | | const uint32_t prescale_y = target->prescale_y(); |
82 | | delete target; |
| 104 | // If the last character is not a digit, add it to the list |
| 105 | std::string name = target->name(); |
| 106 | char last_char = name[name.length() - 1]; |
| 107 | if ((last_char & 0xf0) != 0x30) { |
| 108 | existing_names.push_back(name); |
| 109 | } |
83 | 110 | |
84 | | m_targets[name] = new bgfx_target(name, format, m_guest_width, m_guest_height, prescale_x, prescale_y, TARGET_STYLE_GUEST, double_buffered, filter); |
85 | | m_textures.add_provider(name, m_targets[name]); |
86 | | } |
87 | | } |
| 111 | // If the last character is a zero, and the stripped name isn't already in the list, strip it off and add it to the list |
| 112 | if (last_char == 0x30) |
| 113 | { |
| 114 | std::string shortened_name = name.substr(0, name.length() - 1); |
| 115 | bool exists = false; |
| 116 | for (std::string other_name : existing_names) |
| 117 | { |
| 118 | if (other_name == shortened_name) |
| 119 | { |
| 120 | exists = true; |
| 121 | break; |
| 122 | } |
| 123 | } |
| 124 | if (!exists) |
| 125 | { |
| 126 | existing_names.push_back(shortened_name); |
| 127 | } |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | for (std::string name : existing_names) |
| 132 | { |
| 133 | create_nonexistent_targets(name); |
| 134 | } |
88 | 135 | } |
89 | 136 | |
90 | | void target_manager::update_window_count(uint32_t count) |
| 137 | void target_manager::rebuild_guest_targets(int32_t screen) |
91 | 138 | { |
92 | | if (count != m_window_count) |
| 139 | std::vector<bgfx_target*> to_resize; |
| 140 | for (std::pair<std::string, bgfx_target*> target : m_targets) { |
| 141 | bgfx_target* target_ptr = target.second; |
| 142 | if (target_ptr == nullptr) { |
| 143 | continue; |
| 144 | } |
| 145 | bool is_guest = target_ptr->style() == TARGET_STYLE_GUEST; |
| 146 | bool is_desired_screen = target_ptr->index() == screen || target_ptr->index() == -1; |
| 147 | std::string name = target_ptr->name(); |
| 148 | bool is_indexed = (name[name.length() - 1] & 0xf0) == 0x30; |
| 149 | if (is_guest && is_desired_screen && is_indexed) { |
| 150 | to_resize.push_back(target.second); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | for (bgfx_target* target : to_resize) { |
| 155 | std::string name = target->name(); |
| 156 | const bgfx::TextureFormat::Enum format = target->format(); |
| 157 | const bool double_buffered = target->double_buffered(); |
| 158 | const bool filter = target->filter(); |
| 159 | const uint32_t prescale_x = target->prescale_x(); |
| 160 | const uint32_t prescale_y = target->prescale_y(); |
| 161 | delete target; |
| 162 | |
| 163 | const uint16_t width = m_guest_width[screen]; |
| 164 | const uint16_t height = m_guest_height[screen]; |
| 165 | const bool init = width > 0 && height > 0; |
| 166 | m_targets[name] = new bgfx_target(name, format, width, height, prescale_x, prescale_y, TARGET_STYLE_GUEST, screen, double_buffered, filter, init); |
| 167 | m_textures.add_provider(name, m_targets[name]); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | void target_manager::update_screen_count(uint32_t count) |
| 172 | { |
| 173 | if (count != m_screen_count) |
93 | 174 | { |
94 | | m_window_count = count; |
95 | | rebuild_outputs(); |
| 175 | uint32_t old_count = m_screen_count; |
| 176 | m_screen_count = count; |
| 177 | if (m_screen_count > old_count) |
| 178 | { |
| 179 | create_nonexistent_targets("output"); |
| 180 | create_nonexistent_targets("previous"); |
| 181 | } |
96 | 182 | } |
97 | 183 | } |
98 | 184 | |
99 | | void target_manager::rebuild_outputs() |
| 185 | void target_manager::create_nonexistent_targets(std::string name) |
100 | 186 | { |
101 | | for (uint32_t i = 0; i < m_window_count; i++) |
| 187 | bool double_buffered = true; |
| 188 | bool filter = true; |
| 189 | if (m_targets[name + "0"] != nullptr) |
102 | 190 | { |
103 | | rebuild_target("output" + std::to_string(i)); |
104 | | rebuild_target("previous" + std::to_string(i)); |
| 191 | double_buffered = m_targets[name + "0"]->double_buffered(); |
| 192 | filter = m_targets[name + "0"]->filter(); |
105 | 193 | } |
| 194 | |
| 195 | for (uint32_t screen = 0; screen < m_screen_count; screen++) |
| 196 | { |
| 197 | create_guest_if_nonexistent(name, screen, double_buffered, filter); |
| 198 | } |
106 | 199 | } |
107 | 200 | |
108 | | void target_manager::rebuild_target(std::string name) |
| 201 | bool target_manager::create_guest_if_nonexistent(std::string name, int32_t screen, bool double_buffered, bool filter) |
109 | 202 | { |
110 | | bgfx_target* target = m_targets[name]; |
111 | | if (target != nullptr) { |
112 | | delete target; |
| 203 | std::string full_name = name + std::to_string(screen); |
| 204 | if (m_targets[full_name] != nullptr) |
| 205 | { |
| 206 | return false; |
113 | 207 | } |
114 | | m_targets[name] = new bgfx_target(name, bgfx::TextureFormat::RGBA8, m_guest_width, m_guest_height, m_options.bgfx_prescale_x(), m_options.bgfx_prescale_y(), TARGET_STYLE_GUEST, true, true); |
115 | | m_textures.add_provider(name, m_targets[name]); |
| 208 | |
| 209 | bool init = m_guest_width[screen] > 0 && m_guest_height[screen] > 0; |
| 210 | m_targets[full_name] = new bgfx_target(full_name, bgfx::TextureFormat::RGBA8, m_guest_width[screen], m_guest_height[screen], m_options.bgfx_prescale_x(), m_options.bgfx_prescale_y(), TARGET_STYLE_GUEST, screen, double_buffered, filter, init); |
| 211 | return true; |
116 | 212 | } |
| | No newline at end of file |
branches/bgfx_shader/src/osd/modules/render/bgfx/targetmanager.h
r255105 | r255106 | |
26 | 26 | |
27 | 27 | class target_manager { |
28 | 28 | public: |
29 | | target_manager(osd_options& options, texture_manager& textures) : m_textures(textures), m_options(options), m_guest_width(0), m_guest_height(0), m_window_count(0) { } |
| 29 | target_manager(osd_options& options, texture_manager& textures); |
30 | 30 | ~target_manager(); |
31 | 31 | |
32 | 32 | bgfx_target* create_target(std::string name, bgfx::TextureFormat::Enum format, uint32_t width, uint32_t height, uint32_t prescale_x, uint32_t prescale_y, uint32_t style, bool double_buffer, bool filter, bool output); |
33 | 33 | bgfx_target* create_backbuffer(void *handle, uint32_t width, uint32_t height); |
34 | 34 | |
35 | | void update_guest_targets(uint16_t width, uint16_t height); |
36 | | void update_window_count(uint32_t count); |
| 35 | void update_guest_targets(int32_t screen, uint16_t width, uint16_t height); |
| 36 | void update_screen_count(uint32_t count); |
37 | 37 | |
38 | 38 | // Getters |
39 | 39 | bgfx_target* target(std::string name); |
40 | | uint16_t guest_width() const { return m_guest_width; } |
41 | | uint16_t guest_height() const { return m_guest_height; } |
| 40 | uint16_t guest_width(int32_t screen) const { return m_guest_width[screen]; } |
| 41 | uint16_t guest_height(int32_t screen) const { return m_guest_height[screen]; } |
42 | 42 | |
43 | 43 | private: |
| 44 | void rebuild_guest_targets(int32_t screen); |
44 | 45 | void rebuild_outputs(); |
45 | | void rebuild_target(std::string name); |
| 46 | void ensure_guest_targets(); |
| 47 | void create_nonexistent_targets(std::string name); |
| 48 | bool create_guest_if_nonexistent(std::string name, int32_t screen, bool double_buffered, bool filter); |
46 | 49 | |
47 | 50 | std::map<std::string, bgfx_target*> m_targets; |
48 | 51 | texture_manager& m_textures; |
49 | 52 | osd_options& m_options; |
50 | 53 | |
51 | | uint16_t m_guest_width; |
52 | | uint16_t m_guest_height; |
53 | | uint32_t m_window_count; |
| 54 | uint16_t *m_guest_width; |
| 55 | uint16_t *m_guest_height; |
| 56 | uint32_t m_screen_count; |
| 57 | |
| 58 | static const int32_t MAX_SCREENS; |
54 | 59 | }; |
55 | 60 | |
56 | 61 | #endif // __DRAWBGFX_TARGET_MANAGER__ |
branches/bgfx_shader/src/osd/modules/render/drawbgfx.cpp
r255105 | r255106 | |
331 | 331 | vertex[5].m_v = v[0]; |
332 | 332 | } |
333 | 333 | |
334 | | void renderer_bgfx::process_screen_quad(int view, render_primitive* prim) |
| 334 | void renderer_bgfx::process_screen_quad(int screen, render_primitive* prim) |
335 | 335 | { |
336 | 336 | uint32_t texture_flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP; |
337 | 337 | if (video_config.filter == 0) |
r255105 | r255106 | |
348 | 348 | bgfx_texture *texture = new bgfx_texture("screen", bgfx::TextureFormat::RGBA8, tex_width, tex_height, mem); |
349 | 349 | m_textures->add_provider("screen", texture); |
350 | 350 | |
351 | | int screens = 0; |
352 | | screen_device_iterator iter(window().machine().root_device()); |
353 | | for (const screen_device *screen = iter.first(); screen != nullptr; screen = iter.next()) |
354 | | { |
355 | | screens++; |
356 | | } |
357 | | m_targets->update_guest_targets(tex_width, tex_height); |
358 | | m_targets->update_window_count(screens); |
| 351 | m_targets->update_guest_targets(screen, tex_width, tex_height); |
359 | 352 | |
360 | | m_screen_chain->process(prim, view, view / m_screen_chain->applicable_passes(), *m_textures, window(), get_blend_state(PRIMFLAG_GET_BLENDMODE(prim->flags))); |
| 353 | m_screen_chain->process(prim, screen * m_screen_chain->applicable_passes(), screen, *m_textures, window(), get_blend_state(PRIMFLAG_GET_BLENDMODE(prim->flags))); |
361 | 354 | |
362 | 355 | m_textures->add_provider("screen", nullptr); |
363 | 356 | delete texture; |
r255105 | r255106 | |
744 | 737 | // process |
745 | 738 | render_primitive *prim = window().m_primlist->first(); |
746 | 739 | |
747 | | int seen = 0; |
| 740 | int screens = 0; |
| 741 | screen_device_iterator iter(window().machine().root_device()); |
| 742 | for (const screen_device *screen = iter.first(); screen != nullptr; screen = iter.next()) { |
| 743 | screens++; |
| 744 | } |
| 745 | m_targets->update_screen_count(screens); |
| 746 | |
| 747 | int seen_screen_quads = 0; |
748 | 748 | while (prim != nullptr) |
749 | 749 | { |
750 | 750 | if (PRIMFLAG_GET_SCREENTEX(prim->flags)) |
751 | 751 | { |
752 | | process_screen_quad(m_screen_chain->applicable_passes() * seen, prim); |
753 | | seen++; |
| 752 | process_screen_quad(seen_screen_quads, prim); |
| 753 | seen_screen_quads++; |
754 | 754 | } |
755 | 755 | prim = prim->next(); |
756 | 756 | } |
757 | 757 | |
758 | 758 | window().m_primlist->release_lock(); |
759 | 759 | |
760 | | uint32_t total_passes = seen * m_screen_chain->applicable_passes(); |
| 760 | uint32_t total_passes = seen_screen_quads * m_screen_chain->applicable_passes(); |
761 | 761 | bgfx::setViewFrameBuffer(total_passes, BGFX_INVALID_HANDLE); |
762 | 762 | |
763 | 763 | return total_passes; |