1 // Copyright 2015 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #include <glad/glad.h>
6 #include "common/common_funcs.h"
7 #include "common/logging/log.h"
8 #include "video_core/renderer_opengl/gl_state.h"
9 #include "video_core/renderer_opengl/gl_vars.h"
10 
11 namespace OpenGL {
12 
13 OpenGLState OpenGLState::cur_state;
14 
OpenGLState()15 OpenGLState::OpenGLState() {
16     // These all match default OpenGL values
17     cull.enabled = false;
18     cull.mode = GL_BACK;
19     cull.front_face = GL_CCW;
20 
21     depth.test_enabled = false;
22     depth.test_func = GL_LESS;
23     depth.write_mask = GL_TRUE;
24 
25     color_mask.red_enabled = GL_TRUE;
26     color_mask.green_enabled = GL_TRUE;
27     color_mask.blue_enabled = GL_TRUE;
28     color_mask.alpha_enabled = GL_TRUE;
29 
30     stencil.test_enabled = false;
31     stencil.test_func = GL_ALWAYS;
32     stencil.test_ref = 0;
33     stencil.test_mask = 0xFF;
34     stencil.write_mask = 0xFF;
35     stencil.action_depth_fail = GL_KEEP;
36     stencil.action_depth_pass = GL_KEEP;
37     stencil.action_stencil_fail = GL_KEEP;
38 
39     blend.enabled = true;
40     blend.rgb_equation = GL_FUNC_ADD;
41     blend.a_equation = GL_FUNC_ADD;
42     blend.src_rgb_func = GL_ONE;
43     blend.dst_rgb_func = GL_ZERO;
44     blend.src_a_func = GL_ONE;
45     blend.dst_a_func = GL_ZERO;
46     blend.color.red = 0.0f;
47     blend.color.green = 0.0f;
48     blend.color.blue = 0.0f;
49     blend.color.alpha = 0.0f;
50 
51     logic_op = GL_COPY;
52 
53     for (auto& texture_unit : texture_units) {
54         texture_unit.texture_2d = 0;
55         texture_unit.sampler = 0;
56     }
57 
58     texture_cube_unit.texture_cube = 0;
59     texture_cube_unit.sampler = 0;
60 
61     texture_buffer_lut_lf.texture_buffer = 0;
62     texture_buffer_lut_rg.texture_buffer = 0;
63     texture_buffer_lut_rgba.texture_buffer = 0;
64 
65     image_shadow_buffer = 0;
66     image_shadow_texture_px = 0;
67     image_shadow_texture_nx = 0;
68     image_shadow_texture_py = 0;
69     image_shadow_texture_ny = 0;
70     image_shadow_texture_pz = 0;
71     image_shadow_texture_nz = 0;
72 
73     draw.read_framebuffer = 0;
74     draw.draw_framebuffer = 0;
75     draw.vertex_array = 0;
76     draw.vertex_buffer = 0;
77     draw.uniform_buffer = 0;
78     draw.shader_program = 0;
79     draw.program_pipeline = 0;
80 
81     scissor.enabled = false;
82     scissor.x = 0;
83     scissor.y = 0;
84     scissor.width = 0;
85     scissor.height = 0;
86 
87     viewport.x = 0;
88     viewport.y = 0;
89     viewport.width = 0;
90     viewport.height = 0;
91 
92     clip_distance = {};
93 
94     renderbuffer = 0;
95 }
96 
Apply() const97 void OpenGLState::Apply() const {
98     // Culling
99     if (cull.enabled != cur_state.cull.enabled) {
100         if (cull.enabled) {
101             glEnable(GL_CULL_FACE);
102         } else {
103             glDisable(GL_CULL_FACE);
104         }
105     }
106 
107     if (cull.mode != cur_state.cull.mode) {
108         glCullFace(cull.mode);
109     }
110 
111     if (cull.front_face != cur_state.cull.front_face) {
112         glFrontFace(cull.front_face);
113     }
114 
115     // Depth test
116     if (depth.test_enabled != cur_state.depth.test_enabled) {
117         if (depth.test_enabled) {
118             glEnable(GL_DEPTH_TEST);
119         } else {
120             glDisable(GL_DEPTH_TEST);
121         }
122     }
123 
124     if (depth.test_func != cur_state.depth.test_func) {
125         glDepthFunc(depth.test_func);
126     }
127 
128     // Depth mask
129     if (depth.write_mask != cur_state.depth.write_mask) {
130         glDepthMask(depth.write_mask);
131     }
132 
133     // Color mask
134     if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
135         color_mask.green_enabled != cur_state.color_mask.green_enabled ||
136         color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
137         color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
138         glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled,
139                     color_mask.alpha_enabled);
140     }
141 
142     // Stencil test
143     if (stencil.test_enabled != cur_state.stencil.test_enabled) {
144         if (stencil.test_enabled) {
145             glEnable(GL_STENCIL_TEST);
146         } else {
147             glDisable(GL_STENCIL_TEST);
148         }
149     }
150 
151     if (stencil.test_func != cur_state.stencil.test_func ||
152         stencil.test_ref != cur_state.stencil.test_ref ||
153         stencil.test_mask != cur_state.stencil.test_mask) {
154         glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask);
155     }
156 
157     if (stencil.action_depth_fail != cur_state.stencil.action_depth_fail ||
158         stencil.action_depth_pass != cur_state.stencil.action_depth_pass ||
159         stencil.action_stencil_fail != cur_state.stencil.action_stencil_fail) {
160         glStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail,
161                     stencil.action_depth_pass);
162     }
163 
164     // Stencil mask
165     if (stencil.write_mask != cur_state.stencil.write_mask) {
166         glStencilMask(stencil.write_mask);
167     }
168 
169     // Blending
170     if (blend.enabled != cur_state.blend.enabled) {
171         if (blend.enabled) {
172             glEnable(GL_BLEND);
173         } else {
174             glDisable(GL_BLEND);
175         }
176 
177         // GLES does not support glLogicOp
178         if (!GLES) {
179             if (blend.enabled) {
180                 glDisable(GL_COLOR_LOGIC_OP);
181             } else {
182                 glEnable(GL_COLOR_LOGIC_OP);
183             }
184         }
185     }
186 
187     if (blend.color.red != cur_state.blend.color.red ||
188         blend.color.green != cur_state.blend.color.green ||
189         blend.color.blue != cur_state.blend.color.blue ||
190         blend.color.alpha != cur_state.blend.color.alpha) {
191         glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
192     }
193 
194     if (blend.src_rgb_func != cur_state.blend.src_rgb_func ||
195         blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
196         blend.src_a_func != cur_state.blend.src_a_func ||
197         blend.dst_a_func != cur_state.blend.dst_a_func) {
198         glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func,
199                             blend.dst_a_func);
200     }
201 
202     if (blend.rgb_equation != cur_state.blend.rgb_equation ||
203         blend.a_equation != cur_state.blend.a_equation) {
204         glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
205     }
206 
207     // GLES does not support glLogicOp
208     if (!GLES) {
209         if (logic_op != cur_state.logic_op) {
210             glLogicOp(logic_op);
211         }
212     }
213 
214     // Textures
215     for (u32 i = 0; i < texture_units.size(); ++i) {
216         if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) {
217             glActiveTexture(TextureUnits::PicaTexture(i).Enum());
218             glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d);
219         }
220         if (texture_units[i].sampler != cur_state.texture_units[i].sampler) {
221             glBindSampler(i, texture_units[i].sampler);
222         }
223     }
224 
225     if (texture_cube_unit.texture_cube != cur_state.texture_cube_unit.texture_cube) {
226         glActiveTexture(TextureUnits::TextureCube.Enum());
227         glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cube_unit.texture_cube);
228     }
229     if (texture_cube_unit.sampler != cur_state.texture_cube_unit.sampler) {
230         glBindSampler(TextureUnits::TextureCube.id, texture_cube_unit.sampler);
231     }
232 
233     // Texture buffer LUTs
234     if (texture_buffer_lut_lf.texture_buffer != cur_state.texture_buffer_lut_lf.texture_buffer) {
235         glActiveTexture(TextureUnits::TextureBufferLUT_LF.Enum());
236         glBindTexture(GL_TEXTURE_BUFFER, texture_buffer_lut_lf.texture_buffer);
237     }
238 
239     // Texture buffer LUTs
240     if (texture_buffer_lut_rg.texture_buffer != cur_state.texture_buffer_lut_rg.texture_buffer) {
241         glActiveTexture(TextureUnits::TextureBufferLUT_RG.Enum());
242         glBindTexture(GL_TEXTURE_BUFFER, texture_buffer_lut_rg.texture_buffer);
243     }
244 
245     // Texture buffer LUTs
246     if (texture_buffer_lut_rgba.texture_buffer !=
247         cur_state.texture_buffer_lut_rgba.texture_buffer) {
248         glActiveTexture(TextureUnits::TextureBufferLUT_RGBA.Enum());
249         glBindTexture(GL_TEXTURE_BUFFER, texture_buffer_lut_rgba.texture_buffer);
250     }
251 
252     // Shadow Images
253     if (image_shadow_buffer != cur_state.image_shadow_buffer) {
254         glBindImageTexture(ImageUnits::ShadowBuffer, image_shadow_buffer, 0, GL_FALSE, 0,
255                            GL_READ_WRITE, GL_R32UI);
256     }
257 
258     if (image_shadow_texture_px != cur_state.image_shadow_texture_px) {
259         glBindImageTexture(ImageUnits::ShadowTexturePX, image_shadow_texture_px, 0, GL_FALSE, 0,
260                            GL_READ_ONLY, GL_R32UI);
261     }
262 
263     if (image_shadow_texture_nx != cur_state.image_shadow_texture_nx) {
264         glBindImageTexture(ImageUnits::ShadowTextureNX, image_shadow_texture_nx, 0, GL_FALSE, 0,
265                            GL_READ_ONLY, GL_R32UI);
266     }
267 
268     if (image_shadow_texture_py != cur_state.image_shadow_texture_py) {
269         glBindImageTexture(ImageUnits::ShadowTexturePY, image_shadow_texture_py, 0, GL_FALSE, 0,
270                            GL_READ_ONLY, GL_R32UI);
271     }
272 
273     if (image_shadow_texture_ny != cur_state.image_shadow_texture_ny) {
274         glBindImageTexture(ImageUnits::ShadowTextureNY, image_shadow_texture_ny, 0, GL_FALSE, 0,
275                            GL_READ_ONLY, GL_R32UI);
276     }
277 
278     if (image_shadow_texture_pz != cur_state.image_shadow_texture_pz) {
279         glBindImageTexture(ImageUnits::ShadowTexturePZ, image_shadow_texture_pz, 0, GL_FALSE, 0,
280                            GL_READ_ONLY, GL_R32UI);
281     }
282 
283     if (image_shadow_texture_nz != cur_state.image_shadow_texture_nz) {
284         glBindImageTexture(ImageUnits::ShadowTextureNZ, image_shadow_texture_nz, 0, GL_FALSE, 0,
285                            GL_READ_ONLY, GL_R32UI);
286     }
287 
288     // Framebuffer
289     if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
290         glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
291     }
292     if (draw.draw_framebuffer != cur_state.draw.draw_framebuffer) {
293         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.draw_framebuffer);
294     }
295 
296     // Vertex array
297     if (draw.vertex_array != cur_state.draw.vertex_array) {
298         glBindVertexArray(draw.vertex_array);
299     }
300 
301     // Vertex buffer
302     if (draw.vertex_buffer != cur_state.draw.vertex_buffer) {
303         glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer);
304     }
305 
306     // Uniform buffer
307     if (draw.uniform_buffer != cur_state.draw.uniform_buffer) {
308         glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer);
309     }
310 
311     // Shader program
312     if (draw.shader_program != cur_state.draw.shader_program) {
313         glUseProgram(draw.shader_program);
314     }
315 
316     // Program pipeline
317     if (draw.program_pipeline != cur_state.draw.program_pipeline) {
318         glBindProgramPipeline(draw.program_pipeline);
319     }
320 
321     // Scissor test
322     if (scissor.enabled != cur_state.scissor.enabled) {
323         if (scissor.enabled) {
324             glEnable(GL_SCISSOR_TEST);
325         } else {
326             glDisable(GL_SCISSOR_TEST);
327         }
328     }
329 
330     if (scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y ||
331         scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height) {
332         glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
333     }
334 
335     if (viewport.x != cur_state.viewport.x || viewport.y != cur_state.viewport.y ||
336         viewport.width != cur_state.viewport.width ||
337         viewport.height != cur_state.viewport.height) {
338         glViewport(viewport.x, viewport.y, viewport.width, viewport.height);
339     }
340 
341     // Clip distance
342     if (!GLES || GLAD_GL_EXT_clip_cull_distance) {
343         for (size_t i = 0; i < clip_distance.size(); ++i) {
344             if (clip_distance[i] != cur_state.clip_distance[i]) {
345                 if (clip_distance[i]) {
346                     glEnable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i));
347                 } else {
348                     glDisable(GL_CLIP_DISTANCE0 + static_cast<GLenum>(i));
349                 }
350             }
351         }
352     }
353 
354     if (renderbuffer != cur_state.renderbuffer) {
355         glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
356     }
357 
358     cur_state = *this;
359 }
360 
ResetTexture(GLuint handle)361 OpenGLState& OpenGLState::ResetTexture(GLuint handle) {
362     for (auto& unit : texture_units) {
363         if (unit.texture_2d == handle) {
364             unit.texture_2d = 0;
365         }
366     }
367     if (texture_cube_unit.texture_cube == handle)
368         texture_cube_unit.texture_cube = 0;
369     if (texture_buffer_lut_lf.texture_buffer == handle)
370         texture_buffer_lut_lf.texture_buffer = 0;
371     if (texture_buffer_lut_rg.texture_buffer == handle)
372         texture_buffer_lut_rg.texture_buffer = 0;
373     if (texture_buffer_lut_rgba.texture_buffer == handle)
374         texture_buffer_lut_rgba.texture_buffer = 0;
375     if (image_shadow_buffer == handle)
376         image_shadow_buffer = 0;
377     if (image_shadow_texture_px == handle)
378         image_shadow_texture_px = 0;
379     if (image_shadow_texture_nx == handle)
380         image_shadow_texture_nx = 0;
381     if (image_shadow_texture_py == handle)
382         image_shadow_texture_py = 0;
383     if (image_shadow_texture_ny == handle)
384         image_shadow_texture_ny = 0;
385     if (image_shadow_texture_pz == handle)
386         image_shadow_texture_pz = 0;
387     if (image_shadow_texture_nz == handle)
388         image_shadow_texture_nz = 0;
389     return *this;
390 }
391 
ResetSampler(GLuint handle)392 OpenGLState& OpenGLState::ResetSampler(GLuint handle) {
393     for (auto& unit : texture_units) {
394         if (unit.sampler == handle) {
395             unit.sampler = 0;
396         }
397     }
398     if (texture_cube_unit.sampler == handle) {
399         texture_cube_unit.sampler = 0;
400     }
401     return *this;
402 }
403 
ResetProgram(GLuint handle)404 OpenGLState& OpenGLState::ResetProgram(GLuint handle) {
405     if (draw.shader_program == handle) {
406         draw.shader_program = 0;
407     }
408     return *this;
409 }
410 
ResetPipeline(GLuint handle)411 OpenGLState& OpenGLState::ResetPipeline(GLuint handle) {
412     if (draw.program_pipeline == handle) {
413         draw.program_pipeline = 0;
414     }
415     return *this;
416 }
417 
ResetBuffer(GLuint handle)418 OpenGLState& OpenGLState::ResetBuffer(GLuint handle) {
419     if (draw.vertex_buffer == handle) {
420         draw.vertex_buffer = 0;
421     }
422     if (draw.uniform_buffer == handle) {
423         draw.uniform_buffer = 0;
424     }
425     return *this;
426 }
427 
ResetVertexArray(GLuint handle)428 OpenGLState& OpenGLState::ResetVertexArray(GLuint handle) {
429     if (draw.vertex_array == handle) {
430         draw.vertex_array = 0;
431     }
432     return *this;
433 }
434 
ResetFramebuffer(GLuint handle)435 OpenGLState& OpenGLState::ResetFramebuffer(GLuint handle) {
436     if (draw.read_framebuffer == handle) {
437         draw.read_framebuffer = 0;
438     }
439     if (draw.draw_framebuffer == handle) {
440         draw.draw_framebuffer = 0;
441     }
442     return *this;
443 }
444 
ResetRenderbuffer(GLuint handle)445 OpenGLState& OpenGLState::ResetRenderbuffer(GLuint handle) {
446     if (renderbuffer == handle) {
447         renderbuffer = 0;
448     }
449     return *this;
450 }
451 
452 } // namespace OpenGL
453