diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2016-04-08 17:08:04 +0900 |
---|---|---|
committer | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2016-04-08 19:10:14 +0900 |
commit | cd089979607566bc26259ff9edb079842aabdd4e (patch) | |
tree | be8955067072c88769b865cc1b4441e81aee4c03 /vcl/opengl | |
parent | f65e77c965bb47d53c994d90b7fd0bf5009b343b (diff) |
opengl: refactor GL texture slot mechanism to be more general
Slot mechanism in ImplOpenGLTexture was written to support needs
for FixedTextureAtlas. This commit makes the slot mechanism more
general so it can be used in other kinds of texture atlases like
PackedTextureAtlas.
The ImplOpenGLTexture still tracks slots, but it is not needed to
define beforehand how many slots there are. The deallocation has
been factored out, ImplOpenGLTexture instead calls a callback
function that a slot with a specific "slot id" has been
deallocated.
Change-Id: I23950d325b803969f958d03ebf34805687c4e620
Diffstat (limited to 'vcl/opengl')
-rw-r--r-- | vcl/opengl/FixedTextureAtlas.cxx | 76 | ||||
-rw-r--r-- | vcl/opengl/texture.cxx | 47 |
2 files changed, 79 insertions, 44 deletions
diff --git a/vcl/opengl/FixedTextureAtlas.cxx b/vcl/opengl/FixedTextureAtlas.cxx index 1ed83111d293..87c5bb1ff2ac 100644 --- a/vcl/opengl/FixedTextureAtlas.cxx +++ b/vcl/opengl/FixedTextureAtlas.cxx @@ -17,6 +17,52 @@ #include "opengl/FixedTextureAtlas.hxx" +struct FixedTexture +{ + ImplOpenGLTexture* mpTexture; + int mnFreeSlots; + std::vector<bool> maAllocatedSlots; + + FixedTexture(ImplOpenGLTexture* pTexture, int nNumberOfSlots) + : mpTexture(pTexture) + , mnFreeSlots(nNumberOfSlots) + , maAllocatedSlots(nNumberOfSlots, false) + { + auto aDeallocateFunction = [this] (int nSlotNumber) + { + deallocateSlot(nSlotNumber); + }; + + mpTexture->SetSlotDeallocateCallback(aDeallocateFunction); + mpTexture->InitializeSlotMechanism(nNumberOfSlots); + } + + void allocateSlot(int nSlot) + { + maAllocatedSlots[nSlot] = true; + mnFreeSlots--; + } + + void deallocateSlot(int nSlot) + { + maAllocatedSlots[nSlot] = false; + mnFreeSlots++; + } + + int findAndAllocateFreeSlot() + { + for (size_t i = 0; i < maAllocatedSlots.size(); ++i) + { + if (!maAllocatedSlots[i]) + { + allocateSlot(i); + return i; + } + } + return -1; + } +}; + FixedTextureAtlasManager::FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nSubTextureSize) : mWidthFactor(nWidthFactor) , mHeightFactor(nHeightFactor) @@ -26,11 +72,10 @@ FixedTextureAtlasManager::FixedTextureAtlasManager(int nWidthFactor, int nHeight FixedTextureAtlasManager::~FixedTextureAtlasManager() { - for (auto i = mpTextures.begin(); i != mpTextures.end(); ++i) + for (std::unique_ptr<FixedTexture>& pFixedTexture : maFixedTextures) { // Free texture early in VCL shutdown while we have a context. - (*i)->Dispose(); - (*i)->DecreaseRefCount(0); + delete pFixedTexture->mpTexture; } } @@ -38,32 +83,35 @@ void FixedTextureAtlasManager::CreateNewTexture() { int nTextureWidth = mWidthFactor * mSubTextureSize; int nTextureHeight = mHeightFactor * mSubTextureSize; - mpTextures.push_back(new ImplOpenGLTexture(nTextureWidth, nTextureHeight, true)); - mpTextures.back()->InitializeSlots(mWidthFactor * mHeightFactor); + std::unique_ptr<FixedTexture> pFixedTexture( + new FixedTexture(new ImplOpenGLTexture(nTextureWidth, nTextureHeight, true), + mWidthFactor * mHeightFactor)); + + maFixedTextures.push_back(std::move(pFixedTexture)); } OpenGLTexture FixedTextureAtlasManager::Reserve(int nWidth, int nHeight) { - ImplOpenGLTexture* pTexture = nullptr; + FixedTexture* pFixedTexture = nullptr; - auto funFreeSlot = [] (ImplOpenGLTexture *mpTexture) + auto funFreeSlot = [] (std::unique_ptr<FixedTexture>& inFixedTexture) { - return mpTexture->mnFreeSlots > 0; + return inFixedTexture->mnFreeSlots > 0; }; - auto it = std::find_if(mpTextures.begin(), mpTextures.end(), funFreeSlot); + auto it = std::find_if(maFixedTextures.begin(), maFixedTextures.end(), funFreeSlot); - if (it != mpTextures.end()) + if (it != maFixedTextures.end()) { - pTexture = *it; + pFixedTexture = (*it).get(); } else { CreateNewTexture(); - pTexture = mpTextures.back(); + pFixedTexture = maFixedTextures.back().get(); } - int nSlot = pTexture->FindFreeSlot(); + int nSlot = pFixedTexture->findAndAllocateFreeSlot(); // Calculate coordinates in texture int nX = (nSlot % mWidthFactor) * mSubTextureSize; @@ -71,7 +119,7 @@ OpenGLTexture FixedTextureAtlasManager::Reserve(int nWidth, int nHeight) Rectangle aRectangle(Point(nX, nY), Size(nWidth, nHeight)); - return OpenGLTexture(pTexture, aRectangle, nSlot); + return OpenGLTexture(pFixedTexture->mpTexture, aRectangle, nSlot); } OpenGLTexture FixedTextureAtlasManager::InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData) diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx index 6388a92809cf..b3a36263271b 100644 --- a/vcl/opengl/texture.cxx +++ b/vcl/opengl/texture.cxx @@ -43,8 +43,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ) mnWidth( nWidth ), mnHeight( nHeight ), mnFilter( GL_NEAREST ), - mnOptStencil( 0 ), - mnFreeSlots(-1) + mnOptStencil( 0 ) { OpenGLVCLContextZone aContextZone; @@ -78,8 +77,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight ) mnWidth( nWidth ), mnHeight( nHeight ), mnFilter( GL_NEAREST ), - mnOptStencil( 0 ), - mnFreeSlots(-1) + mnOptStencil( 0 ) { OpenGLVCLContextZone aContextZone; @@ -113,8 +111,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int mnWidth( nWidth ), mnHeight( nHeight ), mnFilter( GL_NEAREST ), - mnOptStencil( 0 ), - mnFreeSlots(-1) + mnOptStencil( 0 ) { OpenGLVCLContextZone aContextZone; @@ -221,53 +218,43 @@ bool ImplOpenGLTexture::InsertBuffer(int nX, int nY, int nWidth, int nHeight, in return true; } -bool ImplOpenGLTexture::InitializeSlots(int nSlotSize) +bool ImplOpenGLTexture::InitializeSlotMechanism(int nInitialSlotSize) { if (mpSlotReferences) return false; - mpSlotReferences.reset(new std::vector<int>(nSlotSize, 0)); - mnFreeSlots = nSlotSize; - + mpSlotReferences.reset(new std::vector<int>(nInitialSlotSize, 0)); return true; } -int ImplOpenGLTexture::FindFreeSlot() -{ - if (mnFreeSlots > 0 && mpSlotReferences) - { - for (size_t i = 0; i < mpSlotReferences->size(); i++) - { - if (mpSlotReferences->at(i) <= 0) - { - return i; - } - } - } - return -1; -} - void ImplOpenGLTexture::IncreaseRefCount(int nSlotNumber) { mnRefCount++; if (mpSlotReferences && nSlotNumber >= 0) { - if (mpSlotReferences->at(nSlotNumber) == 0) - mnFreeSlots--; + if (nSlotNumber >= int(mpSlotReferences->size())) + mpSlotReferences->resize(nSlotNumber + 1, 0); + mpSlotReferences->at(nSlotNumber)++; } } void ImplOpenGLTexture::DecreaseRefCount(int nSlotNumber) { - mnRefCount--; if (mpSlotReferences && nSlotNumber >= 0) { + if (nSlotNumber >= int(mpSlotReferences->size())) + mpSlotReferences->resize(nSlotNumber, 0); + mpSlotReferences->at(nSlotNumber)--; - if (mpSlotReferences->at(nSlotNumber) == 0) - mnFreeSlots++; + + if (mpSlotReferences->at(nSlotNumber) == 0 && mFunctSlotDeallocateCallback) + { + mFunctSlotDeallocateCallback(nSlotNumber); + } } + mnRefCount--; if (mnRefCount <= 0) delete this; } |