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