summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.h22
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp40
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_state_tracker.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_state_tracker.h11
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h13
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp2
7 files changed, 99 insertions, 2 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 491cff370..ed7fc8fdd 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -524,6 +524,12 @@ public:
FractionalEven = 2,
};
+ enum class PolygonMode : u32 {
+ Point = 0x1b00,
+ Line = 0x1b01,
+ Fill = 0x1b02,
+ };
+
struct RenderTargetConfig {
u32 address_high;
u32 address_low;
@@ -705,7 +711,12 @@ public:
s32 clear_stencil;
- INSERT_UNION_PADDING_WORDS(0x7);
+ INSERT_UNION_PADDING_WORDS(0x2);
+
+ PolygonMode polygon_mode_front;
+ PolygonMode polygon_mode_back;
+
+ INSERT_UNION_PADDING_WORDS(0x3);
u32 polygon_offset_point_enable;
u32 polygon_offset_line_enable;
@@ -764,7 +775,11 @@ public:
BitField<12, 4, u32> viewport;
} clear_flags;
- INSERT_UNION_PADDING_WORDS(0x19);
+ INSERT_UNION_PADDING_WORDS(0x10);
+
+ u32 fill_rectangle;
+
+ INSERT_UNION_PADDING_WORDS(0x8);
std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
@@ -1422,6 +1437,8 @@ ASSERT_REG_POSITION(depth_mode, 0x35F);
ASSERT_REG_POSITION(clear_color[0], 0x360);
ASSERT_REG_POSITION(clear_depth, 0x364);
ASSERT_REG_POSITION(clear_stencil, 0x368);
+ASSERT_REG_POSITION(polygon_mode_front, 0x36B);
+ASSERT_REG_POSITION(polygon_mode_back, 0x36C);
ASSERT_REG_POSITION(polygon_offset_point_enable, 0x370);
ASSERT_REG_POSITION(polygon_offset_line_enable, 0x371);
ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372);
@@ -1435,6 +1452,7 @@ ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
ASSERT_REG_POSITION(depth_bounds, 0x3E7);
ASSERT_REG_POSITION(zeta, 0x3F8);
ASSERT_REG_POSITION(clear_flags, 0x43E);
+ASSERT_REG_POSITION(fill_rectangle, 0x44F);
ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
ASSERT_REG_POSITION(rt_control, 0x487);
ASSERT_REG_POSITION(zeta_width, 0x48a);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 4e4138573..8e48a6482 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -487,6 +487,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
SyncViewport();
SyncRasterizeEnable();
+ SyncPolygonModes();
SyncColorMask();
SyncFragmentColorClampState();
SyncMultiSampleState();
@@ -1096,6 +1097,45 @@ void RasterizerOpenGL::SyncRasterizeEnable() {
oglEnable(GL_RASTERIZER_DISCARD, gpu.regs.rasterize_enable == 0);
}
+void RasterizerOpenGL::SyncPolygonModes() {
+ auto& gpu = system.GPU().Maxwell3D();
+ auto& flags = gpu.dirty.flags;
+ if (!flags[Dirty::PolygonModes]) {
+ return;
+ }
+ flags[Dirty::PolygonModes] = false;
+
+ if (gpu.regs.fill_rectangle) {
+ if (!GLAD_GL_NV_fill_rectangle) {
+ LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ return;
+ }
+
+ flags[Dirty::PolygonModeFront] = true;
+ flags[Dirty::PolygonModeBack] = true;
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV);
+ return;
+ }
+
+ if (gpu.regs.polygon_mode_front == gpu.regs.polygon_mode_back) {
+ flags[Dirty::PolygonModeFront] = false;
+ flags[Dirty::PolygonModeBack] = false;
+ glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front));
+ return;
+ }
+
+ if (flags[Dirty::PolygonModeFront]) {
+ flags[Dirty::PolygonModeFront] = false;
+ glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front));
+ }
+
+ if (flags[Dirty::PolygonModeBack]) {
+ flags[Dirty::PolygonModeBack] = false;
+ glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_back));
+ }
+}
+
void RasterizerOpenGL::SyncColorMask() {
auto& gpu = system.GPU().Maxwell3D();
auto& flags = gpu.dirty.flags;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index b24c6661b..e5681d6df 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -178,6 +178,9 @@ private:
/// Syncs the rasterizer enable state to match the guest state
void SyncRasterizeEnable();
+ /// Syncs polygon modes to match the guest state
+ void SyncPolygonModes();
+
/// Syncs Color Mask
void SyncColorMask();
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp
index 1e43c9ec0..3f3bdf812 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.cpp
+++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp
@@ -94,6 +94,15 @@ void SetupDirtyShaders(Tables& tables) {
Shaders);
}
+void SetupDirtyPolygonModes(Tables& tables) {
+ tables[0][OFF(polygon_mode_front)] = PolygonModeFront;
+ tables[0][OFF(polygon_mode_back)] = PolygonModeBack;
+
+ tables[1][OFF(polygon_mode_front)] = PolygonModes;
+ tables[1][OFF(polygon_mode_back)] = PolygonModes;
+ tables[0][OFF(fill_rectangle)] = PolygonModes;
+}
+
void SetupDirtyDepthTest(Tables& tables) {
auto& table = tables[0];
table[OFF(depth_test_enable)] = DepthTest;
@@ -211,6 +220,7 @@ void StateTracker::Initialize() {
SetupDirtyVertexArrays(tables);
SetupDirtyVertexFormat(tables);
SetupDirtyShaders(tables);
+ SetupDirtyPolygonModes(tables);
SetupDirtyDepthTest(tables);
SetupDirtyStencilTest(tables);
SetupDirtyAlphaTest(tables);
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.h b/src/video_core/renderer_opengl/gl_state_tracker.h
index e08482911..b882d75c3 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.h
+++ b/src/video_core/renderer_opengl/gl_state_tracker.h
@@ -59,6 +59,10 @@ enum : u8 {
Shaders,
ClipDistances,
+ PolygonModes,
+ PolygonModeFront,
+ PolygonModeBack,
+
ColorMask,
FrontFace,
CullTest,
@@ -111,6 +115,13 @@ public:
flags[OpenGL::Dirty::VertexInstance0 + 1] = true;
}
+ void NotifyPolygonModes() {
+ auto& flags = system.GPU().Maxwell3D().dirty.flags;
+ flags[OpenGL::Dirty::PolygonModes] = true;
+ flags[OpenGL::Dirty::PolygonModeFront] = true;
+ flags[OpenGL::Dirty::PolygonModeBack] = true;
+ }
+
void NotifyViewport0() {
auto& flags = system.GPU().Maxwell3D().dirty.flags;
flags[OpenGL::Dirty::Viewports] = true;
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 494e38e7a..89f0e04ef 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -488,5 +488,18 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) {
return GL_COPY;
}
+inline GLenum PolygonMode(Maxwell::PolygonMode polygon_mode) {
+ switch (polygon_mode) {
+ case Maxwell::PolygonMode::Point:
+ return GL_POINT;
+ case Maxwell::PolygonMode::Line:
+ return GL_LINE;
+ case Maxwell::PolygonMode::Fill:
+ return GL_FILL;
+ }
+ UNREACHABLE_MSG("Invalid polygon mode={}", static_cast<int>(polygon_mode));
+ return GL_FILL;
+}
+
} // namespace MaxwellToGL
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index c05677cd9..12333e8c9 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -576,6 +576,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
// TODO: Signal state tracker about these changes
state_tracker.NotifyScreenDrawVertexArray();
+ state_tracker.NotifyPolygonModes();
state_tracker.NotifyViewport0();
state_tracker.NotifyScissor0();
state_tracker.NotifyColorMask0();
@@ -611,6 +612,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
glDisable(GL_ALPHA_TEST);
glDisablei(GL_BLEND, 0);
glDisablei(GL_SCISSOR_TEST, 0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);