/* * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include "D3DResourceManager.h" #include "awt.h" #include "D3DPaints.h" #include "D3DTextRenderer.h" void D3DResource::Init(IDirect3DResource9 *pRes, IDirect3DSwapChain9 *pSC) { J2dTraceLn(J2D_TRACE_INFO, "D3DResource::Init"); pResource = NULL; pSwapChain = pSC; pSurface = NULL; pTexture = NULL; pOps = NULL; ZeroMemory(&desc, sizeof(desc)); desc.Format = D3DFMT_UNKNOWN; if (pRes != NULL) { pResource = pRes; D3DRESOURCETYPE type = pResource->GetType(); switch (type) { case D3DRTYPE_TEXTURE: // addRef is needed because both pResource and pTexture will be // Release()d, and they point to the same object pResource->AddRef(); pTexture = (IDirect3DTexture9*)pResource; pTexture->GetSurfaceLevel(0, &pSurface); break; case D3DRTYPE_SURFACE: pResource->AddRef(); pSurface = (IDirect3DSurface9*)pResource; break; case D3DRTYPE_CUBETEXTURE: ((IDirect3DCubeTexture9*)pResource)->GetLevelDesc(0, &desc); break; default: J2dTraceLn1(J2D_TRACE_VERBOSE, " resource type=%d", type); } } else if (pSwapChain != NULL) { pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface); } else { J2dTraceLn(J2D_TRACE_VERBOSE, " pResource == pSwapChain == NULL"); } if (pSurface != NULL) { pSurface->GetDesc(&desc); } SAFE_PRINTLN(pResource); SAFE_PRINTLN(pSurface); SAFE_PRINTLN(pTexture); SAFE_PRINTLN(pSwapChain); } D3DResource::~D3DResource() { Release(); } void D3DResource::SetSDOps(D3DSDOps *pOps) { if (pOps != NULL && this->pOps != NULL) { // something's wrong, we're overwriting // a non-null field (setting it to null is allowed) J2dTraceLn2(J2D_TRACE_WARNING, "D3DResource::SetSDOps: overwriting "\ "this->pOps=0x%x with pOps=0x%x", this->pOps, pOps); } this->pOps = pOps; } BOOL D3DResource::IsDefaultPool() { if (desc.Format != D3DFMT_UNKNOWN) { return (desc.Pool == D3DPOOL_DEFAULT); } return TRUE; } void D3DResource::Release() { J2dTraceLn(J2D_TRACE_INFO, "D3DResource::Release"); SAFE_PRINTLN(pResource); SAFE_PRINTLN(pSurface); SAFE_PRINTLN(pTexture); SAFE_PRINTLN(pSwapChain); SAFE_RELEASE(pSurface); SAFE_RELEASE(pTexture); SAFE_RELEASE(pResource); SAFE_RELEASE(pSwapChain); if (pOps != NULL) { // if sdOps is not NULL it means that the release was initiated // from the native level, and is caused by a surface loss D3DSD_MarkLost(pOps); pOps->pResource = NULL; pOps = NULL; } } HRESULT D3DResourceManager::CreateInstance(D3DContext *pCtx, D3DResourceManager** ppResourceMgr) { HRESULT res; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateInstance"); *ppResourceMgr = new D3DResourceManager(); if (FAILED(res = (*ppResourceMgr)->Init(pCtx))) { delete *ppResourceMgr; *ppResourceMgr = NULL; } return res; } D3DResourceManager::D3DResourceManager() { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::D3DRM"); this->pCtx = NULL; this->pHead = NULL; } HRESULT D3DResourceManager::Init(D3DContext *pCtx) { J2dTraceLn1(J2D_TRACE_INFO, "D3DRM::Init pCtx=%x", pCtx); if (this->pCtx != pCtx || (this->pCtx != NULL && this->pCtx->Get3DDevice() != pCtx->Get3DDevice())) { ReleaseAll(); } this->pCtx = pCtx; return S_OK; } D3DResourceManager::~D3DResourceManager() { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::~D3DRM"); ReleaseAll(); pCtx = NULL; pHead = NULL; } void D3DResourceManager::ReleaseAll() { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::ReleaseAll"); IManagedResource* pCurrent; while (pHead != NULL) { pCurrent = pHead; pHead = pHead->pNext; delete pCurrent; } pCachedDestTexture = NULL; pBlitTexture = NULL; pBlitRTTexture = NULL; pBlitOSPSurface = NULL; pGradientTexture = NULL; pLookupOpLutTexture = NULL; pMaskTexture = NULL; pMultiGradientTexture = NULL; pLockableRTSurface = NULL; } void D3DResourceManager::ReleaseDefPoolResources() { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::ReleaseDefPoolResources"); // REMIND: for now, release all resources ReleaseAll(); } HRESULT D3DResourceManager::ReleaseResource(IManagedResource* pResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::ReleaseResource"); if (pResource != NULL) { J2dTraceLn1(J2D_TRACE_VERBOSE, " releasing pResource=%x", pResource); if (pResource->pPrev != NULL) { pResource->pPrev->pNext = pResource->pNext; } else { // it's the head pHead = pResource->pNext; if (pHead != NULL) { pHead->pPrev = NULL; } } if (pResource->pNext != NULL) { pResource->pNext->pPrev = pResource->pPrev; } delete pResource; } return S_OK; } HRESULT D3DResourceManager::AddResource(IManagedResource* pResource) { HRESULT res = S_OK; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::AddResource"); if (pResource != NULL) { J2dTraceLn1(J2D_TRACE_VERBOSE, " pResource=%x", pResource); pResource->pPrev = NULL; pResource->pNext = pHead; if (pHead != NULL) { pHead->pPrev = pResource; } pHead = pResource; } return S_OK; } HRESULT D3DResourceManager::CreateTexture(UINT width, UINT height, BOOL isRTT, BOOL isOpaque, D3DFORMAT *pFormat, DWORD dwUsage, D3DResource **ppTextureResource) { D3DPOOL pool; D3DFORMAT format; HRESULT res; IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateTexture"); J2dTraceLn4(J2D_TRACE_VERBOSE, " w=%d h=%d isRTT=%d isOpaque=%d", width, height, isRTT, isOpaque); if (ppTextureResource == NULL || pCtx == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) { return E_FAIL; } if (FAILED(res = pd3dDevice->TestCooperativeLevel())) { return res; } if (pFormat != NULL && *pFormat != D3DFMT_UNKNOWN) { format = *pFormat; } else { if (isOpaque) { format = D3DFMT_X8R8G8B8; } else { format = D3DFMT_A8R8G8B8; } } if (isRTT) { dwUsage = D3DUSAGE_RENDERTARGET; pool = D3DPOOL_DEFAULT; } else { if (dwUsage == D3DUSAGE_DYNAMIC && !pCtx->IsDynamicTextureSupported()) { dwUsage = 0; } if (dwUsage == D3DUSAGE_DYNAMIC) { pool = D3DPOOL_DEFAULT; } else { pool = pCtx->IsHWRasterizer() ? D3DPOOL_MANAGED : D3DPOOL_SYSTEMMEM; } } if (pCtx->IsPow2TexturesOnly()) { UINT w, h; for (w = 1; width > w; w <<= 1); for (h = 1; height > h; h <<= 1); width = w; height = h; } if (pCtx->IsSquareTexturesOnly()) { if (width > height) { height = width; } else { width = height; } } IDirect3DTexture9 *pTexture = NULL; res = pd3dDevice->CreateTexture(width, height, 1/*levels*/, dwUsage, format, pool, &pTexture, 0); if (SUCCEEDED(res)) { J2dTraceLn1(J2D_TRACE_VERBOSE, " created texture: 0x%x", pTexture); *ppTextureResource = new D3DResource((IDirect3DResource9*)pTexture); res = AddResource(*ppTextureResource); } else { DebugPrintD3DError(res, "D3DRM::CreateTexture failed"); *ppTextureResource = NULL; format = D3DFMT_UNKNOWN; } if (pFormat != NULL) { *pFormat = format; } return res; } HRESULT D3DResourceManager::CreateRTSurface(UINT width, UINT height, BOOL isOpaque, BOOL isLockable, D3DFORMAT *pFormat/*out*/, D3DResource** ppSurfaceResource/*out*/) { HRESULT res; IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateRTSurface"); J2dTraceLn3(J2D_TRACE_VERBOSE, " w=%d h=%d isOpaque=%d", width, height, isOpaque); if (pCtx == NULL || ppSurfaceResource == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) { return E_FAIL; } if (FAILED(res = pd3dDevice->TestCooperativeLevel())) { return res; } D3DPRESENT_PARAMETERS *curParams = pCtx->GetPresentationParams(); D3DFORMAT format = isOpaque ? curParams->BackBufferFormat : D3DFMT_A8R8G8B8; IDirect3DSurface9 *pSurface = NULL; res = pd3dDevice->CreateRenderTarget(width, height, format, D3DMULTISAMPLE_NONE, 0, isLockable, &pSurface, NULL); if (SUCCEEDED(res)) { J2dTraceLn1(J2D_TRACE_VERBOSE, " created RT Surface: 0x%x ", pSurface); if (pFormat != NULL) { *pFormat = format; } *ppSurfaceResource = new D3DResource((IDirect3DResource9*)pSurface); res = AddResource(*ppSurfaceResource); } else { DebugPrintD3DError(res, "D3DRM::CreateRTSurface failed"); ppSurfaceResource = NULL; } return res; } // REMIND: this method is currently unused; consider removing it later... HRESULT D3DResourceManager::CreateOSPSurface(UINT width, UINT height, D3DFORMAT fmt, D3DResource** ppSurfaceResource/*out*/) { HRESULT res; IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateOSPSurface"); J2dTraceLn2(J2D_TRACE_VERBOSE, " w=%d h=%d", width, height); if (pCtx == NULL || ppSurfaceResource == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) { return E_FAIL; } if (FAILED(res = pd3dDevice->TestCooperativeLevel())) { return res; } // since the off-screen plain surface is intended to be used with // the UpdateSurface() method, it is essential that it be created // in the same format as the destination and allocated in the // SYSTEMMEM pool (otherwise UpdateSurface() will fail) D3DFORMAT format; if (fmt == D3DFMT_UNKNOWN) { format = pCtx->GetPresentationParams()->BackBufferFormat; } else { format = fmt; } D3DPOOL pool = D3DPOOL_SYSTEMMEM; IDirect3DSurface9 *pSurface = NULL; res = pd3dDevice->CreateOffscreenPlainSurface(width, height, format, pool, &pSurface, NULL); if (SUCCEEDED(res)) { J2dTraceLn1(J2D_TRACE_VERBOSE, " created OSP Surface: 0x%x ",pSurface); *ppSurfaceResource = new D3DResource((IDirect3DResource9*)pSurface); res = AddResource(*ppSurfaceResource); } else { DebugPrintD3DError(res, "D3DRM::CreateOSPSurface failed"); ppSurfaceResource = NULL; } return res; } HRESULT D3DResourceManager::CreateSwapChain(HWND hWnd, UINT numBuffers, UINT width, UINT height, D3DSWAPEFFECT swapEffect, UINT presentationInterval, D3DResource ** ppSwapChainResource) { HRESULT res; IDirect3DDevice9 *pd3dDevice; IDirect3DSwapChain9 *pSwapChain = NULL; D3DPRESENT_PARAMETERS newParams, *curParams; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateSwapChain"); J2dTraceLn4(J2D_TRACE_VERBOSE, " w=%d h=%d hwnd=%x numBuffers=%d", width, height, hWnd, numBuffers); if (pCtx == NULL || ppSwapChainResource == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) { return E_FAIL; } RETURN_STATUS_IF_FAILED(res = pd3dDevice->TestCooperativeLevel()); curParams = pCtx->GetPresentationParams(); if (curParams->Windowed == FALSE) { // there's a single swap chain in full-screen mode, use it if // it fits our parameters, reset the device otherwise if (curParams->BackBufferCount != numBuffers || curParams->SwapEffect != swapEffect || curParams->PresentationInterval != presentationInterval) { newParams = *curParams; newParams.BackBufferCount = numBuffers; newParams.SwapEffect = swapEffect; newParams.PresentationInterval = presentationInterval; res = pCtx->ConfigureContext(&newParams); RETURN_STATUS_IF_FAILED(res); // this reset will not have released the device, so our pd3dDevice // is still valid, but to be on a safe side, reset it pd3dDevice = pCtx->Get3DDevice(); } res = pd3dDevice->GetSwapChain(0, &pSwapChain); } else { ZeroMemory(&newParams, sizeof(D3DPRESENT_PARAMETERS)); newParams.BackBufferWidth = width; newParams.BackBufferHeight = height; newParams.hDeviceWindow = hWnd; newParams.Windowed = TRUE; newParams.BackBufferCount = numBuffers; newParams.SwapEffect = swapEffect; newParams.PresentationInterval = presentationInterval; res = pd3dDevice->CreateAdditionalSwapChain(&newParams, &pSwapChain); } if (SUCCEEDED(res)) { J2dTraceLn1(J2D_TRACE_VERBOSE," created swap chain: 0x%x ",pSwapChain); *ppSwapChainResource = new D3DResource(pSwapChain); res = AddResource(*ppSwapChainResource); } else { DebugPrintD3DError(res, "D3DRM::CreateSwapChain failed"); *ppSwapChainResource = NULL; } return res; } HRESULT D3DResourceManager::GetMaskTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetMaskTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); D3DFORMAT format = pCtx->IsTextureFormatSupported(D3DFMT_A8) ? D3DFMT_A8 : D3DFMT_A8R8G8B8; jboolean needsInit = (pMaskTexture == NULL); HRESULT res; if (FAILED(res = GetStockTextureResource(D3D_MASK_CACHE_WIDTH_IN_TEXELS, D3D_MASK_CACHE_HEIGHT_IN_TEXELS, FALSE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pMaskTexture))) { return res; } if (needsInit) { // init special fully opaque tile in the upper-right corner of // the mask cache texture jubyte allOnes[D3D_MASK_CACHE_TILE_SIZE]; memset(allOnes, 0xff, D3D_MASK_CACHE_TILE_SIZE); if (FAILED(res = pCtx->UploadTileToTexture( pMaskTexture, allOnes, D3D_MASK_CACHE_SPECIAL_TILE_X, D3D_MASK_CACHE_SPECIAL_TILE_Y, 0, 0, D3D_MASK_CACHE_TILE_WIDTH, D3D_MASK_CACHE_TILE_HEIGHT, D3D_MASK_CACHE_TILE_WIDTH, TILEFMT_1BYTE_ALPHA))) { return res; } } *ppTextureResource = pMaskTexture; return res; } HRESULT D3DResourceManager::GetBlitTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetBlitTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(D3DC_BLIT_TILE_SIZE, D3DC_BLIT_TILE_SIZE, FALSE/*isRTT*/, FALSE/*isOpaque*/, NULL, D3DUSAGE_DYNAMIC, &pBlitTexture); *ppTextureResource = pBlitTexture; return res; } HRESULT D3DResourceManager::GetGradientTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetGradientTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(2, 1, FALSE/*isRTT*/, FALSE/*isOpaque*/, NULL, 0, &pGradientTexture); *ppTextureResource = pGradientTexture; return res; } HRESULT D3DResourceManager::GetMultiGradientTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetMultiGradientTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(MAX_MULTI_GRADIENT_COLORS, 1, FALSE/*isRTT*/, FALSE/*isOpaque*/, NULL, 0, &pMultiGradientTexture); *ppTextureResource = pMultiGradientTexture; return res; } HRESULT D3DResourceManager::GetLookupOpLutTexture(D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetLookupOpTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); D3DFORMAT format = D3DFMT_L16; HRESULT res = GetStockTextureResource(256, 4, FALSE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pLookupOpLutTexture); *ppTextureResource = pLookupOpLutTexture; return res; } HRESULT D3DResourceManager::GetBlitRTTexture(UINT width, UINT height, D3DFORMAT format, D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetBlitRTTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(width, height, TRUE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pBlitRTTexture); if (SUCCEEDED(res)) { D3DSURFACE_DESC *pDesc = pBlitRTTexture->GetDesc(); D3DCAPS9 *pDevCaps = pCtx->GetDeviceCaps(); if ((width <= pDesc->Width && height <= pDesc->Height) && (format == pDesc->Format || SUCCEEDED(pCtx->Get3DObject()->CheckDeviceFormatConversion( pDevCaps->AdapterOrdinal, pDevCaps->DeviceType, format, pDesc->Format)))) { *ppTextureResource = pBlitRTTexture; return res; } // current texture doesn't fit, release and allocate a new one ReleaseResource(pBlitRTTexture); pBlitRTTexture = NULL; } if (width < D3DC_BLIT_TILE_SIZE) width = D3DC_BLIT_TILE_SIZE; if (height < D3DC_BLIT_TILE_SIZE) height = D3DC_BLIT_TILE_SIZE; res = CreateTexture(width, height, TRUE, FALSE, &format, 0,&pBlitRTTexture); *ppTextureResource = pBlitRTTexture; return res; } HRESULT D3DResourceManager::GetBlitOSPSurface(UINT width, UINT height, D3DFORMAT fmt, D3DResource **ppSurfaceResource) { HRESULT res = S_OK; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetBlitOSPSurface"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppSurfaceResource, E_FAIL); if (pBlitOSPSurface != NULL) { D3DSURFACE_DESC *pDesc = pBlitOSPSurface->GetDesc(); if (width == pDesc->Width && height == pDesc->Height && (fmt == pDesc->Format || fmt == D3DFMT_UNKNOWN)) { *ppSurfaceResource = pBlitOSPSurface; return res; } // current surface doesn't fit, release and allocate a new one ReleaseResource(pBlitOSPSurface); pBlitOSPSurface = NULL; } res = CreateOSPSurface(width, height, fmt, &pBlitOSPSurface); *ppSurfaceResource = pBlitOSPSurface; return res; } HRESULT D3DResourceManager::GetLockableRTSurface(UINT width, UINT height, D3DFORMAT format, D3DResource **ppSurfaceResource) { HRESULT res = S_OK; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetLockableRTSurface"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppSurfaceResource, E_FAIL); if (pLockableRTSurface != NULL) { D3DSURFACE_DESC *pDesc = pLockableRTSurface->GetDesc(); if (width <= pDesc->Width && height <= pDesc->Height && format == pDesc->Format) { *ppSurfaceResource = pLockableRTSurface; return res; } // current surface doesn't fit, release and allocate a new one ReleaseResource(pLockableRTSurface); pLockableRTSurface = NULL; } if (width < D3DC_BLIT_TILE_SIZE) width = D3DC_BLIT_TILE_SIZE; if (height < D3DC_BLIT_TILE_SIZE) height = D3DC_BLIT_TILE_SIZE; res = CreateRTSurface(width,height, (format != D3DFMT_A8R8G8B8), TRUE /*lockable*/, &format, &pLockableRTSurface); *ppSurfaceResource = pLockableRTSurface; return res; } HRESULT D3DResourceManager::GetCachedDestTexture(D3DFORMAT format, D3DResource **ppTextureResource) { J2dTraceLn(J2D_TRACE_INFO, "D3DRM::GetCachedDestTexture"); RETURN_STATUS_IF_NULL(pCtx, E_FAIL); RETURN_STATUS_IF_NULL(ppTextureResource, E_FAIL); HRESULT res = GetStockTextureResource(D3DTR_CACHED_DEST_WIDTH, D3DTR_CACHED_DEST_HEIGHT, TRUE/*isRTT*/, FALSE/*isOpaque*/, &format, 0, &pCachedDestTexture); if (SUCCEEDED(res)) { D3DSURFACE_DESC *pDesc = pCachedDestTexture->GetDesc(); D3DCAPS9 *pDevCaps = pCtx->GetDeviceCaps(); if ((format == pDesc->Format || SUCCEEDED(pCtx->Get3DObject()->CheckDeviceFormatConversion( pDevCaps->AdapterOrdinal, pDevCaps->DeviceType, format, pDesc->Format)))) { *ppTextureResource = pCachedDestTexture; return res; } // current texture doesn't fit, release and allocate a new one ReleaseResource(pCachedDestTexture); pCachedDestTexture = NULL; } res = CreateTexture(D3DTR_CACHED_DEST_WIDTH, D3DTR_CACHED_DEST_HEIGHT, TRUE, FALSE, &format, 0, &pCachedDestTexture); *ppTextureResource = pCachedDestTexture; return res; } HRESULT D3DResourceManager::GetStockTextureResource(UINT width, UINT height, BOOL isRTT, BOOL isOpaque, D3DFORMAT *pFormat/*in/out*/, DWORD dwUsage, D3DResource **ppTextureResource) { D3DResource *pResource = *ppTextureResource; if (pResource != NULL) { if (pResource->GetTexture() != NULL) { return S_OK; } ReleaseResource(pResource); *ppTextureResource = NULL; } return CreateTexture(width, height, isRTT, isOpaque, pFormat, dwUsage, ppTextureResource); }