/******************************************************************************** Copyright (C) 2012 Hugh Bailey This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ********************************************************************************/ #include "Main.h" inline bool IsPow2(UINT num) { return num >= 2 && (num & (num-1)) == 0; } const DXGI_FORMAT convertFormat[] = {DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC5_UNORM}; const UINT formatPitch[] = {0, 1, 1, 4, 4, 4, 4, 8, 16, 0, 0, 0}; const D3D10_TEXTURE_ADDRESS_MODE convertAddressMode[] = {D3D10_TEXTURE_ADDRESS_CLAMP, D3D10_TEXTURE_ADDRESS_WRAP, D3D10_TEXTURE_ADDRESS_MIRROR, D3D10_TEXTURE_ADDRESS_BORDER, D3D10_TEXTURE_ADDRESS_MIRROR_ONCE}; const D3D10_FILTER convertFilter[] = {D3D10_FILTER_MIN_MAG_MIP_LINEAR, D3D10_FILTER_MIN_MAG_MIP_POINT, D3D10_FILTER_ANISOTROPIC, D3D10_FILTER_MIN_MAG_POINT_MIP_LINEAR, D3D10_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, D3D10_FILTER_MIN_POINT_MAG_MIP_LINEAR, D3D10_FILTER_MIN_LINEAR_MAG_MIP_POINT, D3D10_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR, D3D10_FILTER_MIN_MAG_LINEAR_MIP_POINT}; inline GSColorFormat GetGSFormatFromDXGIFormat(DXGI_FORMAT dxgiFormat) { UINT numVals = sizeof(convertFormat)/sizeof(DXGI_FORMAT); for (UINT i=0; iCreateSamplerState(&sampDesc, &state); if(FAILED(err)) { AppWarning(TEXT("D3D10SamplerState::CreateSamplerState: unable to create sampler state, result = %08lX"), err); return NULL; } //------------------------------------------- D3D10SamplerState *samplerState = new D3D10SamplerState; samplerState->state = state; mcpy(&samplerState->info, &info, sizeof(SamplerInfo)); return samplerState; } D3D10SamplerState::~D3D10SamplerState() { SafeRelease(state); } Texture* D3D10Texture::CreateFromSharedHandle(unsigned int width, unsigned int height, HANDLE handle) { HRESULT err; if(!handle) { AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: NULL handle value.")); return NULL; } ID3D10Resource *tempResource; if(FAILED(err = GetD3D()->OpenSharedResource(handle, __uuidof(ID3D10Resource), (void**)&tempResource))) { AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: Failed to open shared handle, result = 0x%08lX"), err); return NULL; } ID3D10Texture2D *texVal; if(FAILED(err = tempResource->QueryInterface(__uuidof(ID3D10Texture2D), (void**)&texVal))) { SafeRelease(tempResource); AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: could not query interface, result = 0x%08lX"), err); return NULL; } tempResource->Release(); //------------------------------------------ D3D10_TEXTURE2D_DESC td; texVal->GetDesc(&td); //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = td.Format; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = 1; ID3D10ShaderResourceView *resource = NULL; if(FAILED(err = GetD3D()->CreateShaderResourceView(texVal, &resourceDesc, &resource))) { SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateFromSharedHandle: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->format = GetGSFormatFromDXGIFormat(td.Format);; newTex->resource = resource; newTex->texture = texVal; newTex->bDynamic = false; newTex->width = width; newTex->height = height; return newTex; } Texture* D3D10Texture::CreateTexture(unsigned int width, unsigned int height, GSColorFormat colorFormat, void *lpData, BOOL bGenMipMaps, BOOL bStatic) { HRESULT err; if(colorFormat >= GS_DXT1) { AppWarning(TEXT("D3D10Texture::CreateTexture: tried to create a blank DXT texture. Use CreateFromFile instead.")); return NULL; } DXGI_FORMAT format = convertFormat[(UINT)colorFormat]; if(bGenMipMaps && (!IsPow2(width) || !IsPow2(height))) { AppWarning(TEXT("D3D10Texture::CreateTexture: Cannot generate mipmaps for a non-power-of-two sized texture. Disabling mipmap generation.")); bGenMipMaps = FALSE; } D3D10_TEXTURE2D_DESC td; zero(&td, sizeof(td)); td.Width = width; td.Height = height; td.MipLevels = bGenMipMaps ? 0 : 1; td.ArraySize = 1; td.Format = format; td.BindFlags = D3D10_BIND_SHADER_RESOURCE; td.SampleDesc.Count = 1; td.Usage = bStatic ? D3D10_USAGE_DEFAULT : D3D10_USAGE_DYNAMIC; td.CPUAccessFlags = bStatic ? 0 : D3D10_CPU_ACCESS_WRITE; D3D10_SUBRESOURCE_DATA srd; D3D10_SUBRESOURCE_DATA *lpSRD; if(lpData) { srd.pSysMem = lpData; srd.SysMemPitch = width*formatPitch[(UINT)colorFormat]; srd.SysMemSlicePitch = 0; lpSRD = &srd; } else lpSRD = NULL; ID3D10Texture2D *texVal; if(FAILED(err = GetD3D()->CreateTexture2D(&td, lpSRD, &texVal))) { AppWarning(TEXT("D3D10Texture::CreateTexture: CreateTexture2D failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = format; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = bGenMipMaps ? -1 : 1; ID3D10ShaderResourceView *resource; if(FAILED(err = GetD3D()->CreateShaderResourceView(texVal, &resourceDesc, &resource))) { SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateTexture: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->format = colorFormat; newTex->resource = resource; newTex->texture = texVal; newTex->bDynamic = !bStatic; newTex->width = width; newTex->height = height; return newTex; } Texture* D3D10Texture::CreateFromFile(CTSTR lpFile, BOOL bBuildMipMaps) { HRESULT err; D3DX10_IMAGE_INFO ii; if(FAILED(D3DX10GetImageInfoFromFile(lpFile, NULL, &ii, NULL))) { AppWarning(TEXT("D3D10Texture::CreateFromFile: Could not get information about texture file '%s'"), lpFile); return NULL; } //------------------------------------------ if(bBuildMipMaps && (!IsPow2(ii.Width) || !IsPow2(ii.Height))) bBuildMipMaps = FALSE; D3DX10_IMAGE_LOAD_INFO ili; ili.Width = D3DX10_DEFAULT; ili.Height = D3DX10_DEFAULT; ili.Depth = D3DX10_DEFAULT; ili.FirstMipLevel = D3DX10_DEFAULT; ili.MipLevels = bBuildMipMaps ? 0 : 1; ili.Usage = (D3D10_USAGE)D3DX10_DEFAULT; ili.BindFlags = D3DX10_DEFAULT; ili.CpuAccessFlags = D3DX10_DEFAULT; ili.MiscFlags = D3DX10_DEFAULT; ili.Format = (DXGI_FORMAT)D3DX10_DEFAULT; ili.Filter = D3DX10_DEFAULT; ili.MipFilter = D3DX10_DEFAULT; ili.pSrcInfo = NULL; ID3D10Resource *texResource; if(FAILED(err = D3DX10CreateTextureFromFile(GetD3D(), lpFile, &ili, NULL, &texResource, NULL))) { AppWarning(TEXT("D3D10Texture::CreateFromFile: failed to load '%s'"), lpFile); return NULL; } //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = ii.Format; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = bBuildMipMaps ? -1 : 1; ID3D10ShaderResourceView *resource; if(FAILED(err = GetD3D()->CreateShaderResourceView(texResource, &resourceDesc, &resource))) { SafeRelease(texResource); AppWarning(TEXT("D3D10Texture::CreateFromFile: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ ID3D10Texture2D *tex2D; err = texResource->QueryInterface(__uuidof(ID3D10Texture2D), (void**)&tex2D); if(FAILED(err)) { SafeRelease(texResource); SafeRelease(resource); AppWarning(TEXT("D3D10Texture::CreateFromFile: could not query texture interface")); return NULL; } texResource->Release(); //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->resource = resource; newTex->texture = tex2D; newTex->width = ii.Width; newTex->height = ii.Height; switch(ii.Format) { case DXGI_FORMAT_R8_UNORM: newTex->format = GS_ALPHA; break; case DXGI_FORMAT_A8_UNORM: newTex->format = GS_GRAYSCALE; break; case DXGI_FORMAT_B8G8R8X8_UNORM: newTex->format = GS_BGR; break; case DXGI_FORMAT_B8G8R8A8_UNORM: newTex->format = GS_BGRA; break; case DXGI_FORMAT_R8G8B8A8_UNORM: newTex->format = GS_RGBA; break; case DXGI_FORMAT_R16G16B16A16_FLOAT: newTex->format = GS_RGBA16F; break; case DXGI_FORMAT_R32G32B32A32_FLOAT: newTex->format = GS_RGBA32F; break; case DXGI_FORMAT_BC1_UNORM: newTex->format = GS_DXT1; break; case DXGI_FORMAT_BC2_UNORM: newTex->format = GS_DXT3; break; case DXGI_FORMAT_BC3_UNORM: newTex->format = GS_DXT5; break; default: newTex->format = GS_UNKNOWNFORMAT; } return newTex; } Texture* D3D10Texture::CreateRenderTarget(unsigned int width, unsigned int height, GSColorFormat colorFormat, BOOL bGenMipMaps) { HRESULT err; if(colorFormat >= GS_DXT1) { AppWarning(TEXT("D3D10Texture::CreateRenderTarget: tried to a blank DXT render target")); return NULL; } DXGI_FORMAT format = convertFormat[(UINT)colorFormat]; D3D10_TEXTURE2D_DESC td; zero(&td, sizeof(td)); td.Width = width; td.Height = height; td.MipLevels = bGenMipMaps ? 0 : 1; td.ArraySize = 1; td.Format = format; td.BindFlags = D3D10_BIND_SHADER_RESOURCE|D3D10_BIND_RENDER_TARGET; td.SampleDesc.Count = 1; td.Usage = D3D10_USAGE_DEFAULT; ID3D10Texture2D *texVal; if(FAILED(err = GetD3D()->CreateTexture2D(&td, NULL, &texVal))) { AppWarning(TEXT("D3D10Texture::CreateRenderTarget: CreateTexture2D failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = format; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = bGenMipMaps ? -1 : 1; ID3D10ShaderResourceView *resource; if(FAILED(err = GetD3D()->CreateShaderResourceView(texVal, &resourceDesc, &resource))) { SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateRenderTarget: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ ID3D10RenderTargetView *view; err = GetD3D()->CreateRenderTargetView(texVal, NULL, &view); if(FAILED(err)) { SafeRelease(texVal); SafeRelease(resource); AppWarning(TEXT("D3D10Texture::CreateRenderTarget: CreateRenderTargetView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->format = colorFormat; newTex->resource = resource; newTex->texture = texVal; newTex->renderTarget = view; newTex->width = width; newTex->height = height; return newTex; } Texture* D3D10Texture::CreateGDITexture(unsigned int width, unsigned int height) { HRESULT err; D3D10_TEXTURE2D_DESC td; zero(&td, sizeof(td)); td.Width = width; td.Height = height; td.MipLevels = 1; td.ArraySize = 1; td.Format = DXGI_FORMAT_B8G8R8A8_UNORM; td.BindFlags = D3D10_BIND_SHADER_RESOURCE|D3D10_BIND_RENDER_TARGET; td.SampleDesc.Count = 1; td.Usage = D3D10_USAGE_DEFAULT; td.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE; D3D10_SUBRESOURCE_DATA srd; zero(&srd, sizeof(srd)); ID3D10Texture2D *texVal; if(FAILED(err = GetD3D()->CreateTexture2D(&td, NULL, &texVal))) { AppWarning(TEXT("D3D10Texture::CreateGDITexture: CreateTexture2D failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = 1; ID3D10ShaderResourceView *resource; if(FAILED(err = GetD3D()->CreateShaderResourceView(texVal, &resourceDesc, &resource))) { SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateGDITexture: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->format = GS_BGRA; newTex->resource = resource; newTex->texture = texVal; newTex->width = width; newTex->height = height; newTex->bGDICompatible = true; return newTex; } Texture* D3D10Texture::CreateShared(unsigned int width, unsigned int height) { HRESULT err; D3D10_TEXTURE2D_DESC td; zero(&td, sizeof(td)); td.Width = width; td.Height = height; td.MipLevels = 1; td.ArraySize = 1; td.Format = DXGI_FORMAT_B8G8R8A8_UNORM; td.BindFlags = D3D10_BIND_SHADER_RESOURCE|D3D10_BIND_RENDER_TARGET; td.SampleDesc.Count = 1; td.Usage = D3D10_USAGE_DEFAULT; td.CPUAccessFlags = 0; td.MiscFlags = D3D10_RESOURCE_MISC_SHARED; ID3D10Texture2D *texVal; if(FAILED(err = GetD3D()->CreateTexture2D(&td, NULL, &texVal))) { AppWarning(TEXT("D3D10Texture::CreateShared: CreateTexture2D failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10_SHADER_RESOURCE_VIEW_DESC resourceDesc; zero(&resourceDesc, sizeof(resourceDesc)); resourceDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; resourceDesc.Texture2D.MipLevels = 1; ID3D10ShaderResourceView *resource; if(FAILED(err = GetD3D()->CreateShaderResourceView(texVal, &resourceDesc, &resource))) { SafeRelease(texVal); AppWarning(TEXT("D3D10Texture::CreateShared: CreateShaderResourceView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ ID3D10RenderTargetView *view; err = GetD3D()->CreateRenderTargetView(texVal, NULL, &view); if(FAILED(err)) { SafeRelease(texVal); SafeRelease(resource); AppWarning(TEXT("D3D10Texture::CreateShared: CreateRenderTargetView failed, result = 0x%08lX"), err); return NULL; } //------------------------------------------ D3D10Texture *newTex = new D3D10Texture; newTex->format = GS_BGRA; newTex->resource = resource; newTex->texture = texVal; newTex->renderTarget = view; newTex->width = width; newTex->height = height; return newTex; } D3D10Texture::~D3D10Texture() { SafeRelease(renderTarget); SafeRelease(resource); SafeRelease(texture); } DWORD D3D10Texture::Width() const { return width; } DWORD D3D10Texture::Height() const { return height; } BOOL D3D10Texture::HasAlpha() const { return format == 1 || (format >= GS_RGBA && format <= GS_RGBA32F) || format == GS_DXT3 || format == GS_DXT5; } GSColorFormat D3D10Texture::GetFormat() const { return (GSColorFormat)format; } bool D3D10Texture::GetDC(HDC &hDC) { if(!bGDICompatible) { AppWarning(TEXT("D3D10Texture::GetDC: function was called on a non-GDI-compatible texture")); return false; } HRESULT err; if(FAILED(err = texture->QueryInterface(__uuidof(IDXGISurface1), (void**)&surface))) { AppWarning(TEXT("D3D10Texture::GetDC: could not query surface interface, result = %08lX"), err); return false; } if(FAILED(err = surface->GetDC(TRUE, &hDC))) { AppWarning(TEXT("D3D10Texture::GetDC: could not get DC, result = %08lX"), err); SafeRelease(surface); return false; } return true; } void D3D10Texture::ReleaseDC() { if(!surface) { AppWarning(TEXT("D3D10Texture::ReleaseDC: no DC to release")); return; } surface->ReleaseDC(NULL); SafeRelease(surface); } //==================================================================================== void CopyPackedRGB(BYTE *lpDest, BYTE *lpSource, UINT nPixels) { DWORD curComponent = 0; UINT totalBytes = (nPixels*3); UINT alignedBytes = totalBytes&0xFFFFFFFC; UINT nDWords = alignedBytes>>2; DWORD *lpDWDest = (DWORD*)lpDest; DWORD *lpDWSrc = (DWORD*)lpSource; while(nDWords) { switch(curComponent) { case 0: *(lpDWDest++) = *lpDWSrc & 0xFFFFFF; *lpDWDest = *(lpDWSrc++)>>24; break; //RBGR case 1: *(lpDWDest++) |= ((*lpDWSrc)<<8) & 0xFFFF00; *lpDWDest = *(lpDWSrc++)>>16; break; //GRBG case 2: *(lpDWDest++) |= ((*lpDWSrc)<<16) & 0xFFFF00; *(lpDWDest++) = *(lpDWSrc++)>>8; break; //BGRB } if(curComponent == 2) curComponent = 0; else curComponent++; nDWords--; } totalBytes -= alignedBytes; lpSource = (LPBYTE)lpDWSrc; lpDest = (LPBYTE)lpDWDest; if(curComponent != 0) lpDest += curComponent; while(totalBytes--) { *(lpDest++) = *(lpSource++); if(curComponent == 2) { *(lpDest++) = 0; curComponent = 0; } else curComponent++; } } void D3D10Texture::SetImage(void *lpData, GSImageFormat imageFormat, UINT pitch) { if(!bDynamic) { AppWarning(TEXT("3D11Texture::SetImage: cannot call on a non-dynamic texture")); return; } bool bMatchingFormat = false; UINT pixelBytes = 0; //What is this needed for? switch(format) { case GS_ALPHA: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_A8); pixelBytes = 1; break; case GS_GRAYSCALE: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_L8); pixelBytes = 1; break; case GS_RGB: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_RGB || imageFormat == GS_IMAGEFORMAT_RGBX); pixelBytes = 4; break; case GS_RGBA: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_RGBA); pixelBytes = 4; break; case GS_BGR: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_BGR || imageFormat == GS_IMAGEFORMAT_BGRX); pixelBytes = 4; break; case GS_BGRA: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_BGRA); pixelBytes = 4; break; case GS_RGBA16F: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_RGBA16F); pixelBytes = 8; break; case GS_RGBA32F: bMatchingFormat = (imageFormat == GS_IMAGEFORMAT_RGBA32F); pixelBytes = 16; break; } if(!bMatchingFormat) { AppWarning(TEXT("D3D10Texture::SetImage: invalid or mismatching image format specified")); return; } HRESULT err; D3D10_MAPPED_TEXTURE2D map; if(FAILED(err = texture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map))) { AppWarning(TEXT("D3D10Texture::SetImage: map failed, result = %08lX"), err); return; } //------------------------------------------------------------------------- if((format == GS_RGB || format == GS_BGR) && (imageFormat == GS_IMAGEFORMAT_BGR || imageFormat == GS_IMAGEFORMAT_RGB)) { if(pitch == (width*3) && map.RowPitch == (width*4)) CopyPackedRGB((BYTE*)map.pData, (BYTE*)lpData, width*height); else { for(UINT y=0; yUnmap(0); } bool D3D10Texture::Map(BYTE *&lpData, UINT &pitch) { HRESULT err; D3D10_MAPPED_TEXTURE2D map; if(FAILED(err = texture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map))) { AppWarning(TEXT("D3D10Texture::Map: map failed, result = %08lX"), err); return false; } lpData = (BYTE*)map.pData; pitch = map.RowPitch; return true; } void D3D10Texture::Unmap() { texture->Unmap(0); } HANDLE D3D10Texture::GetSharedHandle() { HRESULT err; HANDLE handle = NULL; IDXGIResource *pDXGIResource; if FAILED(err = texture->QueryInterface(__uuidof(IDXGIResource), (void **)&pDXGIResource)) { AppWarning(TEXT("D3D10Texture::GetSharedHandle: QueryInterface failed, result = %08lX"), err); return handle; } if FAILED(err = pDXGIResource->GetSharedHandle(&handle)) { AppWarning(TEXT("D3D10Texture::GetSharedHandle: GetSharedHandle failed, result = %08lX"), err); } return handle; }