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 
23 namespace D3D8
24 {
Direct3DVertexBuffer8(Direct3DDevice8 * device,unsigned int length,unsigned long usage,long FVF,D3DPOOL pool)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 
~Direct3DVertexBuffer8()69 	Direct3DVertexBuffer8::~Direct3DVertexBuffer8()
70 	{
71 		vertexBuffer->destruct();
72 	}
73 
QueryInterface(const IID & iid,void ** object)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 
AddRef()93 	unsigned long Direct3DVertexBuffer8::AddRef()
94 	{
95 		TRACE("");
96 
97 		return Direct3DResource8::AddRef();
98 	}
99 
Release()100 	unsigned long Direct3DVertexBuffer8::Release()
101 	{
102 		TRACE("");
103 
104 		return Direct3DResource8::Release();
105 	}
106 
FreePrivateData(const GUID & guid)107 	long Direct3DVertexBuffer8::FreePrivateData(const GUID &guid)
108 	{
109 		TRACE("");
110 
111 		return Direct3DResource8::FreePrivateData(guid);
112 	}
113 
GetPrivateData(const GUID & guid,void * data,unsigned long * size)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 
PreLoad()121 	void Direct3DVertexBuffer8::PreLoad()
122 	{
123 		TRACE("");
124 
125 		Direct3DResource8::PreLoad();
126 	}
127 
SetPrivateData(const GUID & guid,const void * data,unsigned long size,unsigned long flags)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 
GetDevice(IDirect3DDevice8 ** device)135 	long Direct3DVertexBuffer8::GetDevice(IDirect3DDevice8 **device)
136 	{
137 		TRACE("");
138 
139 		return Direct3DResource8::GetDevice(device);
140 	}
141 
SetPriority(unsigned long newPriority)142 	unsigned long Direct3DVertexBuffer8::SetPriority(unsigned long newPriority)
143 	{
144 		TRACE("");
145 
146 		return Direct3DResource8::SetPriority(newPriority);
147 	}
148 
GetPriority()149 	unsigned long Direct3DVertexBuffer8::GetPriority()
150 	{
151 		TRACE("");
152 
153 		return Direct3DResource8::GetPriority();
154 	}
155 
GetType()156 	D3DRESOURCETYPE Direct3DVertexBuffer8::GetType()
157 	{
158 		TRACE("");
159 
160 		return Direct3DResource8::GetType();
161 	}
162 
Lock(unsigned int offset,unsigned int size,unsigned char ** data,unsigned long flags)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 
Unlock()186 	long Direct3DVertexBuffer8::Unlock()
187 	{
188 		TRACE("");
189 
190 		return D3D_OK;
191 	}
192 
GetDesc(D3DVERTEXBUFFER_DESC * description)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 
getLength() const212 	int Direct3DVertexBuffer8::getLength() const
213 	{
214 		return length;
215 	}
216 
getResource() const217 	sw::Resource *Direct3DVertexBuffer8::getResource() const
218 	{
219 		return vertexBuffer;
220 	}
221 }
222