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 "Direct3DVolumeTexture9.hpp" 16 17 #include "Direct3DVolume9.hpp" 18 #include "Direct3DDevice9.hpp" 19 #include "Resource.hpp" 20 #include "Debug.hpp" 21 22 #include <assert.h> 23 24 namespace D3D9 25 { Direct3DVolumeTexture9(Direct3DDevice9 * device,unsigned int width,unsigned int height,unsigned int depth,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool)26 Direct3DVolumeTexture9::Direct3DVolumeTexture9(Direct3DDevice9 *device, unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool) : Direct3DBaseTexture9(device, D3DRTYPE_VOLUMETEXTURE, format, pool, levels, usage), width(width), height(height), depth(depth) 27 { 28 if(levels == 0) 29 { 30 this->levels = sw::log2(sw::max((int)width, (int)height, (int)depth, 1)) + 1; 31 } 32 33 for(unsigned int level = 0; level < sw::MIPMAP_LEVELS; level++) 34 { 35 if(level < this->levels) 36 { 37 volumeLevel[level] = new Direct3DVolume9(device, this, width, height, depth, format, pool, usage); 38 volumeLevel[level]->bind(); 39 } 40 else 41 { 42 volumeLevel[level] = 0; 43 } 44 45 width = sw::max(1, (int)width / 2); 46 height = sw::max(1, (int)height / 2); 47 depth = sw::max(1, (int)depth / 2); 48 } 49 } 50 ~Direct3DVolumeTexture9()51 Direct3DVolumeTexture9::~Direct3DVolumeTexture9() 52 { 53 resource->lock(sw::DESTRUCT); 54 55 for(int level = 0; level < sw::MIPMAP_LEVELS; level++) 56 { 57 if(volumeLevel[level]) 58 { 59 volumeLevel[level]->unbind(); 60 volumeLevel[level] = 0; 61 } 62 } 63 64 resource->unlock(); 65 } 66 QueryInterface(const IID & iid,void ** object)67 long Direct3DVolumeTexture9::QueryInterface(const IID &iid, void **object) 68 { 69 CriticalSection cs(device); 70 71 TRACE(""); 72 73 if(iid == IID_IDirect3DVolumeTexture9 || 74 iid == IID_IDirect3DBaseTexture9 || 75 iid == IID_IDirect3DResource9 || 76 iid == IID_IUnknown) 77 { 78 AddRef(); 79 *object = this; 80 81 return S_OK; 82 } 83 84 *object = 0; 85 86 return NOINTERFACE(iid); 87 } 88 AddRef()89 unsigned long Direct3DVolumeTexture9::AddRef() 90 { 91 TRACE(""); 92 93 return Direct3DBaseTexture9::AddRef(); 94 } 95 Release()96 unsigned long Direct3DVolumeTexture9::Release() 97 { 98 TRACE(""); 99 100 return Direct3DBaseTexture9::Release(); 101 } 102 FreePrivateData(const GUID & guid)103 long Direct3DVolumeTexture9::FreePrivateData(const GUID &guid) 104 { 105 CriticalSection cs(device); 106 107 TRACE(""); 108 109 return Direct3DBaseTexture9::FreePrivateData(guid); 110 } 111 GetPrivateData(const GUID & guid,void * data,unsigned long * size)112 long Direct3DVolumeTexture9::GetPrivateData(const GUID &guid, void *data, unsigned long *size) 113 { 114 CriticalSection cs(device); 115 116 TRACE(""); 117 118 return Direct3DBaseTexture9::GetPrivateData(guid, data, size); 119 } 120 PreLoad()121 void Direct3DVolumeTexture9::PreLoad() 122 { 123 CriticalSection cs(device); 124 125 TRACE(""); 126 127 Direct3DBaseTexture9::PreLoad(); 128 } 129 SetPrivateData(const GUID & guid,const void * data,unsigned long size,unsigned long flags)130 long Direct3DVolumeTexture9::SetPrivateData(const GUID &guid, const void *data, unsigned long size, unsigned long flags) 131 { 132 CriticalSection cs(device); 133 134 TRACE(""); 135 136 return Direct3DBaseTexture9::SetPrivateData(guid, data, size, flags); 137 } 138 GetDevice(IDirect3DDevice9 ** device)139 long Direct3DVolumeTexture9::GetDevice(IDirect3DDevice9 **device) 140 { 141 CriticalSection(this->device); 142 143 TRACE(""); 144 145 return Direct3DBaseTexture9::GetDevice(device); 146 } 147 SetPriority(unsigned long newPriority)148 unsigned long Direct3DVolumeTexture9::SetPriority(unsigned long newPriority) 149 { 150 CriticalSection cs(device); 151 152 TRACE(""); 153 154 return Direct3DBaseTexture9::SetPriority(newPriority); 155 } 156 GetPriority()157 unsigned long Direct3DVolumeTexture9::GetPriority() 158 { 159 CriticalSection cs(device); 160 161 TRACE(""); 162 163 return Direct3DBaseTexture9::GetPriority(); 164 } 165 GetType()166 D3DRESOURCETYPE Direct3DVolumeTexture9::GetType() 167 { 168 CriticalSection cs(device); 169 170 TRACE(""); 171 172 return Direct3DBaseTexture9::GetType(); 173 } 174 GenerateMipSubLevels()175 void Direct3DVolumeTexture9::GenerateMipSubLevels() 176 { 177 CriticalSection cs(device); 178 179 TRACE(""); 180 181 if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !volumeLevel[0]->hasDirtyMipmaps()) 182 { 183 return; 184 } 185 186 resource->lock(sw::PUBLIC); 187 188 for(unsigned int i = 0; i < levels - 1; i++) 189 { 190 Direct3DVolume9 *source = volumeLevel[i]; 191 Direct3DVolume9 *dest = volumeLevel[i + 1]; 192 193 source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); 194 dest->lockInternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC); 195 196 int sWidth = source->getWidth(); 197 int sHeight = source->getHeight(); 198 int sDepth = source->getDepth(); 199 200 int dWidth = dest->getWidth(); 201 int dHeight = dest->getHeight(); 202 int dDepth = dest->getDepth(); 203 204 D3DTEXTUREFILTERTYPE filter = GetAutoGenFilterType(); 205 206 float w = (float)sWidth / (float)dWidth; 207 float h = (float)sHeight / (float)dHeight; 208 float d = (float)sDepth / (float)dDepth; 209 210 float z = 0.5f * d; 211 212 for(int k = 0; k < dDepth; k++) 213 { 214 float y = 0.5f * h; 215 216 for(int j = 0; j < dHeight; j++) 217 { 218 float x = 0.5f * w; 219 220 for(int i = 0; i < dWidth; i++) 221 { 222 dest->copyInternal(source, i, j, k, x, y, z, filter > D3DTEXF_POINT); 223 224 x += w; 225 } 226 227 y += h; 228 } 229 230 z += d; 231 } 232 233 source->unlockInternal(); 234 dest->unlockInternal(); 235 } 236 237 volumeLevel[0]->cleanMipmaps(); 238 239 resource->unlock(); 240 } 241 GetAutoGenFilterType()242 D3DTEXTUREFILTERTYPE Direct3DVolumeTexture9::GetAutoGenFilterType() 243 { 244 CriticalSection cs(device); 245 246 TRACE(""); 247 248 return Direct3DBaseTexture9::GetAutoGenFilterType(); 249 } 250 GetLevelCount()251 unsigned long Direct3DVolumeTexture9::GetLevelCount() 252 { 253 CriticalSection cs(device); 254 255 TRACE(""); 256 257 return Direct3DBaseTexture9::GetLevelCount(); 258 } 259 GetLOD()260 unsigned long Direct3DVolumeTexture9::GetLOD() 261 { 262 CriticalSection cs(device); 263 264 TRACE(""); 265 266 return Direct3DBaseTexture9::GetLOD(); 267 } 268 SetAutoGenFilterType(D3DTEXTUREFILTERTYPE filterType)269 long Direct3DVolumeTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE filterType) 270 { 271 CriticalSection cs(device); 272 273 TRACE(""); 274 275 return Direct3DBaseTexture9::SetAutoGenFilterType(filterType); 276 } 277 SetLOD(unsigned long newLOD)278 unsigned long Direct3DVolumeTexture9::SetLOD(unsigned long newLOD) 279 { 280 CriticalSection cs(device); 281 282 TRACE(""); 283 284 return Direct3DBaseTexture9::SetLOD(newLOD); 285 } 286 GetVolumeLevel(unsigned int level,IDirect3DVolume9 ** volume)287 long Direct3DVolumeTexture9::GetVolumeLevel(unsigned int level, IDirect3DVolume9 **volume) 288 { 289 CriticalSection cs(device); 290 291 TRACE(""); 292 293 *volume = 0; 294 295 if(level >= GetLevelCount() || !volumeLevel[level]) 296 { 297 return INVALIDCALL(); 298 } 299 300 volumeLevel[level]->AddRef(); 301 *volume = volumeLevel[level]; 302 303 return D3D_OK; 304 } 305 LockBox(unsigned int level,D3DLOCKED_BOX * lockedVolume,const D3DBOX * box,unsigned long flags)306 long Direct3DVolumeTexture9::LockBox(unsigned int level, D3DLOCKED_BOX *lockedVolume, const D3DBOX *box, unsigned long flags) 307 { 308 CriticalSection cs(device); 309 310 TRACE(""); 311 312 if(!lockedVolume || level >= GetLevelCount() || !volumeLevel[level]) 313 { 314 return INVALIDCALL(); 315 } 316 317 return volumeLevel[level]->LockBox(lockedVolume, box, flags); 318 } 319 UnlockBox(unsigned int level)320 long Direct3DVolumeTexture9::UnlockBox(unsigned int level) 321 { 322 CriticalSection cs(device); 323 324 TRACE(""); 325 326 if(level >= GetLevelCount() || !volumeLevel[level]) 327 { 328 return INVALIDCALL(); 329 } 330 331 return volumeLevel[level]->UnlockBox(); 332 } 333 AddDirtyBox(const D3DBOX * dirtyBox)334 long Direct3DVolumeTexture9::AddDirtyBox(const D3DBOX *dirtyBox) 335 { 336 CriticalSection cs(device); 337 338 TRACE(""); 339 340 // UNIMPLEMENTED(); 341 342 return D3D_OK; 343 } 344 GetLevelDesc(unsigned int level,D3DVOLUME_DESC * description)345 long Direct3DVolumeTexture9::GetLevelDesc(unsigned int level, D3DVOLUME_DESC *description) 346 { 347 CriticalSection cs(device); 348 349 TRACE(""); 350 351 if(!description || level >= GetLevelCount() || !volumeLevel[level]) 352 { 353 return INVALIDCALL(); 354 } 355 356 return volumeLevel[level]->GetDesc(description); 357 } 358 getInternalVolumeLevel(unsigned int level)359 Direct3DVolume9 *Direct3DVolumeTexture9::getInternalVolumeLevel(unsigned int level) 360 { 361 return volumeLevel[level]; 362 } 363 } 364