summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2015-08-19 11:51:15 +0900
committerTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2015-08-24 19:08:10 +0900
commitb26ba85d04e81f48622dfdbb71d9d80b54dacc40 (patch)
treea349a4e646dbe809fdfbf468b94188052b1bcedc /vcl
parent652e3d2dbdd2d6f43953da3ae37cfc98d350328d (diff)
Fixed (fixed size) texture atlas for "caching" OpenGL texures
Change-Id: I7fe90c0a0033b4d9a341a4f0b8356d7f7133e93e
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/inc/opengl/FixedTextureAtlas.hxx39
-rw-r--r--vcl/inc/opengl/texture.hxx43
-rw-r--r--vcl/opengl/FixedTextureAtlas.cxx71
-rw-r--r--vcl/opengl/texture.cxx100
5 files changed, 233 insertions, 21 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 2e6f8b02b40b..306178c4e794 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -132,6 +132,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/opengl/framebuffer \
vcl/opengl/program \
vcl/opengl/texture \
+ vcl/opengl/FixedTextureAtlas \
vcl/source/opengl/OpenGLContext \
vcl/source/opengl/OpenGLHelper \
vcl/source/window/cairo_cairo \
diff --git a/vcl/inc/opengl/FixedTextureAtlas.hxx b/vcl/inc/opengl/FixedTextureAtlas.hxx
new file mode 100644
index 000000000000..c4f5d6065696
--- /dev/null
+++ b/vcl/inc/opengl/FixedTextureAtlas.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_INC_OPENGL_FIXED_TEXTURE_ATLAS_H
+#define INCLUDED_VCL_INC_OPENGL_FIXED_TEXTURE_ATLAS_H
+
+#include "opengl/texture.hxx"
+
+
+class VCL_PLUGIN_PUBLIC FixedTextureAtlasManager
+{
+ std::vector<std::unique_ptr<ImplOpenGLTexture>> mpTextures;
+
+ int mWidthFactor;
+ int mHeightFactor;
+ int mSubTextureSize;
+
+ void CreateNewTexture();
+
+public:
+ FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nTextureSize);
+ OpenGLTexture InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
+
+ int GetSubtextureSize()
+ {
+ return mSubTextureSize;
+ }
+};
+
+#endif // INCLUDED_VCL_INC_OPENGL_FIXED_TEXTURE_ATLAS_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index b68397641326..51f7040ab9ef 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -26,6 +26,8 @@
#include <rtl/ustring.hxx>
#include <tools/gen.hxx>
+#include <memory>
+
class ImplOpenGLTexture
{
public:
@@ -35,10 +37,45 @@ public:
int mnHeight;
GLenum mnFilter;
+ std::unique_ptr<std::vector<int>> mpSlotReferences;
+ int mnFreeSlots;
+
ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate );
ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight );
~ImplOpenGLTexture();
+
+ bool InsertBuffer(int nX, int nY, int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
+
+ void IncreaseRefCount(int nSlotNumber)
+ {
+ mnRefCount++;
+ if (mpSlotReferences && nSlotNumber >= 0)
+ {
+ if (mpSlotReferences->at(nSlotNumber) == 0)
+ mnFreeSlots--;
+ mpSlotReferences->at(nSlotNumber)++;
+ }
+ }
+
+ void DecreaseRefCount(int nSlotNumber)
+ {
+ mnRefCount--;
+ if (mpSlotReferences && nSlotNumber >= 0)
+ {
+ mpSlotReferences->at(nSlotNumber)--;
+ if (mpSlotReferences->at(nSlotNumber) == 0)
+ mnFreeSlots++;
+ }
+ }
+
+ bool ExistRefs()
+ {
+ return mnRefCount > 0;
+ }
+
+ bool InitializeSlots(int nSlotSize);
+ int FindFreeSlot();
};
class VCL_PLUGIN_PUBLIC OpenGLTexture
@@ -46,12 +83,14 @@ class VCL_PLUGIN_PUBLIC OpenGLTexture
private:
// if the rect size doesn't match the mpImpl one, this instance
// is a sub-area from the real OpenGL texture
- Rectangle maRect;
-
+ Rectangle maRect;
ImplOpenGLTexture* mpImpl;
+ int mnSlotNumber;
public:
OpenGLTexture();
+ OpenGLTexture(ImplOpenGLTexture* pImpl, Rectangle aRectangle, int nSlotNumber = 0);
+
OpenGLTexture( int nWidth, int nHeight, bool bAllocate = true );
OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
OpenGLTexture( int nX, int nY, int nWidth, int nHeight );
diff --git a/vcl/opengl/FixedTextureAtlas.cxx b/vcl/opengl/FixedTextureAtlas.cxx
new file mode 100644
index 000000000000..c8ca50846b9d
--- /dev/null
+++ b/vcl/opengl/FixedTextureAtlas.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sal/config.h>
+#include <vcl/opengl/OpenGLContext.hxx>
+#include <vcl/opengl/OpenGLHelper.hxx>
+
+#include "opengl/framebuffer.hxx"
+#include "opengl/texture.hxx"
+
+#include "opengl/FixedTextureAtlas.hxx"
+
+FixedTextureAtlasManager::FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nSubTextureSize)
+ : mWidthFactor(nWidthFactor)
+ , mHeightFactor(nHeightFactor)
+ , mSubTextureSize(nSubTextureSize)
+{
+}
+
+void FixedTextureAtlasManager::CreateNewTexture()
+{
+ int nTextureWidth = mWidthFactor * mSubTextureSize;
+ int nTextureHeight = mHeightFactor * mSubTextureSize;
+ mpTextures.push_back(std::move(std::unique_ptr<ImplOpenGLTexture>(new ImplOpenGLTexture(nTextureWidth, nTextureHeight, true))));
+ mpTextures.back()->InitializeSlots(mWidthFactor * mHeightFactor);
+}
+
+OpenGLTexture FixedTextureAtlasManager::InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData)
+{
+ ImplOpenGLTexture* pTexture = nullptr;
+
+ for (size_t i = 0; i < mpTextures.size(); i++)
+ {
+ if (mpTextures[i]->mnFreeSlots > 0)
+ {
+ pTexture = mpTextures[i].get();
+ }
+ }
+
+ if (!pTexture)
+ {
+ CreateNewTexture();
+ pTexture = mpTextures.back().get();
+ }
+
+ int nSlot = pTexture->FindFreeSlot();
+
+ // Calculate coordinates in texture
+ int nX = (nSlot % mWidthFactor) * mSubTextureSize;
+ int nY = (nSlot / mWidthFactor) * mSubTextureSize;
+
+ Rectangle aRectangle(Point(nX, nY), Size(nWidth, nHeight));
+
+ // If available, copy the image data to the texture
+ if (pData)
+ {
+ if (!pTexture->InsertBuffer(nX, nY, nWidth, nHeight, nFormat, nType, pData))
+ return OpenGLTexture();
+ }
+
+ return OpenGLTexture(pTexture, aRectangle, nSlot);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index a527ceb98dd3..cbb8b076f38a 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -34,7 +34,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
mnRefCount( 1 ),
mnWidth( nWidth ),
mnHeight( nHeight ),
- mnFilter( GL_NEAREST )
+ mnFilter( GL_NEAREST ),
+ mnFreeSlots(-1)
{
glGenTextures( 1, &mnTexture );
glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -57,7 +58,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
mnTexture( 0 ),
mnWidth( nWidth ),
mnHeight( nHeight ),
- mnFilter( GL_NEAREST )
+ mnFilter( GL_NEAREST ),
+ mnFreeSlots(-1)
{
// FIXME We need the window height here
// nY = GetHeight() - nHeight - nY;
@@ -83,7 +85,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
mnTexture( 0 ),
mnWidth( nWidth ),
mnHeight( nHeight ),
- mnFilter( GL_NEAREST )
+ mnFilter( GL_NEAREST ),
+ mnFreeSlots(-1)
{
if( !mnTexture )
glGenTextures( 1, &mnTexture );
@@ -108,12 +111,64 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
glDeleteTextures( 1, &mnTexture );
}
+bool ImplOpenGLTexture::InsertBuffer(int nX, int nY, int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData)
+{
+ if (!pData || mnTexture == 0)
+ return false;
+ glBindTexture(GL_TEXTURE_2D, mnTexture);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, nX, mnHeight - nY - nHeight, nWidth, nHeight, nFormat, nType, pData);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ SAL_INFO( "vcl.opengl", "OpenGLTexture " << mnTexture << " Insert buff. to " << nX << " " << nY
+ << " size " << nWidth << "x" << nHeight << " from data" );
+ CHECK_GL_ERROR();
+
+ return true;
+}
+
+bool ImplOpenGLTexture::InitializeSlots(int nSlotSize)
+{
+ if (mpSlotReferences)
+ return false;
+
+ mpSlotReferences.reset(new std::vector<int>(nSlotSize, 0));
+ mnFreeSlots = nSlotSize;
+
+ 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;
+}
+
OpenGLTexture::OpenGLTexture() :
maRect( 0, 0, 0, 0 ),
- mpImpl( NULL )
+ mpImpl(NULL),
+ mnSlotNumber(-1)
{
}
+OpenGLTexture::OpenGLTexture(ImplOpenGLTexture* pImpl, Rectangle aRectangle, int nSlotNumber)
+ : maRect(aRectangle)
+ , mpImpl(pImpl)
+ , mnSlotNumber(nSlotNumber)
+{
+ if (mpImpl)
+ mpImpl->IncreaseRefCount(nSlotNumber);
+}
+
OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
{
@@ -136,8 +191,10 @@ OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture )
{
maRect = rTexture.maRect;
mpImpl = rTexture.mpImpl;
- if( mpImpl )
- mpImpl->mnRefCount++;
+ mnSlotNumber = rTexture.mnSlotNumber;
+
+ if (mpImpl)
+ mpImpl->IncreaseRefCount(mnSlotNumber);
}
OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
@@ -146,19 +203,19 @@ OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
maRect = Rectangle( Point( rTexture.maRect.Left() + nX, rTexture.maRect.Top() + nY ),
Size( nWidth, nHeight ) );
mpImpl = rTexture.mpImpl;
- if( mpImpl )
- mpImpl->mnRefCount++;
+ mnSlotNumber = rTexture.mnSlotNumber;
+ if (mpImpl)
+ mpImpl->IncreaseRefCount(mnSlotNumber);
SAL_INFO( "vcl.opengl", "Copying texture " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
}
OpenGLTexture::~OpenGLTexture()
{
- if( mpImpl )
+ if (mpImpl)
{
- if( mpImpl->mnRefCount == 1 )
+ mpImpl->DecreaseRefCount(mnSlotNumber);
+ if (!mpImpl->ExistRefs())
delete mpImpl;
- else
- mpImpl->mnRefCount--;
}
}
@@ -325,25 +382,30 @@ OpenGLTexture::operator bool() const
OpenGLTexture& OpenGLTexture::operator=( const OpenGLTexture& rTexture )
{
- if( rTexture.mpImpl )
- rTexture.mpImpl->mnRefCount++;
- if( mpImpl )
+ if (rTexture.mpImpl)
+ {
+ rTexture.mpImpl->IncreaseRefCount(rTexture.mnSlotNumber);
+ }
+
+ if (mpImpl)
{
- if( mpImpl->mnRefCount == 1 )
+ mpImpl->DecreaseRefCount(mnSlotNumber);
+ if (!mpImpl->ExistRefs())
delete mpImpl;
- else
- mpImpl->mnRefCount--;
}
maRect = rTexture.maRect;
mpImpl = rTexture.mpImpl;
+ mnSlotNumber = rTexture.mnSlotNumber;
return *this;
}
bool OpenGLTexture::operator==( const OpenGLTexture& rTexture ) const
{
- return (mpImpl == rTexture.mpImpl && maRect == rTexture.maRect );
+ return (mpImpl == rTexture.mpImpl
+ && maRect == rTexture.maRect
+ && mnSlotNumber == rTexture.mnSlotNumber);
}
bool OpenGLTexture::operator!=( const OpenGLTexture& rTexture ) const