Kaydet (Commit) b26ba85d authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl

Fixed (fixed size) texture atlas for "caching" OpenGL texures

Change-Id: I7fe90c0a0033b4d9a341a4f0b8356d7f7133e93e
üst 652e3d2d
......@@ -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 \
......
/* -*- 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: */
......@@ -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 );
......
/* -*- 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: */
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment