@@ -40,7 +40,7 @@ OGLVideoDevice::~OGLVideoDevice() {
40
40
glDeleteVertexArrays (1 , &quad_vao);
41
41
glDeleteBuffers (1 , &quad_vbo);
42
42
glDeleteFramebuffers (1 , &fbo);
43
- glDeleteTextures (4 , texture);
43
+ glDeleteTextures (3 , texture);
44
44
}
45
45
46
46
void OGLVideoDevice::Initialize () {
@@ -59,7 +59,7 @@ void OGLVideoDevice::Initialize() {
59
59
60
60
// Create three textures and a framebuffer for postprocessing.
61
61
glGenFramebuffers (1 , &fbo);
62
- glGenTextures (4 , texture);
62
+ glGenTextures (3 , texture);
63
63
64
64
glEnable (GL_FRAMEBUFFER_SRGB);
65
65
@@ -106,20 +106,6 @@ void OGLVideoDevice::CreateShaderPrograms() {
106
106
107
107
ReleaseShaderPrograms ();
108
108
109
- // xBRZ freescale upsampling filter (two passes)
110
- if (video.filter == Video::Filter::xBRZ) {
111
- auto [success0, program0] = CompileProgram (xbrz0_vert, xbrz0_frag);
112
- auto [success1, program1] = CompileProgram (xbrz1_vert, xbrz1_frag);
113
-
114
- if (success0 && success1) {
115
- programs.push_back (program0);
116
- programs.push_back (program1);
117
- } else {
118
- if (success0) glDeleteProgram (program0);
119
- if (success1) glDeleteProgram (program1);
120
- }
121
- }
122
-
123
109
// Color correction pass
124
110
switch (video.color ) {
125
111
case Video::Color::higan: {
@@ -147,29 +133,56 @@ void OGLVideoDevice::CreateShaderPrograms() {
147
133
}
148
134
149
135
// Output pass (final)
150
- auto [success, program] = CompileProgram (output_vert, output_frag);
151
- if (success) {
152
- programs.push_back (program);
136
+ switch (video.filter ) {
137
+ // xBRZ freescale upsampling filter (two passes)
138
+ case Video::Filter::xBRZ: {
139
+ auto [success0, program0] = CompileProgram (xbrz0_vert, xbrz0_frag);
140
+ auto [success1, program1] = CompileProgram (xbrz1_vert, xbrz1_frag);
141
+
142
+ if (success0 && success1) {
143
+ programs.push_back (program0);
144
+ programs.push_back (program1);
145
+ } else {
146
+ if (success0) glDeleteProgram (program0);
147
+ if (success1) glDeleteProgram (program1);
148
+ }
149
+ break ;
150
+ }
151
+ // Plain linear/nearest output.
152
+ default : {
153
+ auto [success, program] = CompileProgram (output_vert, output_frag);
154
+ if (success) {
155
+ programs.push_back (program);
156
+ }
157
+ break ;
158
+ }
153
159
}
154
160
161
+ UpdateShaderUniforms ();
162
+ }
163
+
164
+ void OGLVideoDevice::UpdateShaderUniforms () {
155
165
// Set constant shader uniforms.
156
- for (auto program : programs) {
166
+ for (const auto program : programs) {
157
167
glUseProgram (program);
158
168
159
- auto screen_map = glGetUniformLocation (program, " u_screen_map" );
169
+ const auto screen_map = glGetUniformLocation (program, " u_screen_map" );
160
170
if (screen_map != -1 ) {
161
171
glUniform1i (screen_map, 0 );
162
172
}
163
173
164
- auto history_map = glGetUniformLocation (program, " u_history_map" );
174
+ const auto history_map = glGetUniformLocation (program, " u_history_map" );
165
175
if (history_map != -1 ) {
166
176
glUniform1i (history_map, 1 );
167
177
}
168
178
169
- auto source_map = glGetUniformLocation (program, " u_source_map " );
170
- if (source_map != -1 ) {
171
- glUniform1i (source_map , 2 );
179
+ const auto info_map = glGetUniformLocation (program, " u_info_map " );
180
+ if (info_map != -1 ) {
181
+ glUniform1i (info_map , 2 );
172
182
}
183
+
184
+ const auto output_size = glGetUniformLocation (program, " u_output_size" );
185
+ glUniform2f (output_size, view_width, view_height);
173
186
}
174
187
}
175
188
@@ -233,65 +246,59 @@ void OGLVideoDevice::SetViewport(int x, int y, int width, int height) {
233
246
view_y = y;
234
247
view_width = width;
235
248
view_height = height;
249
+
250
+ UpdateShaderUniforms ();
236
251
}
237
252
238
253
void OGLVideoDevice::SetDefaultFBO (GLuint fbo) {
239
254
default_fbo = fbo;
240
255
}
241
256
242
257
void OGLVideoDevice::Draw (u32 * buffer) {
243
- int target = 0 ;
258
+ // Bind LCD history map
259
+ glActiveTexture (GL_TEXTURE1);
260
+ glBindTexture (GL_TEXTURE_2D, texture[2 ]);
244
261
245
262
// Update and bind LCD screen texture
246
263
glActiveTexture (GL_TEXTURE0);
247
- glBindTexture (GL_TEXTURE_2D, texture[3 ]);
264
+ glBindTexture (GL_TEXTURE_2D, texture[0 ]);
248
265
glTexSubImage2D (
249
266
GL_TEXTURE_2D, 0 , 0 , 0 , 240 , 160 , GL_BGRA, GL_UNSIGNED_BYTE, buffer
250
267
);
251
268
252
- // Bind LCD history map
253
- glActiveTexture (GL_TEXTURE1);
254
- glBindTexture (GL_TEXTURE_2D, texture[2 ]);
255
-
256
- // Bind LCD source map
257
- glActiveTexture (GL_TEXTURE2);
258
- glBindTexture (GL_TEXTURE_2D, texture[3 ]);
259
-
260
- auto program_count = programs.size ();
261
-
262
269
glViewport (0 , 0 , 240 , 160 );
263
270
glBindVertexArray (quad_vao);
271
+ glBindFramebuffer (GL_FRAMEBUFFER, fbo);
264
272
265
- if (program_count <= 2 ) {
266
- target = 2 ;
267
- }
273
+ for (auto pass_iter = programs.begin (); pass_iter != programs.end (); ++pass_iter) {
274
+ glUseProgram (*pass_iter);
268
275
269
- for (int i = 0 ; i < program_count; i++) {
270
- glUseProgram (programs[i]);
276
+ if (pass_iter != programs.begin ()) {
277
+ // Swap input and output textures.
278
+ std::swap (texture[0 ], texture[1 ]);
279
+ }
280
+ if (pass_iter == std::prev (programs.end ())) {
281
+ if (config->video .filter == Video::Filter::xBRZ) {
282
+ glActiveTexture (GL_TEXTURE2);
283
+ glBindTexture (GL_TEXTURE_2D, texture[0 ]);
284
+ glActiveTexture (GL_TEXTURE0);
285
+ glBindTexture (GL_TEXTURE_2D, texture[1 ]);
286
+ glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1 ], 0 );
287
+ } else {
288
+ glBindTexture (GL_TEXTURE_2D, texture[0 ]);
289
+ }
290
+ glActiveTexture (GL_TEXTURE1);
291
+ glReadBuffer (GL_COLOR_ATTACHMENT0);
292
+ glCopyTexSubImage2D (GL_TEXTURE_2D, 0 , 0 , 0 , 0 , 0 , 240 , 160 );
271
293
272
- if (i == program_count - 1 ) {
273
- glViewport (view_x, view_y, view_width, view_height);
274
294
glBindFramebuffer (GL_FRAMEBUFFER, default_fbo);
295
+ glViewport (view_x, view_y, view_width, view_height);
275
296
} else {
276
- glBindFramebuffer (GL_FRAMEBUFFER, fbo );
277
- glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[target ], 0 );
297
+ glBindTexture (GL_TEXTURE_2D, texture[ 0 ] );
298
+ glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1 ], 0 );
278
299
}
279
300
280
301
glDrawArrays (GL_TRIANGLES, 0 , 6 );
281
-
282
- // Output of the current pass is the input for the next pass.
283
- glActiveTexture (GL_TEXTURE0);
284
- glBindTexture (GL_TEXTURE_2D, texture[target]);
285
-
286
- if (i == program_count - 3 ) {
287
- /* The next pass is the next-to-last pass, before we render to screen.
288
- * Render that pass into a separate texture, so that it can be
289
- * used in the next frame to calculate LCD ghosting.
290
- */
291
- target = 2 ;
292
- } else {
293
- target ^= 1 ;
294
- }
295
302
}
296
303
}
297
304
0 commit comments