#include "CmMultiRenderTexture.h" #include "CmTexture.h" #include "CmException.h" namespace CamelotEngine { MultiRenderTexture::MultiRenderTexture() { mColorSurfaces.resize(CM_MAX_MULTIPLE_RENDER_TARGETS); } void MultiRenderTexture::setColorSurface(UINT32 surfaceIdx, TexturePtr texture, UINT32 face, UINT32 numFaces, UINT32 mipLevel) { if(surfaceIdx < 0 || surfaceIdx >= CM_MAX_MULTIPLE_RENDER_TARGETS) CM_EXCEPT(InvalidParametersException, "Invalid surface index. 0 <= " + toString(surfaceIdx) + " < CM_MAX_MULTIPLE_RENDER_TARGETS"); if(texture != nullptr && texture->getUsage() != TU_RENDERTARGET) CM_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage."); if(mColorSurfaces[surfaceIdx] != nullptr) { mColorSurfaces[surfaceIdx]->getTexture()->releaseView(mColorSurfaces[surfaceIdx]); mColorSurfaces[surfaceIdx] = nullptr; } if(texture == nullptr) { setColorSurfaceImpl(surfaceIdx, texture, face, numFaces, mipLevel); return; } mColorSurfaces[surfaceIdx] = Texture::requestView(texture, mipLevel, 1, face, numFaces, GVU_RENDERTARGET); mPriority = CM_REND_TO_TEX_RT_GROUP; mWidth = texture->getWidth(); mHeight = texture->getWidth(); mColorDepth = CamelotEngine::PixelUtil::getNumElemBits(texture->getFormat()); mActive = true; mHwGamma = texture->isHardwareGammaEnabled(); mFSAA = texture->getFSAA(); mFSAAHint = texture->getFSAAHint(); throwIfBuffersDontMatch(); setColorSurfaceImpl(surfaceIdx, texture, face, numFaces, mipLevel); } void MultiRenderTexture::setDepthStencilSurface(TexturePtr depthStencil, UINT32 face, UINT32 numFaces, UINT32 mipLevel) { if(depthStencil != nullptr && depthStencil->getUsage() != TU_DEPTHSTENCIL) CM_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage."); if(mDepthStencilSurface != nullptr) { Texture::releaseView(mDepthStencilSurface); mDepthStencilSurface = nullptr; } if(depthStencil == nullptr) return; mDepthStencilSurface = Texture::requestView(depthStencil, mipLevel, 1, face, numFaces, GVU_DEPTHSTENCIL); throwIfBuffersDontMatch(); setDepthStencilImpl(depthStencil, face, numFaces, mipLevel); } void MultiRenderTexture::throwIfBuffersDontMatch() const { const TextureView* firstSurfaceDesc = nullptr; for(size_t i = 0; i < mColorSurfaces.size(); i++) { if(mColorSurfaces[i] == nullptr) continue; if(firstSurfaceDesc == nullptr) { firstSurfaceDesc = mColorSurfaces[i]; continue; } if(mColorSurfaces[i]->getTexture()->getWidth() != firstSurfaceDesc->getTexture()->getWidth() || mColorSurfaces[i]->getTexture()->getHeight() != firstSurfaceDesc->getTexture()->getHeight() || mColorSurfaces[i]->getTexture()->getFSAA() != firstSurfaceDesc->getTexture()->getFSAA() || mColorSurfaces[i]->getTexture()->getFSAAHint() != firstSurfaceDesc->getTexture()->getFSAAHint()) { String errorInfo = "\nWidth: " + toString(mColorSurfaces[i]->getTexture()->getWidth()) + "/" + toString(firstSurfaceDesc->getTexture()->getWidth()); errorInfo += "\nHeight: " + toString(mColorSurfaces[i]->getTexture()->getHeight()) + "/" + toString(firstSurfaceDesc->getTexture()->getHeight()); errorInfo += "\nFSAA: " + toString(mColorSurfaces[i]->getTexture()->getFSAA()) + "/" + toString(firstSurfaceDesc->getTexture()->getFSAA()); errorInfo += "\nFSAAHint: " + mColorSurfaces[i]->getTexture()->getFSAAHint() + "/" + firstSurfaceDesc->getTexture()->getFSAAHint(); CM_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo); } } if(firstSurfaceDesc == nullptr) return; if(firstSurfaceDesc->getTexture()->getTextureType() != TEX_TYPE_2D) CM_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces."); if((firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) >= firstSurfaceDesc->getTexture()->getNumFaces()) { CM_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " + toString(firstSurfaceDesc->getFirstArraySlice() + firstSurfaceDesc->getNumArraySlices()) + ". Max num faces: " + toString(firstSurfaceDesc->getTexture()->getNumFaces())); } if(firstSurfaceDesc->getMostDetailedMip() >= firstSurfaceDesc->getTexture()->getNumMipmaps()) { CM_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " + toString(firstSurfaceDesc->getMostDetailedMip()) + ". Max num mipmaps: " + toString(firstSurfaceDesc->getTexture()->getNumMipmaps())); } if(mDepthStencilSurface == nullptr) return; if(mDepthStencilSurface->getTexture()->getWidth() != firstSurfaceDesc->getTexture()->getWidth() || mDepthStencilSurface->getTexture()->getHeight() != firstSurfaceDesc->getTexture()->getHeight() || mDepthStencilSurface->getTexture()->getFSAA() != firstSurfaceDesc->getTexture()->getFSAA() || mDepthStencilSurface->getTexture()->getFSAAHint() != firstSurfaceDesc->getTexture()->getFSAAHint()) { String errorInfo = "\nWidth: " + toString(mDepthStencilSurface->getTexture()->getWidth()) + "/" + toString(firstSurfaceDesc->getTexture()->getWidth()); errorInfo += "\nHeight: " + toString(mDepthStencilSurface->getTexture()->getHeight()) + "/" + toString(firstSurfaceDesc->getTexture()->getHeight()); errorInfo += "\nFSAA: " + toString(mDepthStencilSurface->getTexture()->getFSAA()) + "/" + toString(firstSurfaceDesc->getTexture()->getFSAA()); errorInfo += "\nFSAAHint: " + mDepthStencilSurface->getTexture()->getFSAAHint() + "/" + firstSurfaceDesc->getTexture()->getFSAAHint(); CM_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo); } } void MultiRenderTexture::copyContentsToMemory( const PixelData &dst, FrameBuffer buffer /*= FB_AUTO */ ) { throw std::exception("The method or operation is not implemented."); } }