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 "Direct3DVertexBuffer9.hpp" 16 17 #include "Direct3DDevice9.hpp" 18 #include "Resource.hpp" 19 #include "Debug.hpp" 20 21 #include <assert.h> 22 23 namespace D3D9 24 { Direct3DVertexBuffer9(Direct3DDevice9 * device,unsigned int length,unsigned long usage,long FVF,D3DPOOL pool)25 Direct3DVertexBuffer9::Direct3DVertexBuffer9(Direct3DDevice9 *device, unsigned int length, unsigned long usage, long FVF, D3DPOOL pool) : Direct3DResource9(device, D3DRTYPE_VERTEXBUFFER, pool, length), length(length), usage(usage), FVF(FVF) 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 case D3DFVF_XYZW: stride += 16; break; 41 } 42 43 if(FVF & D3DFVF_NORMAL) stride += 12; 44 if(FVF & D3DFVF_PSIZE) stride += 4; 45 if(FVF & D3DFVF_DIFFUSE) stride += 4; 46 if(FVF & D3DFVF_SPECULAR) stride += 4; 47 48 switch((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) 49 { 50 case 8: stride += 4 + 4 * ((1 + (FVF >> 30)) % 4); 51 case 7: stride += 4 + 4 * ((1 + (FVF >> 28)) % 4); 52 case 6: stride += 4 + 4 * ((1 + (FVF >> 26)) % 4); 53 case 5: stride += 4 + 4 * ((1 + (FVF >> 24)) % 4); 54 case 4: stride += 4 + 4 * ((1 + (FVF >> 22)) % 4); 55 case 3: stride += 4 + 4 * ((1 + (FVF >> 20)) % 4); 56 case 2: stride += 4 + 4 * ((1 + (FVF >> 18)) % 4); 57 case 1: stride += 4 + 4 * ((1 + (FVF >> 16)) % 4); 58 case 0: break; 59 default: 60 ASSERT(false); 61 } 62 63 ASSERT(length >= stride); // FIXME 64 } 65 66 vertexBuffer = new sw::Resource(length + 192 + 1024); // NOTE: Applications can 'overshoot' while writing vertices 67 lockCount = 0; 68 } 69 ~Direct3DVertexBuffer9()70 Direct3DVertexBuffer9::~Direct3DVertexBuffer9() 71 { 72 vertexBuffer->destruct(); 73 } 74 QueryInterface(const IID & iid,void ** object)75 long Direct3DVertexBuffer9::QueryInterface(const IID &iid, void **object) 76 { 77 CriticalSection cs(device); 78 79 TRACE(""); 80 81 if(iid == IID_IDirect3DVertexBuffer9 || 82 iid == IID_IDirect3DResource9 || 83 iid == IID_IUnknown) 84 { 85 AddRef(); 86 *object = this; 87 88 return S_OK; 89 } 90 91 *object = 0; 92 93 return NOINTERFACE(iid); 94 } 95 AddRef()96 unsigned long Direct3DVertexBuffer9::AddRef() 97 { 98 TRACE(""); 99 100 return Direct3DResource9::AddRef(); 101 } 102 Release()103 unsigned long Direct3DVertexBuffer9::Release() 104 { 105 TRACE(""); 106 107 return Direct3DResource9::Release(); 108 } 109 FreePrivateData(const GUID & guid)110 long Direct3DVertexBuffer9::FreePrivateData(const GUID &guid) 111 { 112 CriticalSection cs(device); 113 114 TRACE(""); 115 116 return Direct3DResource9::FreePrivateData(guid); 117 } 118 GetPrivateData(const GUID & guid,void * data,unsigned long * size)119 long Direct3DVertexBuffer9::GetPrivateData(const GUID &guid, void *data, unsigned long *size) 120 { 121 CriticalSection cs(device); 122 123 TRACE(""); 124 125 return Direct3DResource9::GetPrivateData(guid, data, size); 126 } 127 PreLoad()128 void Direct3DVertexBuffer9::PreLoad() 129 { 130 CriticalSection cs(device); 131 132 TRACE(""); 133 134 Direct3DResource9::PreLoad(); 135 } 136 SetPrivateData(const GUID & guid,const void * data,unsigned long size,unsigned long flags)137 long Direct3DVertexBuffer9::SetPrivateData(const GUID &guid, const void *data, unsigned long size, unsigned long flags) 138 { 139 CriticalSection cs(device); 140 141 TRACE(""); 142 143 return Direct3DResource9::SetPrivateData(guid, data, size, flags); 144 } 145 GetDevice(IDirect3DDevice9 ** device)146 long Direct3DVertexBuffer9::GetDevice(IDirect3DDevice9 **device) 147 { 148 CriticalSection cs(this->device); 149 150 TRACE(""); 151 152 return Direct3DResource9::GetDevice(device); 153 } 154 SetPriority(unsigned long newPriority)155 unsigned long Direct3DVertexBuffer9::SetPriority(unsigned long newPriority) 156 { 157 CriticalSection cs(device); 158 159 TRACE(""); 160 161 return Direct3DResource9::SetPriority(newPriority); 162 } 163 GetPriority()164 unsigned long Direct3DVertexBuffer9::GetPriority() 165 { 166 CriticalSection cs(device); 167 168 TRACE(""); 169 170 return Direct3DResource9::GetPriority(); 171 } 172 GetType()173 D3DRESOURCETYPE Direct3DVertexBuffer9::GetType() 174 { 175 CriticalSection cs(device); 176 177 TRACE(""); 178 179 return Direct3DResource9::GetType(); 180 } 181 Lock(unsigned int offset,unsigned int size,void ** data,unsigned long flags)182 long Direct3DVertexBuffer9::Lock(unsigned int offset, unsigned int size, void **data, unsigned long flags) 183 { 184 CriticalSection cs(device); 185 186 TRACE(""); 187 188 if(offset == 0 && size == 0) // Lock whole buffer 189 { 190 size = length; 191 } 192 193 if(!data || offset + size > length) 194 { 195 return INVALIDCALL(); 196 } 197 198 void *buffer; 199 200 if(flags & D3DLOCK_DISCARD/* && usage & D3DUSAGE_DYNAMIC*/) 201 { 202 vertexBuffer->destruct(); 203 vertexBuffer = new sw::Resource(length + 192 + 1024); // NOTE: Applications can 'overshoot' while writing vertices 204 205 buffer = (void*)vertexBuffer->data(); 206 } 207 else if(flags & D3DLOCK_NOOVERWRITE/* && usage & D3DUSAGE_DYNAMIC*/) 208 { 209 buffer = (void*)vertexBuffer->data(); 210 } 211 else 212 { 213 buffer = vertexBuffer->lock(sw::PUBLIC); 214 lockCount++; 215 } 216 217 *data = (unsigned char*)buffer + offset; 218 219 return D3D_OK; 220 } 221 Unlock()222 long Direct3DVertexBuffer9::Unlock() 223 { 224 CriticalSection cs(device); 225 226 TRACE(""); 227 228 if(lockCount > 0) 229 { 230 vertexBuffer->unlock(); 231 lockCount--; 232 } 233 234 return D3D_OK; 235 } 236 GetDesc(D3DVERTEXBUFFER_DESC * description)237 long Direct3DVertexBuffer9::GetDesc(D3DVERTEXBUFFER_DESC *description) 238 { 239 CriticalSection cs(device); 240 241 TRACE(""); 242 243 if(!description) 244 { 245 return INVALIDCALL(); 246 } 247 248 description->FVF = FVF; 249 description->Format = D3DFMT_VERTEXDATA; 250 description->Pool = pool; 251 description->Size = length; 252 description->Type = D3DRTYPE_VERTEXBUFFER; 253 description->Usage = usage; 254 255 return D3D_OK; 256 } 257 getLength() const258 int Direct3DVertexBuffer9::getLength() const 259 { 260 return length; 261 } 262 getResource() const263 sw::Resource *Direct3DVertexBuffer9::getResource() const 264 { 265 return vertexBuffer; 266 } 267 } 268