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 "Direct3DSurface9.hpp" 16 17 #include "Direct3DDevice9.hpp" 18 #include "Direct3DBaseTexture9.hpp" 19 #include "Capabilities.hpp" 20 #include "Resource.hpp" 21 #include "Debug.hpp" 22 23 #include <malloc.h> 24 #include <assert.h> 25 26 extern bool quadLayoutEnabled; 27 28 namespace D3D9 29 { getParentResource(Unknown * container)30 sw::Resource *getParentResource(Unknown *container) 31 { 32 Direct3DBaseTexture9 *baseTexture = dynamic_cast<Direct3DBaseTexture9*>(container); 33 34 if(baseTexture) 35 { 36 return baseTexture->getResource(); 37 } 38 39 return 0; 40 } 41 sampleCount(D3DMULTISAMPLE_TYPE multiSample,unsigned int quality)42 int sampleCount(D3DMULTISAMPLE_TYPE multiSample, unsigned int quality) 43 { 44 if(multiSample == D3DMULTISAMPLE_NONMASKABLE) 45 { 46 switch(quality) 47 { 48 case 0: return 2; 49 case 1: return 4; 50 case 2: return 8; 51 case 3: return 16; 52 } 53 } 54 else if(multiSample == D3DMULTISAMPLE_2_SAMPLES) 55 { 56 return 2; 57 } 58 else if(multiSample == D3DMULTISAMPLE_4_SAMPLES) 59 { 60 return 4; 61 } 62 else if(multiSample == D3DMULTISAMPLE_8_SAMPLES) 63 { 64 return 8; 65 } 66 else if(multiSample == D3DMULTISAMPLE_16_SAMPLES) 67 { 68 return 16; 69 } 70 71 return 1; 72 } 73 isLockable(D3DPOOL pool,unsigned long usage,bool lockableOverride)74 bool isLockable(D3DPOOL pool, unsigned long usage, bool lockableOverride) 75 { 76 return (pool != D3DPOOL_DEFAULT) || (usage & D3DUSAGE_DYNAMIC) || lockableOverride; 77 } 78 Direct3DSurface9(Direct3DDevice9 * device,Unknown * container,int width,int height,D3DFORMAT format,D3DPOOL pool,D3DMULTISAMPLE_TYPE multiSample,unsigned int quality,bool lockableOverride,unsigned long usage)79 Direct3DSurface9::Direct3DSurface9(Direct3DDevice9 *device, Unknown *container, int width, int height, D3DFORMAT format, D3DPOOL pool, D3DMULTISAMPLE_TYPE multiSample, unsigned int quality, bool lockableOverride, unsigned long usage) : Direct3DResource9(device, D3DRTYPE_SURFACE, pool, memoryUsage(width, height, format)), Surface(getParentResource(container), width, height, sampleCount(multiSample, quality), translateFormat(format), isLockable(pool, usage, lockableOverride), (usage & D3DUSAGE_RENDERTARGET) || (usage & D3DUSAGE_DEPTHSTENCIL)), container(container), width(width), height(height), format(format), pool(pool), multiSample(multiSample), quality(quality), lockable(isLockable(pool, usage, lockableOverride)), usage(usage) 80 { 81 parentTexture = dynamic_cast<Direct3DBaseTexture9*>(container); 82 } 83 ~Direct3DSurface9()84 Direct3DSurface9::~Direct3DSurface9() 85 { 86 } 87 QueryInterface(const IID & iid,void ** object)88 long Direct3DSurface9::QueryInterface(const IID &iid, void **object) 89 { 90 CriticalSection cs(device); 91 92 TRACE(""); 93 94 if(iid == IID_IDirect3DSurface9 || 95 iid == IID_IDirect3DResource9 || 96 iid == IID_IUnknown) 97 { 98 AddRef(); 99 *object = this; 100 101 return S_OK; 102 } 103 104 *object = 0; 105 106 return NOINTERFACE(iid); 107 } 108 AddRef()109 unsigned long Direct3DSurface9::AddRef() 110 { 111 TRACE(""); 112 113 if(parentTexture) 114 { 115 return parentTexture->AddRef(); 116 } 117 118 return Direct3DResource9::AddRef(); 119 } 120 Release()121 unsigned long Direct3DSurface9::Release() 122 { 123 TRACE(""); 124 125 if(parentTexture) 126 { 127 return parentTexture->Release(); 128 } 129 130 return Direct3DResource9::Release(); 131 } 132 FreePrivateData(const GUID & guid)133 long Direct3DSurface9::FreePrivateData(const GUID &guid) 134 { 135 CriticalSection cs(device); 136 137 TRACE(""); 138 139 return Direct3DResource9::FreePrivateData(guid); 140 } 141 GetPrivateData(const GUID & guid,void * data,unsigned long * size)142 long Direct3DSurface9::GetPrivateData(const GUID &guid, void *data, unsigned long *size) 143 { 144 CriticalSection cs(device); 145 146 TRACE(""); 147 148 return Direct3DResource9::GetPrivateData(guid, data, size); 149 } 150 PreLoad()151 void Direct3DSurface9::PreLoad() 152 { 153 CriticalSection cs(device); 154 155 TRACE(""); 156 157 Direct3DResource9::PreLoad(); 158 } 159 SetPrivateData(const GUID & guid,const void * data,unsigned long size,unsigned long flags)160 long Direct3DSurface9::SetPrivateData(const GUID &guid, const void *data, unsigned long size, unsigned long flags) 161 { 162 CriticalSection cs(device); 163 164 TRACE(""); 165 166 return Direct3DResource9::SetPrivateData(guid, data, size, flags); 167 } 168 GetDevice(IDirect3DDevice9 ** device)169 long Direct3DSurface9::GetDevice(IDirect3DDevice9 **device) 170 { 171 CriticalSection cs(this->device); 172 173 TRACE(""); 174 175 return Direct3DResource9::GetDevice(device); 176 } 177 SetPriority(unsigned long newPriority)178 unsigned long Direct3DSurface9::SetPriority(unsigned long newPriority) 179 { 180 CriticalSection cs(device); 181 182 TRACE(""); 183 184 return Direct3DResource9::SetPriority(newPriority); 185 } 186 GetPriority()187 unsigned long Direct3DSurface9::GetPriority() 188 { 189 CriticalSection cs(device); 190 191 TRACE(""); 192 193 return Direct3DResource9::GetPriority(); 194 } 195 GetType()196 D3DRESOURCETYPE Direct3DSurface9::GetType() 197 { 198 CriticalSection cs(device); 199 200 TRACE(""); 201 202 return Direct3DResource9::GetType(); 203 } 204 GetDC(HDC * deviceContext)205 long Direct3DSurface9::GetDC(HDC *deviceContext) 206 { 207 CriticalSection cs(device); 208 209 TRACE(""); 210 211 if(!deviceContext) 212 { 213 return INVALIDCALL(); 214 } 215 216 UNIMPLEMENTED(); 217 218 return D3D_OK; 219 } 220 ReleaseDC(HDC deviceContext)221 long Direct3DSurface9::ReleaseDC(HDC deviceContext) 222 { 223 CriticalSection cs(device); 224 225 TRACE(""); 226 227 UNIMPLEMENTED(); 228 229 return D3D_OK; 230 } 231 LockRect(D3DLOCKED_RECT * lockedRect,const RECT * rect,unsigned long flags)232 long Direct3DSurface9::LockRect(D3DLOCKED_RECT *lockedRect, const RECT *rect, unsigned long flags) 233 { 234 CriticalSection cs(device); 235 236 TRACE("D3DLOCKED_RECT *lockedRect = 0x%0.8p, const RECT *rect = 0x%0.8p, unsigned long flags = %d", lockedRect, rect, flags); 237 238 if(!lockedRect) 239 { 240 return INVALIDCALL(); 241 } 242 243 lockedRect->Pitch = 0; 244 lockedRect->pBits = 0; 245 246 if(!lockable) 247 { 248 return INVALIDCALL(); 249 } 250 251 lockedRect->Pitch = getExternalPitchB(); 252 253 sw::Lock lock = sw::LOCK_READWRITE; 254 255 if(flags & D3DLOCK_DISCARD) 256 { 257 lock = sw::LOCK_DISCARD; 258 } 259 260 if(flags & D3DLOCK_READONLY) 261 { 262 lock = sw::LOCK_READONLY; 263 } 264 265 if(rect) 266 { 267 lockedRect->pBits = lockExternal(rect->left, rect->top, 0, lock, sw::PUBLIC); 268 } 269 else 270 { 271 lockedRect->pBits = lockExternal(0, 0, 0, lock, sw::PUBLIC); 272 } 273 274 return D3D_OK; 275 } 276 UnlockRect()277 long Direct3DSurface9::UnlockRect() 278 { 279 CriticalSection cs(device); 280 281 TRACE(""); 282 283 unlockExternal(); 284 285 return D3D_OK; 286 } 287 GetContainer(const IID & iid,void ** container)288 long Direct3DSurface9::GetContainer(const IID &iid, void **container) 289 { 290 CriticalSection cs(device); 291 292 TRACE(""); 293 294 if(!container) 295 { 296 return INVALIDCALL(); 297 } 298 299 long result = this->container->QueryInterface(iid, container); 300 301 if(result == S_OK) 302 { 303 return D3D_OK; 304 } 305 306 return INVALIDCALL(); 307 } 308 GetDesc(D3DSURFACE_DESC * description)309 long Direct3DSurface9::GetDesc(D3DSURFACE_DESC *description) 310 { 311 CriticalSection cs(device); 312 313 TRACE(""); 314 315 if(!description) 316 { 317 return INVALIDCALL(); 318 } 319 320 description->Format = format; 321 description->Pool = pool; 322 description->Type = D3DRTYPE_SURFACE; 323 description->Height = height; 324 description->Width = width; 325 description->MultiSampleType = multiSample; 326 description->MultiSampleQuality = quality; 327 description->Usage = usage; 328 329 return D3D_OK; 330 } 331 translateFormat(D3DFORMAT format)332 sw::Format Direct3DSurface9::translateFormat(D3DFORMAT format) 333 { 334 switch(format) 335 { 336 #if S3TC_SUPPORT 337 case D3DFMT_NULL: return sw::FORMAT_NULL; 338 case D3DFMT_DXT1: return sw::FORMAT_DXT1; 339 case D3DFMT_DXT2: return sw::FORMAT_DXT3; 340 case D3DFMT_DXT3: return sw::FORMAT_DXT3; 341 case D3DFMT_DXT4: return sw::FORMAT_DXT5; 342 case D3DFMT_DXT5: return sw::FORMAT_DXT5; 343 case D3DFMT_ATI1: return sw::FORMAT_ATI1; 344 case D3DFMT_ATI2: return sw::FORMAT_ATI2; 345 #endif 346 case D3DFMT_R3G3B2: return sw::FORMAT_R3G3B2; 347 case D3DFMT_A8R3G3B2: return sw::FORMAT_A8R3G3B2; 348 case D3DFMT_X4R4G4B4: return sw::FORMAT_X4R4G4B4; 349 case D3DFMT_A4R4G4B4: return sw::FORMAT_A4R4G4B4; 350 case D3DFMT_A8R8G8B8: return sw::FORMAT_A8R8G8B8; 351 case D3DFMT_A8B8G8R8: return sw::FORMAT_A8B8G8R8; 352 case D3DFMT_G16R16: return sw::FORMAT_G16R16; 353 case D3DFMT_A2R10G10B10: return sw::FORMAT_A2R10G10B10; 354 case D3DFMT_A2B10G10R10: return sw::FORMAT_A2B10G10R10; 355 case D3DFMT_A16B16G16R16: return sw::FORMAT_A16B16G16R16; 356 case D3DFMT_P8: return sw::FORMAT_P8; 357 case D3DFMT_A8P8: return sw::FORMAT_A8P8; 358 case D3DFMT_A8: return sw::FORMAT_A8; 359 case D3DFMT_R5G6B5: return sw::FORMAT_R5G6B5; 360 case D3DFMT_X1R5G5B5: return sw::FORMAT_X1R5G5B5; 361 case D3DFMT_A1R5G5B5: return sw::FORMAT_A1R5G5B5; 362 case D3DFMT_R8G8B8: return sw::FORMAT_R8G8B8; 363 case D3DFMT_X8R8G8B8: return sw::FORMAT_X8R8G8B8; 364 case D3DFMT_X8B8G8R8: return sw::FORMAT_X8B8G8R8; 365 case D3DFMT_V8U8: return sw::FORMAT_V8U8; 366 case D3DFMT_L6V5U5: return sw::FORMAT_L6V5U5; 367 case D3DFMT_Q8W8V8U8: return sw::FORMAT_Q8W8V8U8; 368 case D3DFMT_X8L8V8U8: return sw::FORMAT_X8L8V8U8; 369 case D3DFMT_A2W10V10U10: return sw::FORMAT_A2W10V10U10; 370 case D3DFMT_V16U16: return sw::FORMAT_V16U16; 371 case D3DFMT_Q16W16V16U16: return sw::FORMAT_Q16W16V16U16; 372 case D3DFMT_L8: return sw::FORMAT_L8; 373 case D3DFMT_A4L4: return sw::FORMAT_A4L4; 374 case D3DFMT_L16: return sw::FORMAT_L16; 375 case D3DFMT_A8L8: return sw::FORMAT_A8L8; 376 case D3DFMT_R16F: return sw::FORMAT_R16F; 377 case D3DFMT_G16R16F: return sw::FORMAT_G16R16F; 378 case D3DFMT_A16B16G16R16F: return sw::FORMAT_A16B16G16R16F; 379 case D3DFMT_R32F: return sw::FORMAT_R32F; 380 case D3DFMT_G32R32F: return sw::FORMAT_G32R32F; 381 case D3DFMT_A32B32G32R32F: return sw::FORMAT_A32B32G32R32F; 382 case D3DFMT_D16: return sw::FORMAT_D16; 383 case D3DFMT_D32: return sw::FORMAT_D32; 384 case D3DFMT_D24X8: return sw::FORMAT_D24X8; 385 case D3DFMT_D24S8: return sw::FORMAT_D24S8; 386 case D3DFMT_D24FS8: return sw::FORMAT_D24FS8; 387 case D3DFMT_D32F_LOCKABLE: return sw::FORMAT_D32F_LOCKABLE; 388 case D3DFMT_DF24: return sw::FORMAT_DF24S8; 389 case D3DFMT_DF16: return sw::FORMAT_DF16S8; 390 case D3DFMT_INTZ: return sw::FORMAT_INTZ; 391 default: 392 ASSERT(false); 393 } 394 395 return sw::FORMAT_NULL; 396 } 397 bytes(D3DFORMAT format)398 int Direct3DSurface9::bytes(D3DFORMAT format) 399 { 400 return Surface::bytes(translateFormat(format)); 401 } 402 memoryUsage(int width,int height,D3DFORMAT format)403 unsigned int Direct3DSurface9::memoryUsage(int width, int height, D3DFORMAT format) 404 { 405 return Surface::size(width, height, 1, translateFormat(format)); 406 } 407 } 408