summaryrefslogtreecommitdiff
path: root/Runtime/GfxDevice/opengl/ChannelsGL.cpp
blob: 3b4f275c95f2a188d3cfc66f4f0120dde50000a7 (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#include "UnityPrefix.h"
#include "ChannelsGL.h"
#include "Runtime/GfxDevice/ChannelAssigns.h"
#include "UnityGL.h"
#include "Runtime/Shaders/GraphicsCaps.h"
#include "GLAssert.h"

// dimensionality of the different channels (element count)
static const int kDefaultChannelSizes[kShaderChannelCount] = {
	3, // pos
	3, // normal
	4, // color
	2, // uv
	2, // uv2
	4, // tangent
};

static const GLenum kDefaultChannelTypes[kShaderChannelCount] = {
	GL_FLOAT, // pos
	GL_FLOAT, // normal
	GL_UNSIGNED_BYTE, // color
	GL_FLOAT, // UV0
	GL_FLOAT, // UV1
	GL_FLOAT, // tangent
};


static void SetVertexComponentData( VertexComponent comp, int size, unsigned int type, int stride, const void *pointer )
{
	// We allow pointer to be used as an offset
	//DebugAssertIf( !pointer );

	switch (comp) {
	case kVertexCompColor:
		OGL_CALL(glColorPointer (size, type, stride, pointer));
		break;
	case kVertexCompVertex:
		OGL_CALL(glVertexPointer (size, type, stride, pointer));
		break;
	case kVertexCompNormal:
		DebugAssert( size >= 3 );
		OGL_CALL(glNormalPointer (type, stride, pointer));
		break;
	case kVertexCompTexCoord0:
	case kVertexCompTexCoord1:
	case kVertexCompTexCoord2:
	case kVertexCompTexCoord3:
	case kVertexCompTexCoord4:
	case kVertexCompTexCoord5:
	case kVertexCompTexCoord6:
	case kVertexCompTexCoord7:
		if (gGraphicsCaps.maxTexCoords > 1) {
			OGL_CALL(glClientActiveTextureARB( GL_TEXTURE0_ARB + comp - kVertexCompTexCoord0 ));
		}
		OGL_CALL(glTexCoordPointer (size, type, stride, pointer));
		break;
	case kVertexCompTexCoord:
		printf_console( "Warning: unspecified texcoord bound\n" );
		break;
	case kVertexCompAttrib0: case kVertexCompAttrib1: case kVertexCompAttrib2: case kVertexCompAttrib3:
	case kVertexCompAttrib4: case kVertexCompAttrib5: case kVertexCompAttrib6: case kVertexCompAttrib7:
	case kVertexCompAttrib8: case kVertexCompAttrib9: case kVertexCompAttrib10: case kVertexCompAttrib11:
	case kVertexCompAttrib12: case kVertexCompAttrib13: case kVertexCompAttrib14: case kVertexCompAttrib15:
		OGL_CALL(glVertexAttribPointerARB( comp - kVertexCompAttrib0, size, type, true, stride, pointer ));
		break;
	}
}

static signed char s_EnabledVertexComps[kVertexCompCount]; // 0/1 or -1 if unknown
static unsigned int s_EnabledTargetsMask; // Bitfield of which targets are currently valid

void ClearActiveChannelsGL()
{
	s_EnabledTargetsMask = 0;
}

static UInt32 GetGLType(const ChannelInfo& source)
{
	switch (source.format)
	{
		case kChannelFormatFloat:	return GL_FLOAT;
		case kChannelFormatFloat16:	return GL_HALF_FLOAT_ARB;
		case kChannelFormatColor:	return GL_UNSIGNED_BYTE;
		case kChannelFormatByte:	return GL_BYTE;
	}
	ErrorString("Unknown channel format!");
	return 0;
}

static int GetGLDimension(const ChannelInfo& source)
{
	return (source.format == kChannelFormatColor) ? 4 : source.dimension;
}

void SetChannelDataGL( const ChannelInfo& source, const StreamInfoArray streams, VertexComponent target, const UInt8* buffer )
{
	AssertIf( target == kVertexCompNone || target == kVertexCompTexCoord );
	int stride = source.CalcStride( streams );
	int offset = source.CalcOffset( streams );
	SetVertexComponentData( target, GetGLDimension(source), GetGLType(source), stride, buffer + offset );
	s_EnabledTargetsMask |= (1 << target);
}

void SetChannelDataGL( ShaderChannel source, VertexComponent target, const void *pointer, int stride )
{
	AssertIf( source == kShaderChannelNone );
	if( !pointer )
		return;

	DebugAssertIf( target == kVertexCompNone || target == kVertexCompTexCoord );
	SetVertexComponentData( target, kDefaultChannelSizes[source], kDefaultChannelTypes[source], stride, pointer );
	s_EnabledTargetsMask |= (1 << target);
}

#if UNITY_EDITOR
// only used by GizmoUtil in the editor
void SetChannelDataGL( ShaderChannel source, const ChannelAssigns& channels, const void *pointer, int stride )
{
	AssertIf( source == kShaderChannelNone );
	if( !pointer )
		return;

	for( int i = 0; i < kVertexCompCount; ++i )
	{
		if( channels.GetSourceForTarget( (VertexComponent)i ) == source )
		{
			AssertIf( i == kVertexCompNone || i == kVertexCompTexCoord );
			SetVertexComponentData( (VertexComponent)i, kDefaultChannelSizes[source], kDefaultChannelTypes[source], stride, pointer );
			s_EnabledTargetsMask |= (1 << i);
		}
	}
}

#endif


void ActivateChannelsGL()
{
	unsigned int compMask = s_EnabledTargetsMask;
	int i;

	// fetch now to prevent aliasing
	GLint vaCount = gGraphicsCaps.gl.vertexAttribCount;
	//GLint texUnitCount = gGraphicsCaps.maxTexUnits;
	GLint texCoordCount = gGraphicsCaps.maxTexCoords;

	static GLenum gltargets[] = { 0, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_NORMAL_ARRAY };

	// There's a dark corner of GL spec that says that generic and conventional vertex
	// attributes (and arrays) may be aliased (most decent drivers don't alias them).
	// http://oss.sgi.com/projects/ogl-sample/registry/NV/vertex_program.txt
	//
	// So we first disable all vertex components that we don't use; then enable all
	// that we do use. This should work both in aliased and non-aliased implementations.
	//
	// On some systems (XP, Catalyst 5.7, R9600) this makes a difference!
	// Without it e.g. a single GUIText is not visible.

	// --------------------------------
	// First disable components we don't use

	for( i = kVertexCompVertex; i <= kVertexCompNormal; ++i )
	{
		if( !(compMask & (1<<i)) )
		{
			if( s_EnabledVertexComps[i] != 0 )
			{
				OGL_CALL(glDisableClientState( gltargets[i] ));
				s_EnabledVertexComps[i] = 0;
			}
		}
	}

	for( i = 0; i < texCoordCount; ++i )
	{
		int compIndex = kVertexCompTexCoord0 + i;
		if( !(compMask & (1 << compIndex)) )
		{
			if( s_EnabledVertexComps[compIndex] != 0 )
			{
				if( texCoordCount > 1 )
					OGL_CALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + i));
				OGL_CALL(glDisableClientState (GL_TEXTURE_COORD_ARRAY));
				s_EnabledVertexComps[compIndex] = 0;
			}
		}
	}

	for( i = 0; i < vaCount; ++i )
	{
		int compIndex = kVertexCompAttrib0 + i;
		if( !(compMask & (1 << compIndex)) )
		{
			if( s_EnabledVertexComps[compIndex] != 0 )
			{
				OGL_CALL(glDisableVertexAttribArrayARB (i));
				s_EnabledVertexComps[compIndex] = 0;
			}
		}
	}

	// --------------------------------
	// Then enable components we use

	for( i = kVertexCompVertex; i <= kVertexCompNormal; ++i )
	{
		if( compMask & (1<<i) )
		{
			if( s_EnabledVertexComps[i] != 1 )
			{
				OGL_CALL(glEnableClientState( gltargets[i] ));
				s_EnabledVertexComps[i] = 1;
			}
		}
	}

	for( i = 0; i < texCoordCount; ++i )
	{
		int compIndex = kVertexCompTexCoord0 + i;
		if( compMask & (1 << compIndex) )
		{
			if( s_EnabledVertexComps[compIndex] != 1 )
			{
				if( texCoordCount > 1 )
					OGL_CALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + i));
				OGL_CALL(glEnableClientState (GL_TEXTURE_COORD_ARRAY));
				s_EnabledVertexComps[compIndex] = 1;
			}
		}
	}

	for( i = 0; i < vaCount; ++i )
	{
		int compIndex = kVertexCompAttrib0 + i;
		if( compMask & (1 << compIndex) )
		{
			if( s_EnabledVertexComps[compIndex] != 1 )
			{
				OGL_CALL(glEnableVertexAttribArrayARB( i ));
				s_EnabledVertexComps[compIndex] = 1;
			}
		}
	}

	GLAssert();
}

void InvalidateChannelStateGL()
{
	for( int i = 0; i < kVertexCompCount; ++i )
		s_EnabledVertexComps[i] = -1;
}