summaryrefslogtreecommitdiffstats
path: root/src/Runtime/Source/runtimerender/Qt3DSRenderTextTextureCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/Source/runtimerender/Qt3DSRenderTextTextureCache.cpp')
-rw-r--r--src/Runtime/Source/runtimerender/Qt3DSRenderTextTextureCache.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/Runtime/Source/runtimerender/Qt3DSRenderTextTextureCache.cpp b/src/Runtime/Source/runtimerender/Qt3DSRenderTextTextureCache.cpp
new file mode 100644
index 00000000..304e64b6
--- /dev/null
+++ b/src/Runtime/Source/runtimerender/Qt3DSRenderTextTextureCache.cpp
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "Qt3DSRenderTextTextureCache.h"
+#include "Qt3DSTextRenderer.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/Qt3DSInvasiveLinkedList.h"
+#include "foundation/Qt3DSPool.h"
+
+using namespace qt3ds::render;
+
+namespace eastl {
+template <>
+struct hash<STextRenderInfo>
+{
+ size_t operator()(const qt3ds::render::STextRenderInfo &inInfo) const
+ {
+ size_t retval = hash<size_t>()(reinterpret_cast<size_t>(inInfo.m_Text.c_str()));
+ retval = retval ^ hash<size_t>()(reinterpret_cast<size_t>(inInfo.m_Font.c_str()));
+ retval = retval ^ hash<float>()(inInfo.m_FontSize);
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_HorizontalAlignment));
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_VerticalAlignment));
+ retval = retval ^ hash<float>()(inInfo.m_Leading);
+ retval = retval ^ hash<float>()(inInfo.m_Tracking);
+ retval = retval ^ hash<bool>()(inInfo.m_DropShadow);
+ retval = retval ^ hash<float>()(inInfo.m_DropShadowStrength);
+ retval = retval ^ hash<float>()(inInfo.m_DropShadowOffset); // To be removed in 2.x (when UIP version is next updated)
+ retval = retval ^ hash<float>()(inInfo.m_DropShadowOffsetX);
+ retval = retval ^ hash<float>()(inInfo.m_DropShadowOffsetY);
+ retval = retval ^ hash<float>()(inInfo.m_BoundingBox.x);
+ retval = retval ^ hash<float>()(inInfo.m_BoundingBox.y);
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_Elide));
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_DropShadowHorizontalAlignment)); // To be removed in 2.x (when UIP version is next updated)
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_DropShadowVerticalAlignment)); // To be removed in 2.x (when UIP version is next updated)
+ retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_WordWrap));
+ retval = retval ^ hash<bool>()(inInfo.m_EnableAcceleratedFont);
+ return retval;
+ }
+};
+}
+
+namespace {
+struct STextRenderInfoAndHash
+{
+ STextRenderInfo m_Info;
+ QT3DSF32 m_ScaleFactor;
+ size_t m_Hashcode;
+ STextRenderInfoAndHash(const STextRenderInfo &inInfo, QT3DSF32 inScaleFactor)
+ : m_Info(inInfo)
+ , m_ScaleFactor(inScaleFactor)
+ , m_Hashcode(eastl::hash<STextRenderInfo>()(inInfo) ^ eastl::hash<float>()(inScaleFactor))
+ {
+ }
+ bool operator==(const STextRenderInfoAndHash &inOther) const
+ {
+ return m_Info.m_Text == inOther.m_Info.m_Text && m_Info.m_Font == inOther.m_Info.m_Font
+ && m_Info.m_FontSize == inOther.m_Info.m_FontSize
+ && m_Info.m_HorizontalAlignment == inOther.m_Info.m_HorizontalAlignment
+ && m_Info.m_VerticalAlignment == inOther.m_Info.m_VerticalAlignment
+ && m_Info.m_Leading == inOther.m_Info.m_Leading
+ && m_Info.m_Tracking == inOther.m_Info.m_Tracking
+ && m_Info.m_DropShadow == inOther.m_Info.m_DropShadow
+ && m_Info.m_DropShadowStrength == inOther.m_Info.m_DropShadowStrength
+ && m_Info.m_DropShadowOffset == inOther.m_Info.m_DropShadowOffset
+ && m_Info.m_DropShadowHorizontalAlignment
+ == inOther.m_Info.m_DropShadowHorizontalAlignment
+ && m_Info.m_DropShadowVerticalAlignment == inOther.m_Info.m_DropShadowVerticalAlignment
+ && m_Info.m_BoundingBox == inOther.m_Info.m_BoundingBox
+ && m_Info.m_WordWrap == inOther.m_Info.m_WordWrap
+ && m_Info.m_EnableAcceleratedFont == inOther.m_Info.m_EnableAcceleratedFont
+ && m_ScaleFactor == inOther.m_ScaleFactor;
+ }
+};
+}
+
+namespace eastl {
+template <>
+struct hash<STextRenderInfoAndHash>
+{
+ size_t operator()(const STextRenderInfoAndHash &inInfo) const { return inInfo.m_Hashcode; }
+};
+};
+
+namespace {
+
+struct STextCacheNode
+{
+ STextCacheNode *m_PreviousSibling;
+ STextCacheNode *m_NextSibling;
+ STextRenderInfoAndHash m_RenderInfo;
+ TTPathObjectAndTexture m_TextInfo;
+ QT3DSU32 m_FrameCount;
+
+ STextCacheNode(const STextRenderInfoAndHash &inRenderInfo,
+ const TTPathObjectAndTexture &inTextInfo)
+ : m_PreviousSibling(NULL)
+ , m_NextSibling(NULL)
+ , m_RenderInfo(inRenderInfo)
+ , m_TextInfo(inTextInfo)
+ , m_FrameCount(0)
+ {
+ }
+};
+
+typedef nvhash_map<STextRenderInfoAndHash, STextCacheNode *> TTextureInfoHash;
+
+DEFINE_INVASIVE_LIST(TextCacheNode);
+IMPLEMENT_INVASIVE_LIST(TextCacheNode, m_PreviousSibling, m_NextSibling);
+
+struct STextTextureCache : public ITextTextureCache
+{
+ typedef Pool<STextCacheNode, ForwardingAllocator> TPoolType;
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+ NVScopedRefCounted<ITextRenderer> m_TextRenderer;
+ TTextureInfoHash m_TextureCache;
+ TTextCacheNodeList m_LRUList;
+ TPoolType m_CacheNodePool;
+ QT3DSU32 m_HighWaterMark;
+ QT3DSU32 m_FrameCount;
+ QT3DSU32 m_TextureTotalBytes;
+ NVScopedRefCounted<NVRenderContext> m_RenderContext;
+ bool m_CanUsePathRendering; ///< true if we use hardware accelerated font rendering
+
+ STextTextureCache(NVFoundationBase &inFnd, ITextRenderer &inRenderer,
+ NVRenderContext &inRenderContext)
+ : m_Foundation(inFnd)
+ , mRefCount(0)
+ , m_TextRenderer(inRenderer)
+ , m_TextureCache(m_Foundation.getAllocator(), "STextTextureCache::m_TextureCache")
+ , m_CacheNodePool(ForwardingAllocator(m_Foundation.getAllocator(),
+ "STextTextureCache::m_CacheNodePool"))
+ , m_HighWaterMark(0x100000)
+ , m_FrameCount(0)
+ , m_TextureTotalBytes(0)
+ , m_RenderContext(inRenderContext)
+ {
+ // hardware accelerate font rendering not ready yet
+ m_CanUsePathRendering = (m_RenderContext->IsPathRenderingSupported()
+ && m_RenderContext->IsProgramPipelineSupported());
+ }
+
+ virtual ~STextTextureCache()
+ {
+ for (TTextCacheNodeList::iterator iter = m_LRUList.begin(), end = m_LRUList.end();
+ iter != end; ++iter)
+ iter->~STextCacheNode();
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ static inline QT3DSU32 GetNumBytes(NVRenderTexture2D &inTexture)
+ {
+ STextureDetails theDetails(inTexture.GetTextureDetails());
+ return theDetails.m_Width * theDetails.m_Height
+ * NVRenderTextureFormats::getSizeofFormat(theDetails.m_Format);
+ }
+
+ NVScopedRefCounted<NVRenderTexture2D> InvalidateLastItem()
+ {
+ NVScopedRefCounted<NVRenderTexture2D> nextTexture;
+ if (m_LRUList.empty() == false) {
+ STextCacheNode &theEnd = m_LRUList.back();
+ if (theEnd.m_FrameCount != m_FrameCount) {
+ nextTexture = theEnd.m_TextInfo.second.second;
+ STextureDetails theDetails = nextTexture->GetTextureDetails();
+ m_TextureTotalBytes -= GetNumBytes(*nextTexture.mPtr);
+ m_LRUList.remove(theEnd);
+ // copy the key because the next statement will destroy memory
+ m_TextureCache.erase(theEnd.m_RenderInfo);
+ theEnd.~STextCacheNode();
+ m_CacheNodePool.deallocate(&theEnd);
+ }
+ }
+ return nextTexture;
+ }
+
+ TTPathObjectAndTexture RenderText(const STextRenderInfo &inText, QT3DSF32 inScaleFactor) override
+ {
+ STextRenderInfoAndHash theKey(inText, inScaleFactor);
+ TTextureInfoHash::iterator theFind(
+ m_TextureCache.find(STextRenderInfoAndHash(inText, inScaleFactor)));
+ STextCacheNode *retval = NULL;
+ if (theFind != m_TextureCache.end()) {
+ retval = theFind->second;
+ m_LRUList.remove(*retval);
+ } else {
+ NVScopedRefCounted<NVRenderTexture2D> nextTexture;
+ if (m_TextureTotalBytes >= m_HighWaterMark && m_LRUList.empty() == false)
+ nextTexture = InvalidateLastItem();
+
+ if (nextTexture.mPtr == NULL)
+ nextTexture = m_RenderContext->CreateTexture2D();
+
+ NVScopedRefCounted<NVRenderPathFontItem> nextPathFontItemObject;
+ NVScopedRefCounted<NVRenderPathFontSpecification> nextPathFontObject;
+ // HW acceleration for fonts not supported
+ //if (m_CanUsePathRendering && inText.m_EnableAcceleratedFont) {
+ // nextPathFontItemObject = m_RenderContext->CreatePathFontItem();
+ // nextPathFontObject = m_RenderContext->CreatePathFontSpecification(inText.m_Font);
+ //}
+
+ STextRenderInfo theTextInfo(inText);
+ theTextInfo.m_FontSize *= inScaleFactor;
+ STextTextureDetails theDetails;
+
+
+ // HW acceleration for fonts not supported
+ //if (!m_CanUsePathRendering || !inText.m_EnableAcceleratedFont)
+ theDetails = m_TextRenderer->RenderText(theTextInfo, *nextTexture.mPtr);
+ //else
+ // theDetails = m_TextRenderer->RenderText(theTextInfo, *nextPathFontItemObject.mPtr,
+ // *nextPathFontObject.mPtr);
+
+ if (fabs(inScaleFactor - 1.0f) > .001f) {
+ TTPathObjectAndTexture theCanonicalDetails = RenderText(inText, 1.0f);
+ theDetails.m_ScaleFactor.x =
+ (QT3DSF32)theDetails.m_TextWidth / theCanonicalDetails.second.first.m_TextWidth;
+ theDetails.m_ScaleFactor.y =
+ (QT3DSF32)theDetails.m_TextHeight / theCanonicalDetails.second.first.m_TextHeight;
+ }
+ theKey = STextRenderInfoAndHash(inText, inScaleFactor);
+ retval = m_CacheNodePool.construct(
+ theKey, TTPathObjectAndTexture(
+ TPathFontSpecAndPathObject(nextPathFontObject, nextPathFontItemObject),
+ TTextTextureDetailsAndTexture(theDetails, nextTexture)),
+ __FILE__, __LINE__);
+ TTextureInfoHash::iterator insert =
+ m_TextureCache.insert(eastl::make_pair(theKey, retval)).first;
+ if (!m_CanUsePathRendering)
+ m_TextureTotalBytes += GetNumBytes(*(retval->m_TextInfo.second.second.mPtr));
+ }
+ retval->m_FrameCount = m_FrameCount;
+ m_LRUList.push_front(*retval);
+ return retval->m_TextInfo;
+ }
+ // We may have one more texture in cache than this byte count, but this will be the limiting
+ // factor.
+ QT3DSU32 GetCacheHighWaterBytes() const override { return m_HighWaterMark; }
+ // default cache size is 10 MB.
+ void SetCacheHighWaterBytes(QT3DSU32 inByteCount) override { m_HighWaterMark = inByteCount; }
+
+ void BeginFrame() override {}
+ void EndFrame() override
+ {
+ // algorithm is resistant to rollover.
+ ++m_FrameCount;
+ // Release any texture that put us over the limit.
+ // This almost guarantees thrashing if the limit is set too low. Enable at your
+ // own risk at *TEST CAREFULLY*
+ /*
+ while( m_TextureTotalBytes >= m_HighWaterMark && m_LRUList.empty() == false )
+ InvalidateLastItem();
+ */
+ }
+};
+}
+
+ITextTextureCache &ITextTextureCache::CreateTextureCache(NVFoundationBase &inFnd,
+ ITextRenderer &inTextRenderer,
+ NVRenderContext &inRenderContext)
+{
+ return *QT3DS_NEW(inFnd.getAllocator(), STextTextureCache)(inFnd, inTextRenderer, inRenderContext);
+}