all repos — mgba @ 6604afb670535c2a37b3a93ae48ab715b0ec16a7

mGBA Game Boy Advance Emulator

src/platform/qt/ShaderSelector.cpp (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "ShaderSelector.h"
  7
  8#include "Display.h"
  9
 10#include <QCheckBox>
 11#include <QDoubleSpinBox>
 12#include <QFormLayout>
 13#include <QGridLayout>
 14#include <QSpinBox>
 15
 16extern "C" {
 17#include "platform/video-backend.h"
 18
 19#if !defined(_WIN32) || defined(USE_EPOXY)
 20#include "platform/opengl/gles2.h"
 21#endif
 22}
 23
 24using namespace QGBA;
 25
 26ShaderSelector::ShaderSelector(Display* display, QWidget* parent)
 27	: QDialog(parent)
 28	, m_display(display)
 29{
 30	m_ui.setupUi(this);
 31
 32	refreshShaders();
 33}
 34
 35ShaderSelector::~ShaderSelector() {
 36	clear();
 37}
 38
 39void ShaderSelector::clear() {
 40	m_ui.shaderName->setText(tr("No shader active"));
 41	m_ui.description->clear();
 42	m_ui.author->clear();
 43
 44	while (QWidget* page = m_ui.passes->widget(0)) {
 45		m_ui.passes->removeTab(0);
 46		delete page;
 47	}
 48}
 49
 50void ShaderSelector::refreshShaders() {
 51	clear();
 52	m_shaders = m_display->shaders();
 53	if (!m_shaders) {
 54		return;
 55	}
 56	m_ui.shaderName->setText(m_shaders->name);
 57	m_ui.description->setText(m_shaders->description);
 58	m_ui.author->setText(tr("by %1").arg(m_shaders->author));
 59
 60#if !defined(_WIN32) || defined(USE_EPOXY)
 61	GBAGLES2Shader* shaders = static_cast<GBAGLES2Shader*>(m_shaders->passes);
 62	for (size_t p = 0; p < m_shaders->nPasses; ++p) {
 63		QWidget* page = new QWidget;
 64		QFormLayout* layout = new QFormLayout;
 65		page->setLayout(layout);
 66		for (size_t u = 0 ; u < shaders[p].nUniforms; ++u) {
 67			QGridLayout* settings = new QGridLayout;
 68			GBAGLES2Uniform* uniform = &shaders[p].uniforms[u];
 69			switch (uniform->type) {
 70			case GL_FLOAT:
 71				addUniform(settings, &uniform->value.f, uniform->min.f, uniform->max.f, 0, 0);
 72				break;
 73			case GL_FLOAT_VEC2:
 74				addUniform(settings, &uniform->value.fvec2[0], uniform->min.fvec2[0], uniform->max.fvec2[0], 0, 0);
 75				addUniform(settings, &uniform->value.fvec2[1], uniform->min.fvec2[1], uniform->max.fvec2[1], 0, 1);
 76				break;
 77			case GL_FLOAT_VEC3:
 78				addUniform(settings, &uniform->value.fvec3[0], uniform->min.fvec3[0], uniform->max.fvec3[0], 0, 0);
 79				addUniform(settings, &uniform->value.fvec3[1], uniform->min.fvec3[1], uniform->max.fvec3[1], 0, 1);
 80				addUniform(settings, &uniform->value.fvec3[2], uniform->min.fvec3[2], uniform->max.fvec3[2], 0, 2);
 81				break;
 82			case GL_FLOAT_VEC4:
 83				addUniform(settings, &uniform->value.fvec4[0], uniform->min.fvec4[0], uniform->max.fvec4[0], 0, 0);
 84				addUniform(settings, &uniform->value.fvec4[1], uniform->min.fvec4[1], uniform->max.fvec4[1], 0, 1);
 85				addUniform(settings, &uniform->value.fvec4[2], uniform->min.fvec4[2], uniform->max.fvec4[2], 0, 2);
 86				addUniform(settings, &uniform->value.fvec4[3], uniform->min.fvec4[3], uniform->max.fvec4[3], 0, 3);
 87				break;
 88			case GL_INT:
 89				addUniform(settings, &uniform->value.i, uniform->min.i, uniform->max.i, 0, 0);
 90				break;
 91			case GL_INT_VEC2:
 92				addUniform(settings, &uniform->value.ivec2[0], uniform->min.ivec2[0], uniform->max.ivec2[0], 0, 0);
 93				addUniform(settings, &uniform->value.ivec2[1], uniform->min.ivec2[1], uniform->max.ivec2[1], 0, 1);
 94				break;
 95			case GL_INT_VEC3:
 96				addUniform(settings, &uniform->value.ivec3[0], uniform->min.ivec3[0], uniform->max.ivec3[0], 0, 0);
 97				addUniform(settings, &uniform->value.ivec3[1], uniform->min.ivec3[1], uniform->max.ivec3[1], 0, 1);
 98				addUniform(settings, &uniform->value.ivec3[2], uniform->min.ivec3[2], uniform->max.ivec3[2], 0, 2);
 99				break;
100			case GL_INT_VEC4:
101				addUniform(settings, &uniform->value.ivec4[0], uniform->min.ivec4[0], uniform->max.ivec4[0], 0, 0);
102				addUniform(settings, &uniform->value.ivec4[1], uniform->min.ivec4[1], uniform->max.ivec4[1], 0, 1);
103				addUniform(settings, &uniform->value.ivec4[2], uniform->min.ivec4[2], uniform->max.ivec4[2], 0, 2);
104				addUniform(settings, &uniform->value.ivec4[3], uniform->min.ivec4[3], uniform->max.ivec4[3], 0, 3);
105				break;
106			}
107			layout->addRow(shaders[p].uniforms[u].readableName, settings);
108		}
109		m_ui.passes->addTab(page, tr("Pass %1").arg(p + 1));
110	}
111#endif
112}
113
114void ShaderSelector::addUniform(QGridLayout* settings, float* value, float min, float max, int y, int x) {
115	QDoubleSpinBox* f = new QDoubleSpinBox;
116	f->setDecimals(3);
117	if (min < max) {
118		f->setMinimum(min);
119		f->setMaximum(max);
120	}
121	f->setValue(*value);
122	f->setSingleStep(0.001);
123	f->setAccelerated(true);
124	settings->addWidget(f, y, x);
125	connect(f, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [value](double v) {
126		*value = v;
127	});
128}
129
130void ShaderSelector::addUniform(QGridLayout* settings, int* value, int min, int max, int y, int x) {
131	QSpinBox* i = new QSpinBox;
132	if (min < max) {
133		i->setMinimum(min);
134		i->setMaximum(max);
135	}
136	i->setValue(*value);
137	i->setSingleStep(1);
138	i->setAccelerated(true);
139	settings->addWidget(i, y, x);
140	connect(i, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [value](int v) {
141		*value = v;
142	});
143}