summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/render/bgfx/chainreader.cpp
blob: 0892523faa66e9cb56eebe628250896f1e62c8a9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
//============================================================
//
//  chainreader.cpp - BGFX chain JSON reader
//
//============================================================

#include <string>
#include <vector>
#include <map>

#include "emu.h"
#include <modules/lib/osdobj_common.h>

#include "chain.h"
#include "sliderreader.h"
#include "paramreader.h"
#include "chainentryreader.h"
#include "targetmanager.h"
#include "chainreader.h"
#include "target.h"
#include "slider.h"
#include "parameter.h"

const chain_reader::string_to_enum chain_reader::STYLE_NAMES[chain_reader::STYLE_COUNT] = {
	{ "guest",  TARGET_STYLE_GUEST },
	{ "native", TARGET_STYLE_NATIVE },
	{ "custom",	TARGET_STYLE_CUSTOM }
};

bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix, osd_options& options, running_machine& machine, uint32_t window_index, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t screen_width, uint32_t screen_height)
{
	validate_parameters(value, prefix);

	std::string name = value["name"].GetString();
	std::string author = value["author"].GetString();

	// Parse sliders
	std::vector<bgfx_slider*> sliders;
	if (value.HasMember("sliders"))
	{
		const Value& slider_array = value["sliders"];
		for (UINT32 i = 0; i < slider_array.Size(); i++)
		{
            std::vector<bgfx_slider*> expanded_sliders = slider_reader::read_from_value(slider_array[i], prefix + "sliders[" + std::to_string(i) + "]: ", machine, window_index);
            for (bgfx_slider* slider : expanded_sliders)
            {
                sliders.push_back(slider);
            }
		}
	}

	// Map sliders
	std::map<std::string, bgfx_slider*> slider_map;
	for (bgfx_slider* slider : sliders)
	{
		slider_map[slider->name()] = slider;
	}

	// Parse parameters
	std::vector<bgfx_parameter*> parameters;
	if (value.HasMember("parameters"))
	{
        READER_ASSERT(value["parameters"].IsArray(), (prefix + "Value 'parameters' must be an array\n").c_str());
		const Value& param_array = value["parameters"];
		for (UINT32 i = 0; i < param_array.Size(); i++)
		{
			parameters.push_back(parameter_reader::read_from_value(param_array[i], prefix + "parameters[" + std::to_string(i) + "]; ", window_index));
		}
	}

	// Map parameters
	std::map<std::string, bgfx_parameter*> param_map;
	for (bgfx_parameter* param : parameters)
	{
		param_map[param->name()] = param;
	}

	// Create targets
	if (value.HasMember("targets"))
	{
        READER_ASSERT(value["targets"].IsArray(), (prefix + "Value 'targets' must be an array\n").c_str());
		const Value& target_array = value["targets"];
        // TODO: Move into its own reader
		for (UINT32 i = 0; i < target_array.Size(); i++)
		{
            READER_ASSERT(target_array[i].HasMember("name"), (prefix + "targets[" + std::to_string(i) + "]: Must have string value 'name'\n").c_str());
            READER_ASSERT(target_array[i]["name"].IsString(), (prefix + "targets[" + std::to_string(i) + "]: Value 'name' must be a string\n").c_str());
            READER_ASSERT(target_array[i].HasMember("mode"), (prefix + "targets[" + std::to_string(i) + "]: Must have string enum 'mode'\n").c_str());
            READER_ASSERT(target_array[i]["mode"].IsString(), (prefix + "targets[" + std::to_string(i) + "]: Value 'mode' must be a string (what screens does this apply to?)\n").c_str());
            READER_ASSERT(!target_array[i].HasMember("bilinear") || target_array[i]["bilinear"].IsBool(), (prefix + "targets[" + std::to_string(i) + "]: Value 'bilinear' must be a boolean\n").c_str());
            READER_ASSERT(!target_array[i].HasMember("doublebuffer") || target_array[i]["doublebuffer"].IsBool(), (prefix + "targets[" + std::to_string(i) + "]: Value 'doublebuffer' must be a boolean\n").c_str());
            READER_ASSERT(!target_array[i].HasMember("prescale") || target_array[i]["prescale"].IsBool(), (prefix + "targets[" + std::to_string(i) + "]: Value 'prescale' must be a boolean\n").c_str());

            std::string target_name = target_array[i]["name"].GetString();
			uint32_t mode = uint32_t(get_enum_from_value(target_array[i], "mode", TARGET_STYLE_NATIVE, STYLE_NAMES, STYLE_COUNT));
			bool bilinear = get_bool(target_array[i], "bilinear", true);
			bool double_buffer = get_bool(target_array[i], "doublebuffer", true);
            bool prescale = get_bool(target_array[i], "prescale", false);

			uint16_t width = 0;
			uint16_t height = 0;
			switch (mode)
			{
				case TARGET_STYLE_GUEST:
					width = targets.guest_width();
					height = targets.guest_height();
					break;
				case TARGET_STYLE_NATIVE:
					width = screen_width;
					height = screen_height;
					break;
				case TARGET_STYLE_CUSTOM:
                    READER_ASSERT(target_array[i].HasMember("width"), (prefix + "Target '" + target_name + "': Must have numeric value 'width'\n").c_str());
                    READER_ASSERT(target_array[i]["width"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'width' must be a number\n").c_str());
                    READER_ASSERT(target_array[i].HasMember("height"), (prefix + "Target '" + target_name + "': Must have numeric value 'height'\n").c_str());
                    READER_ASSERT(target_array[i]["height"].IsNumber(), (prefix + "Target '" + target_name + "': Value 'height' must be a number\n").c_str());
					width = uint32_t(target_array[i]["width"].GetDouble());
					height = uint32_t(target_array[i]["height"].GetDouble());
					break;
			}

            uint32_t prescale_x = 1;
            uint32_t prescale_y = 1;
            if (prescale)
            {
                prescale_x = options.bgfx_prescale_x();
                prescale_y = options.bgfx_prescale_y();
            }

			targets.create_target(target_name, bgfx::TextureFormat::RGBA8, width, height, prescale_x, prescale_y, mode, double_buffer, bilinear);
		}
	}

    // Parse chain entries
    std::vector<bgfx_chain_entry*> entries;
    if (value.HasMember("passes"))
    {
        const Value& entry_array = value["passes"];
        for (UINT32 i = 0; i < entry_array.Size(); i++)
        {
            entries.push_back(chain_entry_reader::read_from_value(entry_array[i], prefix + "passes[" + std::to_string(i) + "]: ", options, textures, targets, effects, slider_map, param_map));
        }
    }

    std::string output = value["output"].GetString();

    return new bgfx_chain(name, author, sliders, parameters, entries, output);
}

void chain_reader::validate_parameters(const Value& value, std::string prefix)
{
    READER_ASSERT(value.HasMember("name"), (prefix + "Must have string value 'name'\n").c_str());
    READER_ASSERT(value["name"].IsString(), (prefix + "Value 'name' must be a string\n").c_str());
    READER_ASSERT(value.HasMember("author"), (prefix + "Must have string value 'author'\n").c_str());
    READER_ASSERT(value["author"].IsString(), (prefix + "Value 'author' must be a string\n").c_str());
    READER_ASSERT(value.HasMember("passes"), (prefix + "Must have array value 'passes'\n").c_str());
    READER_ASSERT(value["passes"].IsArray(), (prefix + "Value 'passes' must be an array\n").c_str());
    READER_ASSERT(value.HasMember("output"), (prefix + "Must have string value 'output'\n").c_str());
    READER_ASSERT(value["output"].IsString(), (prefix + "Value 'output' must be a string\n").c_str());
}