1 // Copyright 2019 yuzu Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <limits>
8 
9 #include <glad/glad.h>
10 
11 #include "common/common_types.h"
12 #include "core/core.h"
13 #include "video_core/dirty_flags.h"
14 #include "video_core/engines/maxwell_3d.h"
15 
16 namespace Tegra {
17 class GPU;
18 }
19 
20 namespace OpenGL {
21 
22 namespace Dirty {
23 
24 enum : u8 {
25     First = VideoCommon::Dirty::LastCommonEntry,
26 
27     VertexFormats,
28     VertexFormat0,
29     VertexFormat31 = VertexFormat0 + 31,
30 
31     VertexBuffers,
32     VertexBuffer0,
33     VertexBuffer31 = VertexBuffer0 + 31,
34 
35     VertexInstances,
36     VertexInstance0,
37     VertexInstance31 = VertexInstance0 + 31,
38 
39     ViewportTransform,
40     Viewports,
41     Viewport0,
42     Viewport15 = Viewport0 + 15,
43 
44     Scissors,
45     Scissor0,
46     Scissor15 = Scissor0 + 15,
47 
48     ColorMaskCommon,
49     ColorMasks,
50     ColorMask0,
51     ColorMask7 = ColorMask0 + 7,
52 
53     BlendColor,
54     BlendIndependentEnabled,
55     BlendStates,
56     BlendState0,
57     BlendState7 = BlendState0 + 7,
58 
59     Shaders,
60     ClipDistances,
61 
62     PolygonModes,
63     PolygonModeFront,
64     PolygonModeBack,
65 
66     ColorMask,
67     FrontFace,
68     CullTest,
69     DepthMask,
70     DepthTest,
71     StencilTest,
72     AlphaTest,
73     PrimitiveRestart,
74     PolygonOffset,
75     MultisampleControl,
76     RasterizeEnable,
77     FramebufferSRGB,
78     LogicOp,
79     FragmentClampColor,
80     PointSize,
81     LineWidth,
82     ClipControl,
83     DepthClampEnabled,
84 
85     Last
86 };
87 static_assert(Last <= std::numeric_limits<u8>::max());
88 
89 } // namespace Dirty
90 
91 class StateTracker {
92 public:
93     explicit StateTracker(Tegra::GPU& gpu);
94 
BindIndexBuffer(GLuint new_index_buffer)95     void BindIndexBuffer(GLuint new_index_buffer) {
96         if (index_buffer == new_index_buffer) {
97             return;
98         }
99         index_buffer = new_index_buffer;
100         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, new_index_buffer);
101     }
102 
NotifyScreenDrawVertexArray()103     void NotifyScreenDrawVertexArray() {
104         flags[OpenGL::Dirty::VertexFormats] = true;
105         flags[OpenGL::Dirty::VertexFormat0 + 0] = true;
106         flags[OpenGL::Dirty::VertexFormat0 + 1] = true;
107 
108         flags[OpenGL::Dirty::VertexBuffers] = true;
109         flags[OpenGL::Dirty::VertexBuffer0] = true;
110 
111         flags[OpenGL::Dirty::VertexInstances] = true;
112         flags[OpenGL::Dirty::VertexInstance0 + 0] = true;
113         flags[OpenGL::Dirty::VertexInstance0 + 1] = true;
114     }
115 
NotifyPolygonModes()116     void NotifyPolygonModes() {
117         flags[OpenGL::Dirty::PolygonModes] = true;
118         flags[OpenGL::Dirty::PolygonModeFront] = true;
119         flags[OpenGL::Dirty::PolygonModeBack] = true;
120     }
121 
NotifyViewport0()122     void NotifyViewport0() {
123         flags[OpenGL::Dirty::Viewports] = true;
124         flags[OpenGL::Dirty::Viewport0] = true;
125     }
126 
NotifyScissor0()127     void NotifyScissor0() {
128         flags[OpenGL::Dirty::Scissors] = true;
129         flags[OpenGL::Dirty::Scissor0] = true;
130     }
131 
NotifyColorMask0()132     void NotifyColorMask0() {
133         flags[OpenGL::Dirty::ColorMasks] = true;
134         flags[OpenGL::Dirty::ColorMask0] = true;
135     }
136 
NotifyBlend0()137     void NotifyBlend0() {
138         flags[OpenGL::Dirty::BlendStates] = true;
139         flags[OpenGL::Dirty::BlendState0] = true;
140     }
141 
NotifyFramebuffer()142     void NotifyFramebuffer() {
143         flags[VideoCommon::Dirty::RenderTargets] = true;
144     }
145 
NotifyFrontFace()146     void NotifyFrontFace() {
147         flags[OpenGL::Dirty::FrontFace] = true;
148     }
149 
NotifyCullTest()150     void NotifyCullTest() {
151         flags[OpenGL::Dirty::CullTest] = true;
152     }
153 
NotifyDepthMask()154     void NotifyDepthMask() {
155         flags[OpenGL::Dirty::DepthMask] = true;
156     }
157 
NotifyDepthTest()158     void NotifyDepthTest() {
159         flags[OpenGL::Dirty::DepthTest] = true;
160     }
161 
NotifyStencilTest()162     void NotifyStencilTest() {
163         flags[OpenGL::Dirty::StencilTest] = true;
164     }
165 
NotifyPolygonOffset()166     void NotifyPolygonOffset() {
167         flags[OpenGL::Dirty::PolygonOffset] = true;
168     }
169 
NotifyRasterizeEnable()170     void NotifyRasterizeEnable() {
171         flags[OpenGL::Dirty::RasterizeEnable] = true;
172     }
173 
NotifyFramebufferSRGB()174     void NotifyFramebufferSRGB() {
175         flags[OpenGL::Dirty::FramebufferSRGB] = true;
176     }
177 
NotifyLogicOp()178     void NotifyLogicOp() {
179         flags[OpenGL::Dirty::LogicOp] = true;
180     }
181 
NotifyClipControl()182     void NotifyClipControl() {
183         flags[OpenGL::Dirty::ClipControl] = true;
184     }
185 
NotifyAlphaTest()186     void NotifyAlphaTest() {
187         flags[OpenGL::Dirty::AlphaTest] = true;
188     }
189 
190 private:
191     Tegra::Engines::Maxwell3D::DirtyState::Flags& flags;
192 
193     GLuint index_buffer = 0;
194 };
195 
196 } // namespace OpenGL
197