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