|
@@ -1,1143 +1,1143 @@
|
|
|
-#include "BsCoreThread.h"
|
|
|
|
|
-#include "BsD3D9Texture.h"
|
|
|
|
|
-#include "BsD3D9PixelBuffer.h"
|
|
|
|
|
-#include "BsException.h"
|
|
|
|
|
-#include "BsBitwise.h"
|
|
|
|
|
-#include "BsD3D9Mappings.h"
|
|
|
|
|
-#include "BsD3D9RenderAPI.h"
|
|
|
|
|
-#include "BsD3D9TextureManager.h"
|
|
|
|
|
-#include "BsD3D9Device.h"
|
|
|
|
|
-#include "BsD3D9DeviceManager.h"
|
|
|
|
|
-#include "BsD3D9ResourceManager.h"
|
|
|
|
|
-#include "BsRenderStats.h"
|
|
|
|
|
-#include "BsPixelData.h"
|
|
|
|
|
-
|
|
|
|
|
-namespace BansheeEngine
|
|
|
|
|
-{
|
|
|
|
|
- D3D9TextureCore::D3D9TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
|
|
|
|
|
- PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const PixelDataPtr& initialData)
|
|
|
|
|
- :TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, initialData),
|
|
|
|
|
- mD3DPool(D3DPOOL_MANAGED), mDynamicTextures(false), mHwGammaReadSupported(false), mHwGammaWriteSupported(false),
|
|
|
|
|
- mMultisampleType(D3DMULTISAMPLE_NONE), mMultisampleQuality(0), mIsBindableAsShaderResource(true)
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3D9TextureCore::~D3D9TextureCore()
|
|
|
|
|
- {
|
|
|
|
|
- THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
-
|
|
|
|
|
- for (auto& resPair : mMapDeviceToTextureResources)
|
|
|
|
|
- {
|
|
|
|
|
- TextureResources* textureResource = resPair.second;
|
|
|
|
|
-
|
|
|
|
|
- freeTextureResources(resPair.first, textureResource);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- for (auto& resPair : mMapDeviceToTextureResources)
|
|
|
|
|
- {
|
|
|
|
|
- TextureResources* textureResource = resPair.second;
|
|
|
|
|
-
|
|
|
|
|
- if (textureResource != nullptr)
|
|
|
|
|
- bs_delete(textureResource);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- mMapDeviceToTextureResources.clear();
|
|
|
|
|
- mSurfaceList.clear();
|
|
|
|
|
-
|
|
|
|
|
- BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::initialize()
|
|
|
|
|
- {
|
|
|
|
|
- THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
-
|
|
|
|
|
- for (UINT32 i = 0; i < D3D9RenderAPI::getResourceCreationDeviceCount(); ++i)
|
|
|
|
|
- {
|
|
|
|
|
- IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getResourceCreationDevice(i);
|
|
|
|
|
-
|
|
|
|
|
- createInternalResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
|
|
|
|
|
- TextureCore::initialize();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PixelData D3D9TextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
|
|
|
|
|
- {
|
|
|
|
|
- if (mProperties.getMultisampleCount() > 1)
|
|
|
|
|
- BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
|
|
|
|
|
-
|
|
|
|
|
- if(mLockedBuffer != nullptr)
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
|
|
|
|
|
-
|
|
|
|
|
- if (mProperties.getUsage() == TU_DEPTHSTENCIL)
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Cannot lock a depth stencil texture.");
|
|
|
|
|
-
|
|
|
|
|
- UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
|
|
|
|
|
- UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
|
|
|
|
|
- UINT32 mipDepth = mProperties.getDepth() >> mipLevel;
|
|
|
|
|
-
|
|
|
|
|
- PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
|
|
|
|
|
-
|
|
|
|
|
- mLockedBuffer = getBuffer(face, mipLevel);
|
|
|
|
|
- lockedArea.setExternalBuffer((UINT8*)mLockedBuffer->lock(options));
|
|
|
|
|
-
|
|
|
|
|
- return lockedArea;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::unlockImpl()
|
|
|
|
|
- {
|
|
|
|
|
- if(mLockedBuffer == nullptr)
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
|
|
|
|
|
-
|
|
|
|
|
- mLockedBuffer->unlock();
|
|
|
|
|
- mLockedBuffer = nullptr;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
|
|
|
|
|
- {
|
|
|
|
|
- if (mProperties.getMultisampleCount() > 1)
|
|
|
|
|
- BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
|
|
|
|
|
-
|
|
|
|
|
- if (mProperties.getUsage() == TU_DEPTHSTENCIL || mProperties.getUsage() == TU_RENDERTARGET) // Render targets cannot be locked normally
|
|
|
|
|
- {
|
|
|
|
|
- IDirect3DDevice9* device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
-
|
|
|
|
|
- D3D9PixelBuffer* sourceBuffer = static_cast<D3D9PixelBuffer*>(getBuffer(face, mipLevel).get());
|
|
|
|
|
-
|
|
|
|
|
- UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
|
|
|
|
|
- UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
|
|
|
|
|
- D3DFORMAT format = chooseD3DFormat(device);
|
|
|
|
|
-
|
|
|
|
|
- // Note: I'm allocating and releasing a texture every time we read.
|
|
|
|
|
- // I might consider adding a flag to keep this texture permanent which would make reading
|
|
|
|
|
- // faster but at the cost of double the memory.
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DTexture9* stagingTexture = nullptr;
|
|
|
|
|
- HRESULT hr = D3DXCreateTexture(device, (UINT)mipWidth, (UINT)mipHeight, 1,
|
|
|
|
|
- 0, format, D3DPOOL_SYSTEMMEM, &stagingTexture);
|
|
|
|
|
-
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Failed to create a texture: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DSurface9* stagingSurface = nullptr;
|
|
|
|
|
- hr = stagingTexture->GetSurfaceLevel(0, &stagingSurface);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Failed to retrieve a texture surface: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- hr = device->GetRenderTargetData(sourceBuffer->getSurface(device), stagingSurface);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Failed to retrieve render target data: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PixelData myData(mipWidth, mipHeight, 1, mProperties.getFormat());
|
|
|
|
|
-
|
|
|
|
|
- D3DLOCKED_RECT lrect;
|
|
|
|
|
- hr = stagingSurface->LockRect(&lrect, nullptr, D3DLOCK_READONLY);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Failed to lock surface: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3D9PixelBuffer::initPixelDataFromD3DLock(myData, lrect);
|
|
|
|
|
-
|
|
|
|
|
-#if BS_DEBUG_MODE
|
|
|
|
|
- if (dest.getConsecutiveSize() != myData.getConsecutiveSize())
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
|
|
|
|
|
-#endif
|
|
|
|
|
-
|
|
|
|
|
- PixelUtil::bulkPixelConversion(myData, dest);
|
|
|
|
|
-
|
|
|
|
|
- hr = stagingSurface->UnlockRect();
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Failed to unlock surface: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- SAFE_RELEASE(stagingSurface);
|
|
|
|
|
- SAFE_RELEASE(stagingTexture);
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
|
|
|
|
|
-
|
|
|
|
|
-#if BS_DEBUG_MODE
|
|
|
|
|
- if (dest.getConsecutiveSize() != myData.getConsecutiveSize())
|
|
|
|
|
- {
|
|
|
|
|
- unlock();
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
|
|
|
|
|
- }
|
|
|
|
|
-#endif
|
|
|
|
|
-
|
|
|
|
|
- PixelUtil::bulkPixelConversion(myData, dest);
|
|
|
|
|
-
|
|
|
|
|
- unlock();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
|
|
|
|
|
- {
|
|
|
|
|
- if (mProperties.getMultisampleCount() > 1)
|
|
|
|
|
- BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
|
|
|
|
|
-
|
|
|
|
|
- if (mProperties.getUsage() == TU_DYNAMIC || mProperties.getUsage() == TU_STATIC)
|
|
|
|
|
- {
|
|
|
|
|
- PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
|
|
|
|
|
- PixelUtil::bulkPixelConversion(src, myData);
|
|
|
|
|
- unlock();
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage()));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
|
|
|
|
|
- {
|
|
|
|
|
- THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
-
|
|
|
|
|
- TextureType texType = mProperties.getTextureType();
|
|
|
|
|
-
|
|
|
|
|
- if (texType == TEX_TYPE_1D || texType == TEX_TYPE_3D)
|
|
|
|
|
- BS_EXCEPT(NotImplementedException, "Copy not implemented for 1D and 3D textures yet.");
|
|
|
|
|
-
|
|
|
|
|
- HRESULT hr;
|
|
|
|
|
- D3D9TextureCore* other = static_cast<D3D9TextureCore*>(target.get());
|
|
|
|
|
-
|
|
|
|
|
- for (auto& resPair : mMapDeviceToTextureResources)
|
|
|
|
|
- {
|
|
|
|
|
- TextureResources* srcTextureResource = resPair.second;
|
|
|
|
|
- TextureResources* dstTextureResource = other->getTextureResources(resPair.first);
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DSurface9 *sourceSurface = nullptr;
|
|
|
|
|
- IDirect3DSurface9 *destSurface = nullptr;
|
|
|
|
|
-
|
|
|
|
|
- if (texType == TEX_TYPE_2D && srcTextureResource->pNormTex != nullptr && dstTextureResource->pNormTex != nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- if(FAILED(hr = srcTextureResource->pNormTex->GetSurfaceLevel(srcMipLevel, &sourceSurface)))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Cannot retrieve source surface for copy: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if(FAILED(hr = dstTextureResource->pNormTex->GetSurfaceLevel(destMipLevel, &destSurface)))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Cannot retrieve destination surface for copy: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- else if (texType == TEX_TYPE_CUBE_MAP && srcTextureResource->pCubeTex != nullptr && dstTextureResource->pCubeTex != nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- IDirect3DSurface9 *sourceSurface = nullptr;
|
|
|
|
|
- if (FAILED(hr = srcTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)srcFace, srcMipLevel, &sourceSurface)))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Cannot retrieve source surface for copy: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DSurface9 *destSurface = nullptr;
|
|
|
|
|
- if (FAILED(hr = dstTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)destFace, destMipLevel, &destSurface)))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Cannot retrieve destination surface for copy: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (sourceSurface != nullptr && destSurface != nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- D3DSURFACE_DESC desc;
|
|
|
|
|
-
|
|
|
|
|
- sourceSurface->GetDesc(&desc);
|
|
|
|
|
- if (desc.Pool != D3DPOOL_DEFAULT)
|
|
|
|
|
- BS_EXCEPT(InvalidStateException, "Source surface must be in the default pool.");
|
|
|
|
|
-
|
|
|
|
|
- destSurface->GetDesc(&desc);
|
|
|
|
|
- if (desc.Pool != D3DPOOL_DEFAULT)
|
|
|
|
|
- BS_EXCEPT(InvalidStateException, "Destination surface must be in the default pool.");
|
|
|
|
|
-
|
|
|
|
|
- if (FAILED(hr = resPair.first->StretchRect(sourceSurface, NULL, destSurface, NULL, D3DTEXF_NONE)))
|
|
|
|
|
- {
|
|
|
|
|
- String msg = DXGetErrorDescription(hr);
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "StretchRect failed during copy: " + msg);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- SAFE_RELEASE(sourceSurface);
|
|
|
|
|
- SAFE_RELEASE(destSurface);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3D9TextureCore::TextureResources* D3D9TextureCore::getTextureResources(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
|
|
|
|
|
-
|
|
|
|
|
- if (iterFind == mMapDeviceToTextureResources.end())
|
|
|
|
|
- return nullptr;
|
|
|
|
|
-
|
|
|
|
|
- return iterFind->second;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3D9TextureCore::TextureResources* D3D9TextureCore::allocateTextureResources(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- assert(mMapDeviceToTextureResources.find(d3d9Device) == mMapDeviceToTextureResources.end());
|
|
|
|
|
-
|
|
|
|
|
- TextureResources* textureResources = bs_new<TextureResources>();
|
|
|
|
|
-
|
|
|
|
|
- textureResources->pNormTex = nullptr;
|
|
|
|
|
- textureResources->pCubeTex = nullptr;
|
|
|
|
|
- textureResources->pVolumeTex = nullptr;
|
|
|
|
|
- textureResources->pBaseTex = nullptr;
|
|
|
|
|
- textureResources->pMultisampleSurface = nullptr;
|
|
|
|
|
- textureResources->pDepthStencilSurface = nullptr;
|
|
|
|
|
-
|
|
|
|
|
- mMapDeviceToTextureResources[d3d9Device] = textureResources;
|
|
|
|
|
-
|
|
|
|
|
- return textureResources;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::freeTextureResources(IDirect3DDevice9* d3d9Device, D3D9TextureCore::TextureResources* textureResources)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
-
|
|
|
|
|
- // Release surfaces from each mip level.
|
|
|
|
|
- for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
|
|
|
|
|
-
|
|
|
|
|
- pixelBuffer->releaseSurfaces(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Release the rest of the resources.
|
|
|
|
|
- SAFE_RELEASE(textureResources->pBaseTex);
|
|
|
|
|
- SAFE_RELEASE(textureResources->pNormTex);
|
|
|
|
|
- SAFE_RELEASE(textureResources->pCubeTex);
|
|
|
|
|
- SAFE_RELEASE(textureResources->pVolumeTex);
|
|
|
|
|
- SAFE_RELEASE(textureResources->pMultisampleSurface);
|
|
|
|
|
- SAFE_RELEASE(textureResources->pDepthStencilSurface);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- UINT32 D3D9TextureCore::calculateSize() const
|
|
|
|
|
- {
|
|
|
|
|
- UINT32 instanceSize = mProperties.getNumFaces() *
|
|
|
|
|
- PixelUtil::getMemorySize(mProperties.getWidth(), mProperties.getHeight(),
|
|
|
|
|
- mProperties.getDepth(), mProperties.getFormat());
|
|
|
|
|
-
|
|
|
|
|
- return instanceSize * (UINT32)mMapDeviceToTextureResources.size();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::determinePool()
|
|
|
|
|
- {
|
|
|
|
|
- if (useDefaultPool())
|
|
|
|
|
- mD3DPool = D3DPOOL_DEFAULT;
|
|
|
|
|
- else
|
|
|
|
|
- mD3DPool = D3DPOOL_MANAGED;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::createInternalResources(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- switch (mProperties.getTextureType())
|
|
|
|
|
- {
|
|
|
|
|
- case TEX_TYPE_1D:
|
|
|
|
|
- case TEX_TYPE_2D:
|
|
|
|
|
- createNormTex(d3d9Device);
|
|
|
|
|
- break;
|
|
|
|
|
- case TEX_TYPE_CUBE_MAP:
|
|
|
|
|
- createCubeTex(d3d9Device);
|
|
|
|
|
- break;
|
|
|
|
|
- case TEX_TYPE_3D:
|
|
|
|
|
- createVolumeTex(d3d9Device);
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Unknown texture type.");
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::createNormTex(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- UINT32 width = mProperties.getWidth();
|
|
|
|
|
- UINT32 height = mProperties.getHeight();
|
|
|
|
|
- int texUsage = mProperties.getUsage();
|
|
|
|
|
- UINT32 origNumMips = mProperties.getNumMipmaps();
|
|
|
|
|
- PixelFormat format = mProperties.getFormat();
|
|
|
|
|
- bool hwGamma = mProperties.isHardwareGammaEnabled();
|
|
|
|
|
- UINT32 sampleCount = mProperties.getMultisampleCount();
|
|
|
|
|
-
|
|
|
|
|
- assert(width > 0 || height > 0);
|
|
|
|
|
-
|
|
|
|
|
- D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
|
|
|
|
|
- if (format != D3D9Mappings::_getPF(d3dPF))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
|
|
|
|
|
- UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
|
|
|
|
|
-
|
|
|
|
|
- DWORD usage = 0;
|
|
|
|
|
- if ((texUsage & TU_RENDERTARGET) != 0)
|
|
|
|
|
- usage = D3DUSAGE_RENDERTARGET;
|
|
|
|
|
- else if ((texUsage & TU_DEPTHSTENCIL) != 0)
|
|
|
|
|
- usage = D3DUSAGE_DEPTHSTENCIL;
|
|
|
|
|
-
|
|
|
|
|
- // Check dynamic textures
|
|
|
|
|
- if (texUsage & TU_DYNAMIC)
|
|
|
|
|
- {
|
|
|
|
|
- if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF))
|
|
|
|
|
- {
|
|
|
|
|
- usage |= D3DUSAGE_DYNAMIC;
|
|
|
|
|
- mDynamicTextures = true;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- mDynamicTextures = false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Check sRGB support
|
|
|
|
|
- if (hwGamma)
|
|
|
|
|
- {
|
|
|
|
|
- mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, false);
|
|
|
|
|
- if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
- mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, true);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Check multisample level
|
|
|
|
|
- if ((texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9RenderAPI* rsys = static_cast<D3D9RenderAPI*>(BansheeEngine::RenderAPICore::instancePtr());
|
|
|
|
|
- rsys->determineMultisampleSettings(d3d9Device, sampleCount, d3dPF, false, &mMultisampleType, &mMultisampleQuality);
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- mMultisampleType = D3DMULTISAMPLE_NONE;
|
|
|
|
|
- mMultisampleQuality = 0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
- const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
-
|
|
|
|
|
- // Check if mip maps are supported on hardware
|
|
|
|
|
- if (numMips > 1 && (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) || (texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- determinePool();
|
|
|
|
|
- TextureResources* textureResources;
|
|
|
|
|
-
|
|
|
|
|
- // Get or create new texture resources structure.
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- if (textureResources != NULL)
|
|
|
|
|
- freeTextureResources(d3d9Device, textureResources);
|
|
|
|
|
- else
|
|
|
|
|
- textureResources = allocateTextureResources(d3d9Device);
|
|
|
|
|
-
|
|
|
|
|
- if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
- {
|
|
|
|
|
- // Create AA surface
|
|
|
|
|
- HRESULT hr = d3d9Device->CreateRenderTarget(width, height, d3dPF,
|
|
|
|
|
- mMultisampleType, mMultisampleQuality,
|
|
|
|
|
- FALSE,
|
|
|
|
|
- &textureResources->pMultisampleSurface, NULL);
|
|
|
|
|
-
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Unable to create AA render target: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
-
|
|
|
|
|
- D3DSURFACE_DESC desc;
|
|
|
|
|
- hr = textureResources->pMultisampleSurface->GetDesc(&desc);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
-
|
|
|
|
|
- mIsBindableAsShaderResource = false; // Cannot bind AA surfaces
|
|
|
|
|
- }
|
|
|
|
|
- else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
- {
|
|
|
|
|
- // Create AA depth stencil surface
|
|
|
|
|
- HRESULT hr = d3d9Device->CreateDepthStencilSurface(width, height, d3dPF,
|
|
|
|
|
- mMultisampleType, mMultisampleQuality,
|
|
|
|
|
- FALSE,
|
|
|
|
|
- &textureResources->pDepthStencilSurface, NULL);
|
|
|
|
|
-
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Unable to create AA depth stencil render target: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
-
|
|
|
|
|
- // Update final parameters as they may differ from requested ones
|
|
|
|
|
- D3DSURFACE_DESC desc;
|
|
|
|
|
- hr = textureResources->pDepthStencilSurface->GetDesc(&desc);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
-
|
|
|
|
|
- mIsBindableAsShaderResource = false; // Cannot bind AA depth buffer
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- // Create normal texture
|
|
|
|
|
- HRESULT hr = D3DXCreateTexture(d3d9Device, (UINT)width, (UINT)height, numMips,
|
|
|
|
|
- usage, d3dPF, mD3DPool, &textureResources->pNormTex);
|
|
|
|
|
-
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- hr = textureResources->pNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Update final parameters as they may differ from requested ones
|
|
|
|
|
- D3DSURFACE_DESC desc;
|
|
|
|
|
- hr = textureResources->pNormTex->GetLevelDesc(0, &desc);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::createCubeTex(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- UINT32 width = mProperties.getWidth();
|
|
|
|
|
- UINT32 height = mProperties.getHeight();
|
|
|
|
|
- int texUsage = mProperties.getUsage();
|
|
|
|
|
- UINT32 origNumMips = mProperties.getNumMipmaps();
|
|
|
|
|
- PixelFormat format = mProperties.getFormat();
|
|
|
|
|
- bool hwGamma = mProperties.isHardwareGammaEnabled();
|
|
|
|
|
-
|
|
|
|
|
- assert(width > 0 || height > 0);
|
|
|
|
|
-
|
|
|
|
|
- D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
|
|
|
|
|
- if (format != D3D9Mappings::_getPF(d3dPF))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
|
|
|
|
|
- DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
|
|
|
|
|
- usage |= (texUsage & TU_DEPTHSTENCIL) ? D3DUSAGE_DEPTHSTENCIL : 0;
|
|
|
|
|
-
|
|
|
|
|
- UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
|
|
|
|
|
-
|
|
|
|
|
- // Check dynamic textures
|
|
|
|
|
- if (texUsage & TU_DYNAMIC)
|
|
|
|
|
- {
|
|
|
|
|
- if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF))
|
|
|
|
|
- {
|
|
|
|
|
- usage |= D3DUSAGE_DYNAMIC;
|
|
|
|
|
- mDynamicTextures = true;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- mDynamicTextures = false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Check sRGB support
|
|
|
|
|
- if (hwGamma)
|
|
|
|
|
- {
|
|
|
|
|
- mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, false);
|
|
|
|
|
- if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
- mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, true);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // No multisampling on cube textures
|
|
|
|
|
- mMultisampleType = D3DMULTISAMPLE_NONE;
|
|
|
|
|
- mMultisampleQuality = 0;
|
|
|
|
|
-
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
- const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
-
|
|
|
|
|
- // Check if mip map cube textures are supported
|
|
|
|
|
- if (numMips > 1 && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- determinePool();
|
|
|
|
|
- TextureResources* textureResources;
|
|
|
|
|
-
|
|
|
|
|
- // Get or create new texture resources structure.
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- if (textureResources != NULL)
|
|
|
|
|
- freeTextureResources(d3d9Device, textureResources);
|
|
|
|
|
- else
|
|
|
|
|
- textureResources = allocateTextureResources(d3d9Device);
|
|
|
|
|
-
|
|
|
|
|
- // Create the texture
|
|
|
|
|
- HRESULT hr = D3DXCreateCubeTexture(d3d9Device, (UINT)width, numMips,
|
|
|
|
|
- usage, d3dPF, mD3DPool, &textureResources->pCubeTex);
|
|
|
|
|
-
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- hr = textureResources->pCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Update final parameters as they may differ from requested ones
|
|
|
|
|
- D3DSURFACE_DESC desc;
|
|
|
|
|
- hr = textureResources->pCubeTex->GetLevelDesc(0, &desc);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::createVolumeTex(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- UINT32 width = mProperties.getWidth();
|
|
|
|
|
- UINT32 height = mProperties.getHeight();
|
|
|
|
|
- UINT32 depth = mProperties.getDepth();
|
|
|
|
|
- int texUsage = mProperties.getUsage();
|
|
|
|
|
- UINT32 origNumMips = mProperties.getNumMipmaps();
|
|
|
|
|
- PixelFormat format = mProperties.getFormat();
|
|
|
|
|
- bool hwGamma = mProperties.isHardwareGammaEnabled();
|
|
|
|
|
-
|
|
|
|
|
- assert(width > 0 && height > 0 && depth > 0);
|
|
|
|
|
-
|
|
|
|
|
- if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as render target !!");
|
|
|
|
|
-
|
|
|
|
|
- if (texUsage & TU_DEPTHSTENCIL)
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as a depth stencil target !!");
|
|
|
|
|
-
|
|
|
|
|
- D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
|
|
|
|
|
- if(format != D3D9Mappings::_getPF(d3dPF))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
|
|
|
|
|
- DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
|
|
|
|
|
- UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
|
|
|
|
|
-
|
|
|
|
|
- // Check dynamic textures
|
|
|
|
|
- if (texUsage & TU_DYNAMIC)
|
|
|
|
|
- {
|
|
|
|
|
- if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF))
|
|
|
|
|
- {
|
|
|
|
|
- usage |= D3DUSAGE_DYNAMIC;
|
|
|
|
|
- mDynamicTextures = true;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- mDynamicTextures = false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Check sRGB support
|
|
|
|
|
- if (hwGamma)
|
|
|
|
|
- {
|
|
|
|
|
- mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, false);
|
|
|
|
|
- if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
- mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, true);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
- const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
-
|
|
|
|
|
- // Check if mip map volume textures are supported
|
|
|
|
|
- if (numMips > 1 && !(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- determinePool();
|
|
|
|
|
- TextureResources* textureResources;
|
|
|
|
|
-
|
|
|
|
|
- // Get or create new texture resources structure.
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- if (textureResources != NULL)
|
|
|
|
|
- freeTextureResources(d3d9Device, textureResources);
|
|
|
|
|
- else
|
|
|
|
|
- textureResources = allocateTextureResources(d3d9Device);
|
|
|
|
|
-
|
|
|
|
|
- // Create the texture
|
|
|
|
|
- HRESULT hr = D3DXCreateVolumeTexture(d3d9Device, (UINT)width, (UINT)height, (UINT)depth,
|
|
|
|
|
- numMips, usage, d3dPF, mD3DPool, &textureResources->pVolumeTex);
|
|
|
|
|
-
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- hr = textureResources->pVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void**)&textureResources->pBaseTex);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Update final parameters as they may differ from requested ones
|
|
|
|
|
- D3DVOLUME_DESC desc;
|
|
|
|
|
- hr = textureResources->pVolumeTex->GetLevelDesc(0, &desc);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, desc.Depth, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::setFinalAttributes(IDirect3DDevice9* d3d9Device, TextureResources* textureResources,
|
|
|
|
|
- UINT32 width, UINT32 height, UINT32 depth, PixelFormat format)
|
|
|
|
|
- {
|
|
|
|
|
- if(width != mProperties.getWidth() || height != mProperties.getHeight() || depth != mProperties.getDepth())
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Wanted and created textures sizes don't match!" \
|
|
|
|
|
- "Width: " + toString(width) + "/" + toString(mProperties.getWidth()) +
|
|
|
|
|
- "Height: " + toString(height) + "/" + toString(mProperties.getHeight()) +
|
|
|
|
|
- "Depth: " + toString(depth) + "/" + toString(mProperties.getDepth()));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if(format != mProperties.getFormat())
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Wanted and created texture formats don't match! " +
|
|
|
|
|
- toString(format) + "/" + toString(mProperties.getFormat()));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- createSurfaceList(d3d9Device, textureResources);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3DTEXTUREFILTERTYPE D3D9TextureCore::getBestFilterMethod(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
- const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
-
|
|
|
|
|
- DWORD filterCaps = 0;
|
|
|
|
|
-
|
|
|
|
|
- switch (mProperties.getTextureType())
|
|
|
|
|
- {
|
|
|
|
|
- case TEX_TYPE_1D:
|
|
|
|
|
- // Same as 2D
|
|
|
|
|
- case TEX_TYPE_2D:
|
|
|
|
|
- filterCaps = deviceCaps.TextureFilterCaps;
|
|
|
|
|
- break;
|
|
|
|
|
- case TEX_TYPE_3D:
|
|
|
|
|
- filterCaps = deviceCaps.VolumeTextureFilterCaps;
|
|
|
|
|
- break;
|
|
|
|
|
- case TEX_TYPE_CUBE_MAP:
|
|
|
|
|
- filterCaps = deviceCaps.CubeTextureFilterCaps;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if(filterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
|
|
|
|
|
- return D3DTEXF_GAUSSIANQUAD;
|
|
|
|
|
-
|
|
|
|
|
- if(filterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
|
|
|
|
|
- return D3DTEXF_PYRAMIDALQUAD;
|
|
|
|
|
-
|
|
|
|
|
- if(filterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
|
|
|
|
|
- return D3DTEXF_ANISOTROPIC;
|
|
|
|
|
-
|
|
|
|
|
- if(filterCaps & D3DPTFILTERCAPS_MINFLINEAR)
|
|
|
|
|
- return D3DTEXF_LINEAR;
|
|
|
|
|
-
|
|
|
|
|
- if(filterCaps & D3DPTFILTERCAPS_MINFPOINT)
|
|
|
|
|
- return D3DTEXF_POINT;
|
|
|
|
|
-
|
|
|
|
|
- return D3DTEXF_POINT;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- bool D3D9TextureCore::canUseDynamicTextures(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType,
|
|
|
|
|
- D3DFORMAT srcFormat)
|
|
|
|
|
- {
|
|
|
|
|
- IDirect3D9* pD3D = nullptr;
|
|
|
|
|
-
|
|
|
|
|
- HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!");
|
|
|
|
|
-
|
|
|
|
|
- if (pD3D != nullptr)
|
|
|
|
|
- pD3D->Release();
|
|
|
|
|
-
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
- const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
- D3DFORMAT backBufferFormat = device->getBackBufferFormat();
|
|
|
|
|
-
|
|
|
|
|
- hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
|
|
|
|
|
- backBufferFormat, srcUsage | D3DUSAGE_DYNAMIC, srcType, srcFormat);
|
|
|
|
|
-
|
|
|
|
|
- return hr == D3D_OK;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- bool D3D9TextureCore::canUseHardwareGammaCorrection(IDirect3DDevice9* d3d9Device, DWORD srcUsage,
|
|
|
|
|
- D3DRESOURCETYPE srcType, D3DFORMAT srcFormat, bool forwriting)
|
|
|
|
|
- {
|
|
|
|
|
- IDirect3D9* pD3D = nullptr;
|
|
|
|
|
-
|
|
|
|
|
- HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!" );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (pD3D != nullptr)
|
|
|
|
|
- pD3D->Release();
|
|
|
|
|
-
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
- const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
- D3DFORMAT backBufferFormat = device->getBackBufferFormat();
|
|
|
|
|
-
|
|
|
|
|
- if (forwriting)
|
|
|
|
|
- srcUsage |= D3DUSAGE_QUERY_SRGBWRITE;
|
|
|
|
|
- else
|
|
|
|
|
- srcUsage |= D3DUSAGE_QUERY_SRGBREAD;
|
|
|
|
|
-
|
|
|
|
|
- hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
|
|
|
|
|
- backBufferFormat, srcUsage, srcType, srcFormat);
|
|
|
|
|
-
|
|
|
|
|
- return hr == D3D_OK;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- bool D3D9TextureCore::canAutoGenMipmaps(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
|
|
|
|
|
- {
|
|
|
|
|
- IDirect3D9* pD3D = nullptr;
|
|
|
|
|
-
|
|
|
|
|
- HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
|
|
|
|
|
- if (FAILED(hr))
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "GetDirect3D failed.");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (pD3D != nullptr)
|
|
|
|
|
- pD3D->Release();
|
|
|
|
|
-
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
- const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
- D3DFORMAT backBufferFormat = device->getBackBufferFormat();
|
|
|
|
|
-
|
|
|
|
|
- if (deviceCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
|
|
|
|
|
- {
|
|
|
|
|
- hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
|
|
|
|
|
- backBufferFormat, srcUsage | D3DUSAGE_AUTOGENMIPMAP, srcType, srcFormat);
|
|
|
|
|
-
|
|
|
|
|
- return hr == D3D_OK;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- D3DFORMAT D3D9TextureCore::chooseD3DFormat(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- // Choose frame buffer pixel format in case PF_UNKNOWN was requested
|
|
|
|
|
- if(mProperties.getFormat() == PF_UNKNOWN)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
-
|
|
|
|
|
- if((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
|
|
|
|
|
- return device->getDepthStencilFormat();
|
|
|
|
|
- else
|
|
|
|
|
- return device->getBackBufferFormat();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Choose closest supported D3D format as a D3D format
|
|
|
|
|
- return D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(mProperties.getFormat()));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources)
|
|
|
|
|
- {
|
|
|
|
|
- int texUsage = mProperties.getUsage();
|
|
|
|
|
- TextureType texType = mProperties.getTextureType();
|
|
|
|
|
- UINT32 numMips = mProperties.getNumMipmaps();
|
|
|
|
|
-
|
|
|
|
|
- assert(textureResources != nullptr);
|
|
|
|
|
-
|
|
|
|
|
- // Need to know static / dynamic
|
|
|
|
|
- UINT32 usage;
|
|
|
|
|
- if ((texUsage & TU_DYNAMIC) && mDynamicTextures)
|
|
|
|
|
- {
|
|
|
|
|
- usage = GBU_DYNAMIC;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- usage = GBU_STATIC;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
- {
|
|
|
|
|
- usage |= TU_RENDERTARGET;
|
|
|
|
|
- }
|
|
|
|
|
- else if (texUsage & TU_DEPTHSTENCIL)
|
|
|
|
|
- {
|
|
|
|
|
- usage |= TU_RENDERTARGET;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- UINT32 surfaceCount = static_cast<UINT32>((mProperties.getNumFaces() * (numMips + 1)));
|
|
|
|
|
- bool updateOldList = mSurfaceList.size() == surfaceCount;
|
|
|
|
|
- if(!updateOldList)
|
|
|
|
|
- {
|
|
|
|
|
- mSurfaceList.clear();
|
|
|
|
|
- for (UINT32 face = 0; face < mProperties.getNumFaces(); face++)
|
|
|
|
|
- {
|
|
|
|
|
- for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
- {
|
|
|
|
|
- mSurfaceList.push_back(bs_shared_ptr_new<D3D9PixelBuffer>((GpuBufferUsage)usage, this));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DSurface9* surface = nullptr;
|
|
|
|
|
- IDirect3DVolume9* volume = nullptr;
|
|
|
|
|
-
|
|
|
|
|
- if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
- {
|
|
|
|
|
- assert(textureResources->pMultisampleSurface);
|
|
|
|
|
- assert(texType == TEX_TYPE_2D);
|
|
|
|
|
-
|
|
|
|
|
- D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
|
|
|
|
|
-
|
|
|
|
|
- currPixelBuffer->bind(d3d9Device, textureResources->pMultisampleSurface, textureResources->pBaseTex);
|
|
|
|
|
- }
|
|
|
|
|
- else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
- {
|
|
|
|
|
- assert(textureResources->pDepthStencilSurface);
|
|
|
|
|
- assert(texType == TEX_TYPE_2D);
|
|
|
|
|
-
|
|
|
|
|
- D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
|
|
|
|
|
-
|
|
|
|
|
- currPixelBuffer->bind(d3d9Device, textureResources->pDepthStencilSurface, textureResources->pBaseTex);
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- assert(textureResources->pBaseTex);
|
|
|
|
|
-
|
|
|
|
|
- UINT32 numCreatedMips = textureResources->pBaseTex->GetLevelCount() - 1;
|
|
|
|
|
- if (numCreatedMips != numMips)
|
|
|
|
|
- {
|
|
|
|
|
- BS_EXCEPT(InternalErrorException, "Number of created and wanted mip map levels doesn't match: " +
|
|
|
|
|
- toString(numCreatedMips) + "/" + toString(numMips));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch(texType)
|
|
|
|
|
- {
|
|
|
|
|
- case TEX_TYPE_2D:
|
|
|
|
|
- case TEX_TYPE_1D:
|
|
|
|
|
- assert(textureResources->pNormTex);
|
|
|
|
|
-
|
|
|
|
|
- for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
- {
|
|
|
|
|
- if(textureResources->pNormTex->GetSurfaceLevel(static_cast<UINT>(mip), &surface) != D3D_OK)
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Get surface level failed");
|
|
|
|
|
-
|
|
|
|
|
- D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
|
|
|
|
|
-
|
|
|
|
|
- currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
|
|
|
|
|
-
|
|
|
|
|
- surface->Release();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- break;
|
|
|
|
|
- case TEX_TYPE_CUBE_MAP:
|
|
|
|
|
- assert(textureResources->pCubeTex);
|
|
|
|
|
-
|
|
|
|
|
- for(UINT32 face = 0; face < 6; face++)
|
|
|
|
|
- {
|
|
|
|
|
- for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
- {
|
|
|
|
|
- if(textureResources->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, static_cast<UINT>(mip), &surface) != D3D_OK)
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Get cubemap surface failed");
|
|
|
|
|
-
|
|
|
|
|
- UINT32 idx = face*(numMips + 1) + mip;
|
|
|
|
|
- D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[idx].get());
|
|
|
|
|
-
|
|
|
|
|
- currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
|
|
|
|
|
-
|
|
|
|
|
- surface->Release();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
- case TEX_TYPE_3D:
|
|
|
|
|
- assert(textureResources->pVolumeTex);
|
|
|
|
|
-
|
|
|
|
|
- for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
- {
|
|
|
|
|
- if(textureResources->pVolumeTex->GetVolumeLevel(static_cast<UINT>(mip), &volume) != D3D_OK)
|
|
|
|
|
- BS_EXCEPT(RenderingAPIException, "Get volume level failed");
|
|
|
|
|
-
|
|
|
|
|
- D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
|
|
|
|
|
- currPixelBuffer->bind(d3d9Device, volume, textureResources->pBaseTex);
|
|
|
|
|
-
|
|
|
|
|
- volume->Release();
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PixelBufferPtr D3D9TextureCore::getBuffer(UINT32 face, UINT32 mipmap)
|
|
|
|
|
- {
|
|
|
|
|
- THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
-
|
|
|
|
|
- if(face >= mProperties.getNumFaces())
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
|
|
|
|
|
- if (mipmap > mProperties.getNumMipmaps())
|
|
|
|
|
- BS_EXCEPT(InvalidParametersException, "Mipmap index out of range");
|
|
|
|
|
-
|
|
|
|
|
- UINT32 idx = face*(mProperties.getNumMipmaps() + 1) + mipmap;
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
- TextureResources* textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- createInternalResources(d3d9Device);
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- assert(textureResources != nullptr);
|
|
|
|
|
- assert(idx < mSurfaceList.size());
|
|
|
|
|
- return mSurfaceList[idx];
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- bool D3D9TextureCore::useDefaultPool()
|
|
|
|
|
- {
|
|
|
|
|
- int usage = mProperties.getUsage();
|
|
|
|
|
- return (usage & TU_RENDERTARGET) || (usage & TU_DEPTHSTENCIL) || ((usage & TU_DYNAMIC) && mDynamicTextures);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
-
|
|
|
|
|
- if (D3D9RenderAPI::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
|
|
|
|
|
- createInternalResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
-
|
|
|
|
|
- auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
|
|
|
|
|
-
|
|
|
|
|
- if (iterFind != mMapDeviceToTextureResources.end())
|
|
|
|
|
- {
|
|
|
|
|
- TextureResources* textureResource = iterFind->second;
|
|
|
|
|
-
|
|
|
|
|
- for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
|
|
|
|
|
-
|
|
|
|
|
- pixelBuffer->destroyBufferResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- freeTextureResources(d3d9Device, textureResource);
|
|
|
|
|
-
|
|
|
|
|
- if(textureResource != nullptr)
|
|
|
|
|
- bs_delete(textureResource);
|
|
|
|
|
-
|
|
|
|
|
- mMapDeviceToTextureResources.erase(iterFind);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
-
|
|
|
|
|
- if(mD3DPool == D3DPOOL_DEFAULT)
|
|
|
|
|
- {
|
|
|
|
|
- auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
|
|
|
|
|
-
|
|
|
|
|
- if (iterFind != mMapDeviceToTextureResources.end())
|
|
|
|
|
- {
|
|
|
|
|
- TextureResources* textureResource = iterFind->second;
|
|
|
|
|
- freeTextureResources(d3d9Device, textureResource);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void D3D9TextureCore::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
- {
|
|
|
|
|
- D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
-
|
|
|
|
|
- if(mD3DPool == D3DPOOL_DEFAULT)
|
|
|
|
|
- {
|
|
|
|
|
- createInternalResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DBaseTexture9* D3D9TextureCore::getTexture_internal()
|
|
|
|
|
- {
|
|
|
|
|
- THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
-
|
|
|
|
|
- TextureResources* textureResources;
|
|
|
|
|
- IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
-
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- createInternalResources(d3d9Device);
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- assert(textureResources);
|
|
|
|
|
- assert(textureResources->pBaseTex);
|
|
|
|
|
-
|
|
|
|
|
- return textureResources->pBaseTex;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DTexture9* D3D9TextureCore::getNormTexture_internal()
|
|
|
|
|
- {
|
|
|
|
|
- THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
-
|
|
|
|
|
- TextureResources* textureResources;
|
|
|
|
|
- IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
-
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- if (textureResources == nullptr || textureResources->pNormTex == nullptr)
|
|
|
|
|
- {
|
|
|
|
|
- createInternalResources(d3d9Device);
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
- assert(textureResources);
|
|
|
|
|
- assert(textureResources->pNormTex);
|
|
|
|
|
-
|
|
|
|
|
- return textureResources->pNormTex;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- IDirect3DCubeTexture9* D3D9TextureCore::getCubeTexture_internal()
|
|
|
|
|
- {
|
|
|
|
|
- THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
-
|
|
|
|
|
- TextureResources* textureResources;
|
|
|
|
|
- IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
-
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- if (textureResources == nullptr || textureResources->pCubeTex)
|
|
|
|
|
- {
|
|
|
|
|
- createInternalResources(d3d9Device);
|
|
|
|
|
- textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- assert(textureResources);
|
|
|
|
|
- assert(textureResources->pCubeTex);
|
|
|
|
|
-
|
|
|
|
|
- return textureResources->pCubeTex;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+#include "BsCoreThread.h"
|
|
|
|
|
+#include "BsD3D9Texture.h"
|
|
|
|
|
+#include "BsD3D9PixelBuffer.h"
|
|
|
|
|
+#include "BsException.h"
|
|
|
|
|
+#include "BsBitwise.h"
|
|
|
|
|
+#include "BsD3D9Mappings.h"
|
|
|
|
|
+#include "BsD3D9RenderAPI.h"
|
|
|
|
|
+#include "BsD3D9TextureManager.h"
|
|
|
|
|
+#include "BsD3D9Device.h"
|
|
|
|
|
+#include "BsD3D9DeviceManager.h"
|
|
|
|
|
+#include "BsD3D9ResourceManager.h"
|
|
|
|
|
+#include "BsRenderStats.h"
|
|
|
|
|
+#include "BsPixelData.h"
|
|
|
|
|
+
|
|
|
|
|
+namespace BansheeEngine
|
|
|
|
|
+{
|
|
|
|
|
+ D3D9TextureCore::D3D9TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
|
|
|
|
|
+ PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount, const PixelDataPtr& initialData)
|
|
|
|
|
+ :TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount, initialData),
|
|
|
|
|
+ mD3DPool(D3DPOOL_MANAGED), mDynamicTextures(false), mHwGammaReadSupported(false), mHwGammaWriteSupported(false),
|
|
|
|
|
+ mMultisampleType(D3DMULTISAMPLE_NONE), mMultisampleQuality(0), mIsBindableAsShaderResource(true)
|
|
|
|
|
+ {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3D9TextureCore::~D3D9TextureCore()
|
|
|
|
|
+ {
|
|
|
|
|
+ THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
+
|
|
|
|
|
+ for (auto& resPair : mMapDeviceToTextureResources)
|
|
|
|
|
+ {
|
|
|
|
|
+ TextureResources* textureResource = resPair.second;
|
|
|
|
|
+
|
|
|
|
|
+ freeTextureResources(resPair.first, textureResource);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (auto& resPair : mMapDeviceToTextureResources)
|
|
|
|
|
+ {
|
|
|
|
|
+ TextureResources* textureResource = resPair.second;
|
|
|
|
|
+
|
|
|
|
|
+ if (textureResource != nullptr)
|
|
|
|
|
+ bs_delete(textureResource);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ mMapDeviceToTextureResources.clear();
|
|
|
|
|
+ mSurfaceList.clear();
|
|
|
|
|
+
|
|
|
|
|
+ BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::initialize()
|
|
|
|
|
+ {
|
|
|
|
|
+ THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
+
|
|
|
|
|
+ for (UINT32 i = 0; i < D3D9RenderAPI::getResourceCreationDeviceCount(); ++i)
|
|
|
|
|
+ {
|
|
|
|
|
+ IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getResourceCreationDevice(i);
|
|
|
|
|
+
|
|
|
|
|
+ createInternalResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
|
|
|
|
|
+ TextureCore::initialize();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ PixelData D3D9TextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mProperties.getMultisampleCount() > 1)
|
|
|
|
|
+ BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
|
|
|
|
|
+
|
|
|
|
|
+ if(mLockedBuffer != nullptr)
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
|
|
|
|
|
+
|
|
|
|
|
+ if (mProperties.getUsage() == TU_DEPTHSTENCIL)
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Cannot lock a depth stencil texture.");
|
|
|
|
|
+
|
|
|
|
|
+ UINT32 mipWidth = std::max(1u, mProperties.getWidth() >> mipLevel);
|
|
|
|
|
+ UINT32 mipHeight = std::max(1u, mProperties.getHeight() >> mipLevel);
|
|
|
|
|
+ UINT32 mipDepth = std::max(1u, mProperties.getDepth() >> mipLevel);
|
|
|
|
|
+
|
|
|
|
|
+ PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
|
|
|
|
|
+
|
|
|
|
|
+ mLockedBuffer = getBuffer(face, mipLevel);
|
|
|
|
|
+ lockedArea.setExternalBuffer((UINT8*)mLockedBuffer->lock(options));
|
|
|
|
|
+
|
|
|
|
|
+ return lockedArea;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::unlockImpl()
|
|
|
|
|
+ {
|
|
|
|
|
+ if(mLockedBuffer == nullptr)
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
|
|
|
|
|
+
|
|
|
|
|
+ mLockedBuffer->unlock();
|
|
|
|
|
+ mLockedBuffer = nullptr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mProperties.getMultisampleCount() > 1)
|
|
|
|
|
+ BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
|
|
|
|
|
+
|
|
|
|
|
+ if (mProperties.getUsage() == TU_DEPTHSTENCIL || mProperties.getUsage() == TU_RENDERTARGET) // Render targets cannot be locked normally
|
|
|
|
|
+ {
|
|
|
|
|
+ IDirect3DDevice9* device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
+
|
|
|
|
|
+ D3D9PixelBuffer* sourceBuffer = static_cast<D3D9PixelBuffer*>(getBuffer(face, mipLevel).get());
|
|
|
|
|
+
|
|
|
|
|
+ UINT32 mipWidth = std::max(1u, mProperties.getWidth() >> mipLevel);
|
|
|
|
|
+ UINT32 mipHeight = std::max(1u, mProperties.getHeight() >> mipLevel);
|
|
|
|
|
+ D3DFORMAT format = chooseD3DFormat(device);
|
|
|
|
|
+
|
|
|
|
|
+ // Note: I'm allocating and releasing a texture every time we read.
|
|
|
|
|
+ // I might consider adding a flag to keep this texture permanent which would make reading
|
|
|
|
|
+ // faster but at the cost of double the memory.
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DTexture9* stagingTexture = nullptr;
|
|
|
|
|
+ HRESULT hr = D3DXCreateTexture(device, (UINT)mipWidth, (UINT)mipHeight, 1,
|
|
|
|
|
+ 0, format, D3DPOOL_SYSTEMMEM, &stagingTexture);
|
|
|
|
|
+
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Failed to create a texture: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DSurface9* stagingSurface = nullptr;
|
|
|
|
|
+ hr = stagingTexture->GetSurfaceLevel(0, &stagingSurface);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Failed to retrieve a texture surface: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hr = device->GetRenderTargetData(sourceBuffer->getSurface(device), stagingSurface);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Failed to retrieve render target data: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ PixelData myData(mipWidth, mipHeight, 1, mProperties.getFormat());
|
|
|
|
|
+
|
|
|
|
|
+ D3DLOCKED_RECT lrect;
|
|
|
|
|
+ hr = stagingSurface->LockRect(&lrect, nullptr, D3DLOCK_READONLY);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Failed to lock surface: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3D9PixelBuffer::initPixelDataFromD3DLock(myData, lrect);
|
|
|
|
|
+
|
|
|
|
|
+#if BS_DEBUG_MODE
|
|
|
|
|
+ if (dest.getConsecutiveSize() != myData.getConsecutiveSize())
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ PixelUtil::bulkPixelConversion(myData, dest);
|
|
|
|
|
+
|
|
|
|
|
+ hr = stagingSurface->UnlockRect();
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Failed to unlock surface: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ SAFE_RELEASE(stagingSurface);
|
|
|
|
|
+ SAFE_RELEASE(stagingTexture);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
|
|
|
|
|
+
|
|
|
|
|
+#if BS_DEBUG_MODE
|
|
|
|
|
+ if (dest.getConsecutiveSize() != myData.getConsecutiveSize())
|
|
|
|
|
+ {
|
|
|
|
|
+ unlock();
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ PixelUtil::bulkPixelConversion(myData, dest);
|
|
|
|
|
+
|
|
|
|
|
+ unlock();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mProperties.getMultisampleCount() > 1)
|
|
|
|
|
+ BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
|
|
|
|
|
+
|
|
|
|
|
+ if (mProperties.getUsage() == TU_DYNAMIC || mProperties.getUsage() == TU_STATIC)
|
|
|
|
|
+ {
|
|
|
|
|
+ PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
|
|
|
|
|
+ PixelUtil::bulkPixelConversion(src, myData);
|
|
|
|
|
+ unlock();
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
|
|
|
|
|
+ {
|
|
|
|
|
+ THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
+
|
|
|
|
|
+ TextureType texType = mProperties.getTextureType();
|
|
|
|
|
+
|
|
|
|
|
+ if (texType == TEX_TYPE_1D || texType == TEX_TYPE_3D)
|
|
|
|
|
+ BS_EXCEPT(NotImplementedException, "Copy not implemented for 1D and 3D textures yet.");
|
|
|
|
|
+
|
|
|
|
|
+ HRESULT hr;
|
|
|
|
|
+ D3D9TextureCore* other = static_cast<D3D9TextureCore*>(target.get());
|
|
|
|
|
+
|
|
|
|
|
+ for (auto& resPair : mMapDeviceToTextureResources)
|
|
|
|
|
+ {
|
|
|
|
|
+ TextureResources* srcTextureResource = resPair.second;
|
|
|
|
|
+ TextureResources* dstTextureResource = other->getTextureResources(resPair.first);
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DSurface9 *sourceSurface = nullptr;
|
|
|
|
|
+ IDirect3DSurface9 *destSurface = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ if (texType == TEX_TYPE_2D && srcTextureResource->pNormTex != nullptr && dstTextureResource->pNormTex != nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(FAILED(hr = srcTextureResource->pNormTex->GetSurfaceLevel(srcMipLevel, &sourceSurface)))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Cannot retrieve source surface for copy: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(FAILED(hr = dstTextureResource->pNormTex->GetSurfaceLevel(destMipLevel, &destSurface)))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Cannot retrieve destination surface for copy: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (texType == TEX_TYPE_CUBE_MAP && srcTextureResource->pCubeTex != nullptr && dstTextureResource->pCubeTex != nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ IDirect3DSurface9 *sourceSurface = nullptr;
|
|
|
|
|
+ if (FAILED(hr = srcTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)srcFace, srcMipLevel, &sourceSurface)))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Cannot retrieve source surface for copy: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DSurface9 *destSurface = nullptr;
|
|
|
|
|
+ if (FAILED(hr = dstTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)destFace, destMipLevel, &destSurface)))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Cannot retrieve destination surface for copy: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (sourceSurface != nullptr && destSurface != nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3DSURFACE_DESC desc;
|
|
|
|
|
+
|
|
|
|
|
+ sourceSurface->GetDesc(&desc);
|
|
|
|
|
+ if (desc.Pool != D3DPOOL_DEFAULT)
|
|
|
|
|
+ BS_EXCEPT(InvalidStateException, "Source surface must be in the default pool.");
|
|
|
|
|
+
|
|
|
|
|
+ destSurface->GetDesc(&desc);
|
|
|
|
|
+ if (desc.Pool != D3DPOOL_DEFAULT)
|
|
|
|
|
+ BS_EXCEPT(InvalidStateException, "Destination surface must be in the default pool.");
|
|
|
|
|
+
|
|
|
|
|
+ if (FAILED(hr = resPair.first->StretchRect(sourceSurface, NULL, destSurface, NULL, D3DTEXF_NONE)))
|
|
|
|
|
+ {
|
|
|
|
|
+ String msg = DXGetErrorDescription(hr);
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "StretchRect failed during copy: " + msg);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ SAFE_RELEASE(sourceSurface);
|
|
|
|
|
+ SAFE_RELEASE(destSurface);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3D9TextureCore::TextureResources* D3D9TextureCore::getTextureResources(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
|
|
|
|
|
+
|
|
|
|
|
+ if (iterFind == mMapDeviceToTextureResources.end())
|
|
|
|
|
+ return nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ return iterFind->second;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3D9TextureCore::TextureResources* D3D9TextureCore::allocateTextureResources(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ assert(mMapDeviceToTextureResources.find(d3d9Device) == mMapDeviceToTextureResources.end());
|
|
|
|
|
+
|
|
|
|
|
+ TextureResources* textureResources = bs_new<TextureResources>();
|
|
|
|
|
+
|
|
|
|
|
+ textureResources->pNormTex = nullptr;
|
|
|
|
|
+ textureResources->pCubeTex = nullptr;
|
|
|
|
|
+ textureResources->pVolumeTex = nullptr;
|
|
|
|
|
+ textureResources->pBaseTex = nullptr;
|
|
|
|
|
+ textureResources->pMultisampleSurface = nullptr;
|
|
|
|
|
+ textureResources->pDepthStencilSurface = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ mMapDeviceToTextureResources[d3d9Device] = textureResources;
|
|
|
|
|
+
|
|
|
|
|
+ return textureResources;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::freeTextureResources(IDirect3DDevice9* d3d9Device, D3D9TextureCore::TextureResources* textureResources)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
+
|
|
|
|
|
+ // Release surfaces from each mip level.
|
|
|
|
|
+ for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
|
|
|
|
|
+
|
|
|
|
|
+ pixelBuffer->releaseSurfaces(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Release the rest of the resources.
|
|
|
|
|
+ SAFE_RELEASE(textureResources->pBaseTex);
|
|
|
|
|
+ SAFE_RELEASE(textureResources->pNormTex);
|
|
|
|
|
+ SAFE_RELEASE(textureResources->pCubeTex);
|
|
|
|
|
+ SAFE_RELEASE(textureResources->pVolumeTex);
|
|
|
|
|
+ SAFE_RELEASE(textureResources->pMultisampleSurface);
|
|
|
|
|
+ SAFE_RELEASE(textureResources->pDepthStencilSurface);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ UINT32 D3D9TextureCore::calculateSize() const
|
|
|
|
|
+ {
|
|
|
|
|
+ UINT32 instanceSize = mProperties.getNumFaces() *
|
|
|
|
|
+ PixelUtil::getMemorySize(mProperties.getWidth(), mProperties.getHeight(),
|
|
|
|
|
+ mProperties.getDepth(), mProperties.getFormat());
|
|
|
|
|
+
|
|
|
|
|
+ return instanceSize * (UINT32)mMapDeviceToTextureResources.size();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::determinePool()
|
|
|
|
|
+ {
|
|
|
|
|
+ if (useDefaultPool())
|
|
|
|
|
+ mD3DPool = D3DPOOL_DEFAULT;
|
|
|
|
|
+ else
|
|
|
|
|
+ mD3DPool = D3DPOOL_MANAGED;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::createInternalResources(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ switch (mProperties.getTextureType())
|
|
|
|
|
+ {
|
|
|
|
|
+ case TEX_TYPE_1D:
|
|
|
|
|
+ case TEX_TYPE_2D:
|
|
|
|
|
+ createNormTex(d3d9Device);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case TEX_TYPE_CUBE_MAP:
|
|
|
|
|
+ createCubeTex(d3d9Device);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case TEX_TYPE_3D:
|
|
|
|
|
+ createVolumeTex(d3d9Device);
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Unknown texture type.");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::createNormTex(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ UINT32 width = mProperties.getWidth();
|
|
|
|
|
+ UINT32 height = mProperties.getHeight();
|
|
|
|
|
+ int texUsage = mProperties.getUsage();
|
|
|
|
|
+ UINT32 origNumMips = mProperties.getNumMipmaps();
|
|
|
|
|
+ PixelFormat format = mProperties.getFormat();
|
|
|
|
|
+ bool hwGamma = mProperties.isHardwareGammaEnabled();
|
|
|
|
|
+ UINT32 sampleCount = mProperties.getMultisampleCount();
|
|
|
|
|
+
|
|
|
|
|
+ assert(width > 0 || height > 0);
|
|
|
|
|
+
|
|
|
|
|
+ D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
|
|
|
|
|
+ if (format != D3D9Mappings::_getPF(d3dPF))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
|
|
|
|
|
+ UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
|
|
|
|
|
+
|
|
|
|
|
+ DWORD usage = 0;
|
|
|
|
|
+ if ((texUsage & TU_RENDERTARGET) != 0)
|
|
|
|
|
+ usage = D3DUSAGE_RENDERTARGET;
|
|
|
|
|
+ else if ((texUsage & TU_DEPTHSTENCIL) != 0)
|
|
|
|
|
+ usage = D3DUSAGE_DEPTHSTENCIL;
|
|
|
|
|
+
|
|
|
|
|
+ // Check dynamic textures
|
|
|
|
|
+ if (texUsage & TU_DYNAMIC)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF))
|
|
|
|
|
+ {
|
|
|
|
|
+ usage |= D3DUSAGE_DYNAMIC;
|
|
|
|
|
+ mDynamicTextures = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ mDynamicTextures = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check sRGB support
|
|
|
|
|
+ if (hwGamma)
|
|
|
|
|
+ {
|
|
|
|
|
+ mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, false);
|
|
|
|
|
+ if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
+ mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check multisample level
|
|
|
|
|
+ if ((texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9RenderAPI* rsys = static_cast<D3D9RenderAPI*>(BansheeEngine::RenderAPICore::instancePtr());
|
|
|
|
|
+ rsys->determineMultisampleSettings(d3d9Device, sampleCount, d3dPF, false, &mMultisampleType, &mMultisampleQuality);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ mMultisampleType = D3DMULTISAMPLE_NONE;
|
|
|
|
|
+ mMultisampleQuality = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+ const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
+
|
|
|
|
|
+ // Check if mip maps are supported on hardware
|
|
|
|
|
+ if (numMips > 1 && (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) || (texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ determinePool();
|
|
|
|
|
+ TextureResources* textureResources;
|
|
|
|
|
+
|
|
|
|
|
+ // Get or create new texture resources structure.
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ if (textureResources != NULL)
|
|
|
|
|
+ freeTextureResources(d3d9Device, textureResources);
|
|
|
|
|
+ else
|
|
|
|
|
+ textureResources = allocateTextureResources(d3d9Device);
|
|
|
|
|
+
|
|
|
|
|
+ if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create AA surface
|
|
|
|
|
+ HRESULT hr = d3d9Device->CreateRenderTarget(width, height, d3dPF,
|
|
|
|
|
+ mMultisampleType, mMultisampleQuality,
|
|
|
|
|
+ FALSE,
|
|
|
|
|
+ &textureResources->pMultisampleSurface, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Unable to create AA render target: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+
|
|
|
|
|
+ D3DSURFACE_DESC desc;
|
|
|
|
|
+ hr = textureResources->pMultisampleSurface->GetDesc(&desc);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
+
|
|
|
|
|
+ mIsBindableAsShaderResource = false; // Cannot bind AA surfaces
|
|
|
|
|
+ }
|
|
|
|
|
+ else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create AA depth stencil surface
|
|
|
|
|
+ HRESULT hr = d3d9Device->CreateDepthStencilSurface(width, height, d3dPF,
|
|
|
|
|
+ mMultisampleType, mMultisampleQuality,
|
|
|
|
|
+ FALSE,
|
|
|
|
|
+ &textureResources->pDepthStencilSurface, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Unable to create AA depth stencil render target: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+
|
|
|
|
|
+ // Update final parameters as they may differ from requested ones
|
|
|
|
|
+ D3DSURFACE_DESC desc;
|
|
|
|
|
+ hr = textureResources->pDepthStencilSurface->GetDesc(&desc);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
+
|
|
|
|
|
+ mIsBindableAsShaderResource = false; // Cannot bind AA depth buffer
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ // Create normal texture
|
|
|
|
|
+ HRESULT hr = D3DXCreateTexture(d3d9Device, (UINT)width, (UINT)height, numMips,
|
|
|
|
|
+ usage, d3dPF, mD3DPool, &textureResources->pNormTex);
|
|
|
|
|
+
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hr = textureResources->pNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Update final parameters as they may differ from requested ones
|
|
|
|
|
+ D3DSURFACE_DESC desc;
|
|
|
|
|
+ hr = textureResources->pNormTex->GetLevelDesc(0, &desc);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::createCubeTex(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ UINT32 width = mProperties.getWidth();
|
|
|
|
|
+ UINT32 height = mProperties.getHeight();
|
|
|
|
|
+ int texUsage = mProperties.getUsage();
|
|
|
|
|
+ UINT32 origNumMips = mProperties.getNumMipmaps();
|
|
|
|
|
+ PixelFormat format = mProperties.getFormat();
|
|
|
|
|
+ bool hwGamma = mProperties.isHardwareGammaEnabled();
|
|
|
|
|
+
|
|
|
|
|
+ assert(width > 0 || height > 0);
|
|
|
|
|
+
|
|
|
|
|
+ D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
|
|
|
|
|
+ if (format != D3D9Mappings::_getPF(d3dPF))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
|
|
|
|
|
+ DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
|
|
|
|
|
+ usage |= (texUsage & TU_DEPTHSTENCIL) ? D3DUSAGE_DEPTHSTENCIL : 0;
|
|
|
|
|
+
|
|
|
|
|
+ UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
|
|
|
|
|
+
|
|
|
|
|
+ // Check dynamic textures
|
|
|
|
|
+ if (texUsage & TU_DYNAMIC)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF))
|
|
|
|
|
+ {
|
|
|
|
|
+ usage |= D3DUSAGE_DYNAMIC;
|
|
|
|
|
+ mDynamicTextures = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ mDynamicTextures = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check sRGB support
|
|
|
|
|
+ if (hwGamma)
|
|
|
|
|
+ {
|
|
|
|
|
+ mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, false);
|
|
|
|
|
+ if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
+ mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // No multisampling on cube textures
|
|
|
|
|
+ mMultisampleType = D3DMULTISAMPLE_NONE;
|
|
|
|
|
+ mMultisampleQuality = 0;
|
|
|
|
|
+
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+ const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
+
|
|
|
|
|
+ // Check if mip map cube textures are supported
|
|
|
|
|
+ if (numMips > 1 && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ determinePool();
|
|
|
|
|
+ TextureResources* textureResources;
|
|
|
|
|
+
|
|
|
|
|
+ // Get or create new texture resources structure.
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ if (textureResources != NULL)
|
|
|
|
|
+ freeTextureResources(d3d9Device, textureResources);
|
|
|
|
|
+ else
|
|
|
|
|
+ textureResources = allocateTextureResources(d3d9Device);
|
|
|
|
|
+
|
|
|
|
|
+ // Create the texture
|
|
|
|
|
+ HRESULT hr = D3DXCreateCubeTexture(d3d9Device, (UINT)width, numMips,
|
|
|
|
|
+ usage, d3dPF, mD3DPool, &textureResources->pCubeTex);
|
|
|
|
|
+
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hr = textureResources->pCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Update final parameters as they may differ from requested ones
|
|
|
|
|
+ D3DSURFACE_DESC desc;
|
|
|
|
|
+ hr = textureResources->pCubeTex->GetLevelDesc(0, &desc);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::createVolumeTex(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ UINT32 width = mProperties.getWidth();
|
|
|
|
|
+ UINT32 height = mProperties.getHeight();
|
|
|
|
|
+ UINT32 depth = mProperties.getDepth();
|
|
|
|
|
+ int texUsage = mProperties.getUsage();
|
|
|
|
|
+ UINT32 origNumMips = mProperties.getNumMipmaps();
|
|
|
|
|
+ PixelFormat format = mProperties.getFormat();
|
|
|
|
|
+ bool hwGamma = mProperties.isHardwareGammaEnabled();
|
|
|
|
|
+
|
|
|
|
|
+ assert(width > 0 && height > 0 && depth > 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as render target !!");
|
|
|
|
|
+
|
|
|
|
|
+ if (texUsage & TU_DEPTHSTENCIL)
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as a depth stencil target !!");
|
|
|
|
|
+
|
|
|
|
|
+ D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
|
|
|
|
|
+ if(format != D3D9Mappings::_getPF(d3dPF))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
|
|
|
|
|
+ DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
|
|
|
|
|
+ UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
|
|
|
|
|
+
|
|
|
|
|
+ // Check dynamic textures
|
|
|
|
|
+ if (texUsage & TU_DYNAMIC)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF))
|
|
|
|
|
+ {
|
|
|
|
|
+ usage |= D3DUSAGE_DYNAMIC;
|
|
|
|
|
+ mDynamicTextures = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ mDynamicTextures = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check sRGB support
|
|
|
|
|
+ if (hwGamma)
|
|
|
|
|
+ {
|
|
|
|
|
+ mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, false);
|
|
|
|
|
+ if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
+ mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, true);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+ const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
+
|
|
|
|
|
+ // Check if mip map volume textures are supported
|
|
|
|
|
+ if (numMips > 1 && !(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ determinePool();
|
|
|
|
|
+ TextureResources* textureResources;
|
|
|
|
|
+
|
|
|
|
|
+ // Get or create new texture resources structure.
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ if (textureResources != NULL)
|
|
|
|
|
+ freeTextureResources(d3d9Device, textureResources);
|
|
|
|
|
+ else
|
|
|
|
|
+ textureResources = allocateTextureResources(d3d9Device);
|
|
|
|
|
+
|
|
|
|
|
+ // Create the texture
|
|
|
|
|
+ HRESULT hr = D3DXCreateVolumeTexture(d3d9Device, (UINT)width, (UINT)height, (UINT)depth,
|
|
|
|
|
+ numMips, usage, d3dPF, mD3DPool, &textureResources->pVolumeTex);
|
|
|
|
|
+
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ hr = textureResources->pVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void**)&textureResources->pBaseTex);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Update final parameters as they may differ from requested ones
|
|
|
|
|
+ D3DVOLUME_DESC desc;
|
|
|
|
|
+ hr = textureResources->pVolumeTex->GetLevelDesc(0, &desc);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, desc.Depth, D3D9Mappings::_getPF(desc.Format));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::setFinalAttributes(IDirect3DDevice9* d3d9Device, TextureResources* textureResources,
|
|
|
|
|
+ UINT32 width, UINT32 height, UINT32 depth, PixelFormat format)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(width != mProperties.getWidth() || height != mProperties.getHeight() || depth != mProperties.getDepth())
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Wanted and created textures sizes don't match!" \
|
|
|
|
|
+ "Width: " + toString(width) + "/" + toString(mProperties.getWidth()) +
|
|
|
|
|
+ "Height: " + toString(height) + "/" + toString(mProperties.getHeight()) +
|
|
|
|
|
+ "Depth: " + toString(depth) + "/" + toString(mProperties.getDepth()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(format != mProperties.getFormat())
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Wanted and created texture formats don't match! " +
|
|
|
|
|
+ toString(format) + "/" + toString(mProperties.getFormat()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ createSurfaceList(d3d9Device, textureResources);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3DTEXTUREFILTERTYPE D3D9TextureCore::getBestFilterMethod(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+ const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
+
|
|
|
|
|
+ DWORD filterCaps = 0;
|
|
|
|
|
+
|
|
|
|
|
+ switch (mProperties.getTextureType())
|
|
|
|
|
+ {
|
|
|
|
|
+ case TEX_TYPE_1D:
|
|
|
|
|
+ // Same as 2D
|
|
|
|
|
+ case TEX_TYPE_2D:
|
|
|
|
|
+ filterCaps = deviceCaps.TextureFilterCaps;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case TEX_TYPE_3D:
|
|
|
|
|
+ filterCaps = deviceCaps.VolumeTextureFilterCaps;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case TEX_TYPE_CUBE_MAP:
|
|
|
|
|
+ filterCaps = deviceCaps.CubeTextureFilterCaps;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(filterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
|
|
|
|
|
+ return D3DTEXF_GAUSSIANQUAD;
|
|
|
|
|
+
|
|
|
|
|
+ if(filterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
|
|
|
|
|
+ return D3DTEXF_PYRAMIDALQUAD;
|
|
|
|
|
+
|
|
|
|
|
+ if(filterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
|
|
|
|
|
+ return D3DTEXF_ANISOTROPIC;
|
|
|
|
|
+
|
|
|
|
|
+ if(filterCaps & D3DPTFILTERCAPS_MINFLINEAR)
|
|
|
|
|
+ return D3DTEXF_LINEAR;
|
|
|
|
|
+
|
|
|
|
|
+ if(filterCaps & D3DPTFILTERCAPS_MINFPOINT)
|
|
|
|
|
+ return D3DTEXF_POINT;
|
|
|
|
|
+
|
|
|
|
|
+ return D3DTEXF_POINT;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bool D3D9TextureCore::canUseDynamicTextures(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType,
|
|
|
|
|
+ D3DFORMAT srcFormat)
|
|
|
|
|
+ {
|
|
|
|
|
+ IDirect3D9* pD3D = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!");
|
|
|
|
|
+
|
|
|
|
|
+ if (pD3D != nullptr)
|
|
|
|
|
+ pD3D->Release();
|
|
|
|
|
+
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+ const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
+ D3DFORMAT backBufferFormat = device->getBackBufferFormat();
|
|
|
|
|
+
|
|
|
|
|
+ hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
|
|
|
|
|
+ backBufferFormat, srcUsage | D3DUSAGE_DYNAMIC, srcType, srcFormat);
|
|
|
|
|
+
|
|
|
|
|
+ return hr == D3D_OK;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bool D3D9TextureCore::canUseHardwareGammaCorrection(IDirect3DDevice9* d3d9Device, DWORD srcUsage,
|
|
|
|
|
+ D3DRESOURCETYPE srcType, D3DFORMAT srcFormat, bool forwriting)
|
|
|
|
|
+ {
|
|
|
|
|
+ IDirect3D9* pD3D = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!" );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (pD3D != nullptr)
|
|
|
|
|
+ pD3D->Release();
|
|
|
|
|
+
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+ const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
+ D3DFORMAT backBufferFormat = device->getBackBufferFormat();
|
|
|
|
|
+
|
|
|
|
|
+ if (forwriting)
|
|
|
|
|
+ srcUsage |= D3DUSAGE_QUERY_SRGBWRITE;
|
|
|
|
|
+ else
|
|
|
|
|
+ srcUsage |= D3DUSAGE_QUERY_SRGBREAD;
|
|
|
|
|
+
|
|
|
|
|
+ hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
|
|
|
|
|
+ backBufferFormat, srcUsage, srcType, srcFormat);
|
|
|
|
|
+
|
|
|
|
|
+ return hr == D3D_OK;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bool D3D9TextureCore::canAutoGenMipmaps(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
|
|
|
|
|
+ {
|
|
|
|
|
+ IDirect3D9* pD3D = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
|
|
|
|
|
+ if (FAILED(hr))
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "GetDirect3D failed.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (pD3D != nullptr)
|
|
|
|
|
+ pD3D->Release();
|
|
|
|
|
+
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+ const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
|
|
|
|
|
+ D3DFORMAT backBufferFormat = device->getBackBufferFormat();
|
|
|
|
|
+
|
|
|
|
|
+ if (deviceCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
|
|
|
|
|
+ {
|
|
|
|
|
+ hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
|
|
|
|
|
+ backBufferFormat, srcUsage | D3DUSAGE_AUTOGENMIPMAP, srcType, srcFormat);
|
|
|
|
|
+
|
|
|
|
|
+ return hr == D3D_OK;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ D3DFORMAT D3D9TextureCore::chooseD3DFormat(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Choose frame buffer pixel format in case PF_UNKNOWN was requested
|
|
|
|
|
+ if(mProperties.getFormat() == PF_UNKNOWN)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
|
|
|
|
|
+
|
|
|
|
|
+ if((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
|
|
|
|
|
+ return device->getDepthStencilFormat();
|
|
|
|
|
+ else
|
|
|
|
|
+ return device->getBackBufferFormat();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Choose closest supported D3D format as a D3D format
|
|
|
|
|
+ return D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(mProperties.getFormat()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources)
|
|
|
|
|
+ {
|
|
|
|
|
+ int texUsage = mProperties.getUsage();
|
|
|
|
|
+ TextureType texType = mProperties.getTextureType();
|
|
|
|
|
+ UINT32 numMips = mProperties.getNumMipmaps();
|
|
|
|
|
+
|
|
|
|
|
+ assert(textureResources != nullptr);
|
|
|
|
|
+
|
|
|
|
|
+ // Need to know static / dynamic
|
|
|
|
|
+ UINT32 usage;
|
|
|
|
|
+ if ((texUsage & TU_DYNAMIC) && mDynamicTextures)
|
|
|
|
|
+ {
|
|
|
|
|
+ usage = GBU_DYNAMIC;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ usage = GBU_STATIC;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (texUsage & TU_RENDERTARGET)
|
|
|
|
|
+ {
|
|
|
|
|
+ usage |= TU_RENDERTARGET;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (texUsage & TU_DEPTHSTENCIL)
|
|
|
|
|
+ {
|
|
|
|
|
+ usage |= TU_RENDERTARGET;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ UINT32 surfaceCount = static_cast<UINT32>((mProperties.getNumFaces() * (numMips + 1)));
|
|
|
|
|
+ bool updateOldList = mSurfaceList.size() == surfaceCount;
|
|
|
|
|
+ if(!updateOldList)
|
|
|
|
|
+ {
|
|
|
|
|
+ mSurfaceList.clear();
|
|
|
|
|
+ for (UINT32 face = 0; face < mProperties.getNumFaces(); face++)
|
|
|
|
|
+ {
|
|
|
|
|
+ for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
+ {
|
|
|
|
|
+ mSurfaceList.push_back(bs_shared_ptr_new<D3D9PixelBuffer>((GpuBufferUsage)usage, this));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DSurface9* surface = nullptr;
|
|
|
|
|
+ IDirect3DVolume9* volume = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
+ {
|
|
|
|
|
+ assert(textureResources->pMultisampleSurface);
|
|
|
|
|
+ assert(texType == TEX_TYPE_2D);
|
|
|
|
|
+
|
|
|
|
|
+ D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
|
|
|
|
|
+
|
|
|
|
|
+ currPixelBuffer->bind(d3d9Device, textureResources->pMultisampleSurface, textureResources->pBaseTex);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
|
|
|
|
|
+ {
|
|
|
|
|
+ assert(textureResources->pDepthStencilSurface);
|
|
|
|
|
+ assert(texType == TEX_TYPE_2D);
|
|
|
|
|
+
|
|
|
|
|
+ D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
|
|
|
|
|
+
|
|
|
|
|
+ currPixelBuffer->bind(d3d9Device, textureResources->pDepthStencilSurface, textureResources->pBaseTex);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ assert(textureResources->pBaseTex);
|
|
|
|
|
+
|
|
|
|
|
+ UINT32 numCreatedMips = textureResources->pBaseTex->GetLevelCount() - 1;
|
|
|
|
|
+ if (numCreatedMips != numMips)
|
|
|
|
|
+ {
|
|
|
|
|
+ BS_EXCEPT(InternalErrorException, "Number of created and wanted mip map levels doesn't match: " +
|
|
|
|
|
+ toString(numCreatedMips) + "/" + toString(numMips));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ switch(texType)
|
|
|
|
|
+ {
|
|
|
|
|
+ case TEX_TYPE_2D:
|
|
|
|
|
+ case TEX_TYPE_1D:
|
|
|
|
|
+ assert(textureResources->pNormTex);
|
|
|
|
|
+
|
|
|
|
|
+ for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(textureResources->pNormTex->GetSurfaceLevel(static_cast<UINT>(mip), &surface) != D3D_OK)
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Get surface level failed");
|
|
|
|
|
+
|
|
|
|
|
+ D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
|
|
|
|
|
+
|
|
|
|
|
+ currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
|
|
|
|
|
+
|
|
|
|
|
+ surface->Release();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ case TEX_TYPE_CUBE_MAP:
|
|
|
|
|
+ assert(textureResources->pCubeTex);
|
|
|
|
|
+
|
|
|
|
|
+ for(UINT32 face = 0; face < 6; face++)
|
|
|
|
|
+ {
|
|
|
|
|
+ for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(textureResources->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, static_cast<UINT>(mip), &surface) != D3D_OK)
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Get cubemap surface failed");
|
|
|
|
|
+
|
|
|
|
|
+ UINT32 idx = face*(numMips + 1) + mip;
|
|
|
|
|
+ D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[idx].get());
|
|
|
|
|
+
|
|
|
|
|
+ currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
|
|
|
|
|
+
|
|
|
|
|
+ surface->Release();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case TEX_TYPE_3D:
|
|
|
|
|
+ assert(textureResources->pVolumeTex);
|
|
|
|
|
+
|
|
|
|
|
+ for (UINT32 mip = 0; mip <= numMips; mip++)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(textureResources->pVolumeTex->GetVolumeLevel(static_cast<UINT>(mip), &volume) != D3D_OK)
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Get volume level failed");
|
|
|
|
|
+
|
|
|
|
|
+ D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
|
|
|
|
|
+ currPixelBuffer->bind(d3d9Device, volume, textureResources->pBaseTex);
|
|
|
|
|
+
|
|
|
|
|
+ volume->Release();
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ PixelBufferPtr D3D9TextureCore::getBuffer(UINT32 face, UINT32 mipmap)
|
|
|
|
|
+ {
|
|
|
|
|
+ THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
+
|
|
|
|
|
+ if(face >= mProperties.getNumFaces())
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
|
|
|
|
|
+ if (mipmap > mProperties.getNumMipmaps())
|
|
|
|
|
+ BS_EXCEPT(InvalidParametersException, "Mipmap index out of range");
|
|
|
|
|
+
|
|
|
|
|
+ UINT32 idx = face*(mProperties.getNumMipmaps() + 1) + mipmap;
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
+ TextureResources* textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ createInternalResources(d3d9Device);
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ assert(textureResources != nullptr);
|
|
|
|
|
+ assert(idx < mSurfaceList.size());
|
|
|
|
|
+ return mSurfaceList[idx];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ bool D3D9TextureCore::useDefaultPool()
|
|
|
|
|
+ {
|
|
|
|
|
+ int usage = mProperties.getUsage();
|
|
|
|
|
+ return (usage & TU_RENDERTARGET) || (usage & TU_DEPTHSTENCIL) || ((usage & TU_DYNAMIC) && mDynamicTextures);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
+
|
|
|
|
|
+ if (D3D9RenderAPI::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
|
|
|
|
|
+ createInternalResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
+
|
|
|
|
|
+ auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
|
|
|
|
|
+
|
|
|
|
|
+ if (iterFind != mMapDeviceToTextureResources.end())
|
|
|
|
|
+ {
|
|
|
|
|
+ TextureResources* textureResource = iterFind->second;
|
|
|
|
|
+
|
|
|
|
|
+ for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
|
|
|
|
|
+
|
|
|
|
|
+ pixelBuffer->destroyBufferResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ freeTextureResources(d3d9Device, textureResource);
|
|
|
|
|
+
|
|
|
|
|
+ if(textureResource != nullptr)
|
|
|
|
|
+ bs_delete(textureResource);
|
|
|
|
|
+
|
|
|
|
|
+ mMapDeviceToTextureResources.erase(iterFind);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
+
|
|
|
|
|
+ if(mD3DPool == D3DPOOL_DEFAULT)
|
|
|
|
|
+ {
|
|
|
|
|
+ auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
|
|
|
|
|
+
|
|
|
|
|
+ if (iterFind != mMapDeviceToTextureResources.end())
|
|
|
|
|
+ {
|
|
|
|
|
+ TextureResources* textureResource = iterFind->second;
|
|
|
|
|
+ freeTextureResources(d3d9Device, textureResource);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void D3D9TextureCore::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
|
|
|
|
|
+ {
|
|
|
|
|
+ D3D9_DEVICE_ACCESS_CRITICAL_SECTION
|
|
|
|
|
+
|
|
|
|
|
+ if(mD3DPool == D3DPOOL_DEFAULT)
|
|
|
|
|
+ {
|
|
|
|
|
+ createInternalResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DBaseTexture9* D3D9TextureCore::getTexture_internal()
|
|
|
|
|
+ {
|
|
|
|
|
+ THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
+
|
|
|
|
|
+ TextureResources* textureResources;
|
|
|
|
|
+ IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
+
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ createInternalResources(d3d9Device);
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ assert(textureResources);
|
|
|
|
|
+ assert(textureResources->pBaseTex);
|
|
|
|
|
+
|
|
|
|
|
+ return textureResources->pBaseTex;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DTexture9* D3D9TextureCore::getNormTexture_internal()
|
|
|
|
|
+ {
|
|
|
|
|
+ THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
+
|
|
|
|
|
+ TextureResources* textureResources;
|
|
|
|
|
+ IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
+
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ if (textureResources == nullptr || textureResources->pNormTex == nullptr)
|
|
|
|
|
+ {
|
|
|
|
|
+ createInternalResources(d3d9Device);
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+ assert(textureResources);
|
|
|
|
|
+ assert(textureResources->pNormTex);
|
|
|
|
|
+
|
|
|
|
|
+ return textureResources->pNormTex;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ IDirect3DCubeTexture9* D3D9TextureCore::getCubeTexture_internal()
|
|
|
|
|
+ {
|
|
|
|
|
+ THROW_IF_NOT_CORE_THREAD;
|
|
|
|
|
+
|
|
|
|
|
+ TextureResources* textureResources;
|
|
|
|
|
+ IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
|
|
|
|
|
+
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ if (textureResources == nullptr || textureResources->pCubeTex)
|
|
|
|
|
+ {
|
|
|
|
|
+ createInternalResources(d3d9Device);
|
|
|
|
|
+ textureResources = getTextureResources(d3d9Device);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ assert(textureResources);
|
|
|
|
|
+ assert(textureResources->pCubeTex);
|
|
|
|
|
+
|
|
|
|
|
+ return textureResources->pCubeTex;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|