summaryrefslogtreecommitdiff
path: root/source/modules/asura-core/graphics/gpu_buffer.cpp
blob: 8d6f4919d89558f19616611127d8929dad1e1170 (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
#include "gpu_buffer.h"

namespace AsuraEngine
{
	namespace Graphics
	{

		GPUBuffer::GPUBuffer(BufferType type, BufferUsage usage, BufferDataType dataType, size_t size)
			: mTarget(GL_ZERO)
			, mBuffer(GL_ZERO)
			, mSize(0)
#if ASURA_DEBUG 
			, mData(nullptr)
#endif
		{
			mTarget = ConvertBufferType(type);
			mUsage = ConvertBufferUsage(usage);
			mDataType = ConvertBufferDataType(dataType);
			mSize = size;
		}

		GPUBuffer::~GPUBuffer()
		{
#if ASURA_DEBUG 
			if (mData)
				free(mData);
#endif
			glDeleteBuffers(1, &mBuffer);
		}

		GLenum GPUBuffer::ConvertBufferType(BufferType type)
		{
			switch (type)
			{
			case BUFFER_TYPE_VERTEX:
				return GL_ARRAY_BUFFER;
			case BUFFER_TYPE_INDEX:
				return GL_ELEMENT_ARRAY_BUFFER;
			}
		}

		GLenum GPUBuffer::ConvertBufferUsage(BufferUsage usage)
		{
			switch (usage)
			{
			case BUFFER_USAGE_STREAM:
				return GL_STREAM_DRAW;
			case BUFFER_USAGE_DYNAMIC:
				return GL_DYNAMIC_DRAW;
			case BUFFER_USAGE_STATIC:
				return GL_STATIC_DRAW;
			}
		}

		GLenum GPUBuffer::ConvertBufferDataType(BufferDataType type)
		{
			switch (type)
			{
			case BUFFER_DATA_TYPE_INT: 
				return GL_INT; 
			case BUFFER_DATA_TYPE_FLOAT: 
				return GL_FLOAT;
			case BUFFER_DATA_TYPE_UNSIGNED_BYTE: 
				return GL_UNSIGNED_BYTE;
			}
		}

		bool GPUBuffer::Fill(const void * data, size_t size, uint offset)
		{
			if (data == nullptr)
				return false;
			if (mBuffer == 0)
			{
				gfx.WipeError();
				glGenBuffers(1, &mBuffer);
				if (mBuffer == 0)
					throw Exception("OpenGL glGenBuffers failed.");
				glBindBuffer(mTarget, mBuffer);
				glBufferData(mTarget, mSize, NULL, mUsage);
				if (gfx.HasError())
				{
					glBindBuffer(mTarget, 0);
					throw Exception("OpenGL glBufferData failed. Errorcode=%d.", gfx.GetError());
				}
#if ASURA_DEBUG 
				mData = (byte*)malloc(size);
				memset(mData, 0, size);
#endif
			}
			else
				glBindBuffer(mTarget, mBuffer);
			glBufferSubData(mTarget, offset, size, data);
			if (gfx.HasError())
			{
				glBindBuffer(mTarget, 0);
				throw Exception("OpenGL glBufferSubData failed. Errorcode=%d.", gfx.GetError());
			}
			glBindBuffer(mTarget, 0);
#if ASURA_DEBUG
			memcpy(mData + offset, data, size);
#endif
			return true;
		}

		void GPUBuffer::Bind()
		{
			glBindBuffer(mTarget, mBuffer);
		}
		
		void GPUBuffer::UnBind()
		{
			glBindBuffer(mTarget, 0);
		}

		uint GPUBuffer::GetBufferSize()
		{
			return mSize; 
		}

		GLenum GPUBuffer::GetDataType()
		{
			return mDataType;
		}

		size_t GPUBuffer::GetDataTypeSize()
		{
			//https://blog.csdn.net/nklinux/article/details/16919017
			switch (mDataType)
			{
			case GL_UNSIGNED_BYTE: 
				return sizeof(GLbyte); 
			case GL_FLOAT : 
				return sizeof(GLfloat); 
			case GL_INT: 
				return sizeof(GLint);
			}
		}

		size_t GPUBuffer::GetDataTypeSize(GLenum datatype)
		{
			switch (datatype)
			{
			case GL_UNSIGNED_BYTE:
				return sizeof(GLbyte);
			case GL_FLOAT:
				return sizeof(GLfloat);
			case GL_INT:
				return sizeof(GLint);
			}
		}

	}
}