summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/GeometryShaderManager.cpp
blob: 19a480692f78f30285b564327b0b77ce71a624a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <cfloat>
#include <cmath>

#include "VideoCommon/BPMemory.h"
#include "VideoCommon/GeometryShaderGen.h"
#include "VideoCommon/GeometryShaderManager.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/XFMemory.h"

static const int LINE_PT_TEX_OFFSETS[8] = {
	0, 16, 8, 4, 2, 1, 1, 1
};

GeometryShaderConstants GeometryShaderManager::constants;
bool GeometryShaderManager::dirty;

static bool s_projection_changed;
static bool s_viewport_changed;

void GeometryShaderManager::Init()
{
	memset(&constants, 0, sizeof(constants));

	// Init any intial constants which aren't zero when bpmem is zero.
	SetViewportChanged();
	SetProjectionChanged();

	dirty = true;
}

void GeometryShaderManager::Shutdown()
{
}

void GeometryShaderManager::Dirty()
{
	// This function is called after a savestate is loaded.
	// Any constants that can changed based on settings should be re-calculated
	s_projection_changed = true;

	dirty = true;
}

void GeometryShaderManager::SetConstants()
{
	if (s_projection_changed && g_ActiveConfig.iStereoMode > 0)
	{
		s_projection_changed = false;

		if (xfmem.projection.type == GX_PERSPECTIVE)
		{
			float offset = (g_ActiveConfig.iStereoDepth / 1000.0f) * (g_ActiveConfig.iStereoDepthPercentage / 100.0f);
			constants.stereoparams[0] = g_ActiveConfig.bStereoSwapEyes ? offset : -offset;
			constants.stereoparams[1] = g_ActiveConfig.bStereoSwapEyes ? -offset : offset;
		}
		else
		{
			constants.stereoparams[0] = constants.stereoparams[1] = 0;
		}

		constants.stereoparams[2] = (float)(g_ActiveConfig.iStereoConvergenceMinimum + g_ActiveConfig.iStereoConvergence);

		dirty = true;
	}

	if (s_viewport_changed)
	{
		s_viewport_changed = false;

		constants.lineptparams[0] = 2.0f * xfmem.viewport.wd;
		constants.lineptparams[1] = -2.0f * xfmem.viewport.ht;

		dirty = true;
	}
}

void GeometryShaderManager::SetViewportChanged()
{
	s_viewport_changed = true;
}

void GeometryShaderManager::SetProjectionChanged()
{
	s_projection_changed = true;
}

void GeometryShaderManager::SetLinePtWidthChanged()
{
	constants.lineptparams[2] = bpmem.lineptwidth.linesize / 6.f;
	constants.lineptparams[3] = bpmem.lineptwidth.pointsize / 6.f;
	constants.texoffset[2] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff];
	constants.texoffset[3] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff];
	dirty = true;
}

void GeometryShaderManager::SetTexCoordChanged(u8 texmapid)
{
	TCoordInfo& tc = bpmem.texcoords[texmapid];
	int bitmask = 1 << texmapid;
	constants.texoffset[0] &= ~bitmask;
	constants.texoffset[0] |= tc.s.line_offset << texmapid;
	constants.texoffset[1] &= ~bitmask;
	constants.texoffset[1] |= tc.s.point_offset << texmapid;
	dirty = true;
}

void GeometryShaderManager::DoState(PointerWrap &p)
{
	p.Do(s_projection_changed);
	p.Do(s_viewport_changed);

	p.Do(constants);

	if (p.GetMode() == PointerWrap::MODE_READ)
	{
		// Fixup the current state from global GPU state
		// NOTE: This requires that all GPU memory has been loaded already.
		Dirty();
	}
}