1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "Direct3DVertexBuffer8.hpp"
16
17#include "Direct3DDevice8.hpp"
18#include "Resource.hpp"
19#include "Debug.hpp"
20
21#include <assert.h>
22
23namespace D3D8
24{
25	Direct3DVertexBuffer8::Direct3DVertexBuffer8(Direct3DDevice8 *device, unsigned int length, unsigned long usage, long FVF, D3DPOOL pool) : Direct3DResource8(device, D3DRTYPE_VERTEXBUFFER, length), length(length), usage(usage), FVF(FVF), pool(pool)
26	{
27		if(FVF)
28		{
29			unsigned int stride = 0;
30
31			switch(FVF & D3DFVF_POSITION_MASK)
32			{
33			case D3DFVF_XYZ:	stride += 12;	break;
34			case D3DFVF_XYZRHW:	stride += 16;	break;
35			case D3DFVF_XYZB1:	stride += 16;	break;
36			case D3DFVF_XYZB2:	stride += 20;	break;
37			case D3DFVF_XYZB3:	stride += 24;	break;
38			case D3DFVF_XYZB4:	stride += 28;	break;
39			case D3DFVF_XYZB5:	stride += 32;	break;
40			}
41
42			if(FVF & D3DFVF_NORMAL)   stride += 12;
43			if(FVF & D3DFVF_PSIZE)    stride += 4;
44			if(FVF & D3DFVF_DIFFUSE)  stride += 4;
45			if(FVF & D3DFVF_SPECULAR) stride += 4;
46
47			switch((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT)
48			{
49			case 8: stride += 4 + 4 * ((1 + (FVF >> 30)) % 4);
50			case 7: stride += 4 + 4 * ((1 + (FVF >> 28)) % 4);
51			case 6: stride += 4 + 4 * ((1 + (FVF >> 26)) % 4);
52			case 5: stride += 4 + 4 * ((1 + (FVF >> 24)) % 4);
53			case 4: stride += 4 + 4 * ((1 + (FVF >> 22)) % 4);
54			case 3: stride += 4 + 4 * ((1 + (FVF >> 20)) % 4);
55			case 2: stride += 4 + 4 * ((1 + (FVF >> 18)) % 4);
56			case 1: stride += 4 + 4 * ((1 + (FVF >> 16)) % 4);
57			case 0: break;
58			default:
59				ASSERT(false);
60			}
61
62			ASSERT(length >= stride);       // FIXME
63			ASSERT(length % stride == 0);   // D3D vertex size calculated incorrectly   // FIXME
64		}
65
66		vertexBuffer = new sw::Resource(length + 192 + 1024);   // NOTE: Applications can 'overshoot' while writing vertices
67	}
68
69	Direct3DVertexBuffer8::~Direct3DVertexBuffer8()
70	{
71		vertexBuffer->destruct();
72	}
73
74	long Direct3DVertexBuffer8::QueryInterface(const IID &iid, void **object)
75	{
76		TRACE("");
77
78		if(iid == IID_IDirect3DVertexBuffer8 ||
79		   iid == IID_IDirect3DResource8 ||
80		   iid == IID_IUnknown)
81		{
82			AddRef();
83			*object = this;
84
85			return S_OK;
86		}
87
88		*object = 0;
89
90		return NOINTERFACE(iid);
91	}
92
93	unsigned long Direct3DVertexBuffer8::AddRef()
94	{
95		TRACE("");
96
97		return Direct3DResource8::AddRef();
98	}
99
100	unsigned long Direct3DVertexBuffer8::Release()
101	{
102		TRACE("");
103
104		return Direct3DResource8::Release();
105	}
106
107	long Direct3DVertexBuffer8::FreePrivateData(const GUID &guid)
108	{
109		TRACE("");
110
111		return Direct3DResource8::FreePrivateData(guid);
112	}
113
114	long Direct3DVertexBuffer8::GetPrivateData(const GUID &guid, void *data, unsigned long *size)
115	{
116		TRACE("");
117
118		return Direct3DResource8::GetPrivateData(guid, data, size);
119	}
120
121	void Direct3DVertexBuffer8::PreLoad()
122	{
123		TRACE("");
124
125		Direct3DResource8::PreLoad();
126	}
127
128	long Direct3DVertexBuffer8::SetPrivateData(const GUID &guid, const void *data, unsigned long size, unsigned long flags)
129	{
130		TRACE("");
131
132		return Direct3DResource8::SetPrivateData(guid, data, size, flags);
133	}
134
135	long Direct3DVertexBuffer8::GetDevice(IDirect3DDevice8 **device)
136	{
137		TRACE("");
138
139		return Direct3DResource8::GetDevice(device);
140	}
141
142	unsigned long Direct3DVertexBuffer8::SetPriority(unsigned long newPriority)
143	{
144		TRACE("");
145
146		return Direct3DResource8::SetPriority(newPriority);
147	}
148
149	unsigned long Direct3DVertexBuffer8::GetPriority()
150	{
151		TRACE("");
152
153		return Direct3DResource8::GetPriority();
154	}
155
156	D3DRESOURCETYPE Direct3DVertexBuffer8::GetType()
157	{
158		TRACE("");
159
160		return Direct3DResource8::GetType();
161	}
162
163	long Direct3DVertexBuffer8::Lock(unsigned int offset, unsigned int size, unsigned char **data, unsigned long flags)
164	{
165		TRACE("");
166
167		if(offset == 0 && size == 0)   // Lock whole buffer
168		{
169			size = length;
170		}
171
172		if(!data || offset + size > length)
173		{
174			return INVALIDCALL();
175		}
176
177		lockOffset = offset;
178		lockSize = size;
179
180		*data = (unsigned char*)vertexBuffer->lock(sw::PUBLIC) + offset;
181		vertexBuffer->unlock();
182
183		return D3D_OK;
184	}
185
186	long Direct3DVertexBuffer8::Unlock()
187	{
188		TRACE("");
189
190		return D3D_OK;
191	}
192
193	long Direct3DVertexBuffer8::GetDesc(D3DVERTEXBUFFER_DESC *description)
194	{
195		TRACE("");
196
197		if(!description)
198		{
199			return INVALIDCALL();
200		}
201
202		description->FVF = FVF;
203		description->Format = D3DFMT_VERTEXDATA;
204		description->Pool = pool;
205		description->Size = length;
206		description->Type = D3DRTYPE_VERTEXBUFFER;
207		description->Usage = usage;
208
209		return D3D_OK;
210	}
211
212	int Direct3DVertexBuffer8::getLength() const
213	{
214		return length;
215	}
216
217	sw::Resource *Direct3DVertexBuffer8::getResource() const
218	{
219		return vertexBuffer;
220	}
221}
222