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}