1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <sal/config.h>
12 #include <vcl/opengl/OpenGLContext.hxx>
13 #include <vcl/opengl/OpenGLHelper.hxx>
15 #include "opengl/framebuffer.hxx"
16 #include "opengl/texture.hxx"
18 #include "opengl/PackedTextureAtlas.hxx"
23 std::unique_ptr
<Node
> mLeftNode
;
24 std::unique_ptr
<Node
> mRightNode
;
27 explicit Node(int nWidth
, int nHeight
);
28 explicit Node(Rectangle
& aRectangle
);
31 Node
* insert(int nWidth
, int nHeight
, int nPadding
);
34 Node::Node(int nWidth
, int nHeight
)
35 : mRectangle(Rectangle(Point(), Size(nWidth
, nHeight
)))
41 Node::Node(Rectangle
& aRectangle
)
42 : mRectangle(aRectangle
)
50 return mLeftNode
.get() == nullptr &&
51 mRightNode
.get() == nullptr;
54 Node
* Node::insert(int nWidth
, int nHeight
, int nPadding
)
58 Node
* pNewNode
= mLeftNode
->insert(nWidth
, nHeight
, nPadding
);
60 if (pNewNode
!= nullptr)
63 return mRightNode
->insert(nWidth
, nHeight
, nPadding
);
72 if (nWidth
> mRectangle
.GetWidth() || nHeight
> mRectangle
.GetHeight())
77 if (nWidth
== mRectangle
.GetWidth() && nHeight
== mRectangle
.GetHeight())
83 int dw
= mRectangle
.GetWidth() - nWidth
;
84 int dh
= mRectangle
.GetHeight() - nHeight
;
90 aLeftRect
= Rectangle(Point(mRectangle
.Left(), mRectangle
.Top()),
91 Size(nWidth
, mRectangle
.GetHeight()));
92 aRightRect
= Rectangle(Point(nPadding
+ mRectangle
.Left() + nWidth
, mRectangle
.Top()),
93 Size(mRectangle
.GetWidth() - nWidth
- nPadding
, mRectangle
.GetHeight()));
97 aLeftRect
= Rectangle(Point(mRectangle
.Left(), mRectangle
.Top()),
98 Size(mRectangle
.GetWidth(), nHeight
));
99 aRightRect
= Rectangle(Point(mRectangle
.Left(), nPadding
+ mRectangle
.Top() + nHeight
),
100 Size(mRectangle
.GetWidth(), mRectangle
.GetHeight() - nHeight
- nPadding
));
103 mLeftNode
.reset(new Node(aLeftRect
));
104 mRightNode
.reset(new Node(aRightRect
));
106 return mLeftNode
->insert(nWidth
, nHeight
, nPadding
);
112 std::unique_ptr
<ImplOpenGLTexture
> mpTexture
;
113 std::unique_ptr
<Node
> mpRootNode
;
114 int mnDeallocatedArea
;
116 PackedTexture(int nWidth
, int nHeight
)
117 : mpTexture(new ImplOpenGLTexture(nWidth
, nHeight
, true))
118 , mpRootNode(new Node(nWidth
, nHeight
))
119 , mnDeallocatedArea(0)
123 PackedTextureAtlasManager::PackedTextureAtlasManager(int nTextureWidth
, int nTextureHeight
)
124 : mnTextureWidth(nTextureWidth
)
125 , mnTextureHeight(nTextureHeight
)
129 PackedTextureAtlasManager::~PackedTextureAtlasManager()
131 for (std::unique_ptr
<PackedTexture
>& pPackedTexture
: maPackedTextures
)
133 // Free texture early in VCL shutdown while we have a context.
134 pPackedTexture
->mpTexture
.reset();
138 void PackedTextureAtlasManager::CreateNewTexture()
140 std::unique_ptr
<PackedTexture
> pPackedTexture(new PackedTexture(mnTextureWidth
, mnTextureHeight
));
141 GLuint nTextureID
= pPackedTexture
->mpTexture
->mnTexture
;
142 maPackedTextures
.push_back(std::move(pPackedTexture
));
143 VCL_GL_INFO("PackedTextureAtlas::CreateNewTexture adding texture: " << nTextureID
<<
144 " atlases: " << maPackedTextures
.size());
147 OpenGLTexture
PackedTextureAtlasManager::Reserve(int nWidth
, int nHeight
)
149 for (std::unique_ptr
<PackedTexture
>& pPackedTexture
: maPackedTextures
)
151 Node
* pNode
= pPackedTexture
->mpRootNode
->insert(nWidth
, nHeight
, 1);
152 if (pNode
!= nullptr)
154 return OpenGLTexture(pPackedTexture
->mpTexture
.get(), pNode
->mRectangle
, -1);
158 std::unique_ptr
<PackedTexture
>& pPackedTexture
= maPackedTextures
.back();
159 Node
* pNode
= pPackedTexture
->mpRootNode
->insert(nWidth
, nHeight
, 1);
160 if (pNode
!= nullptr)
162 return OpenGLTexture(pPackedTexture
->mpTexture
.get(), pNode
->mRectangle
, -1);
164 return OpenGLTexture();
167 OpenGLTexture
PackedTextureAtlasManager::InsertBuffer(int nWidth
, int nHeight
, int nFormat
, int nType
, sal_uInt8
* pData
)
169 OpenGLTexture aTexture
= Reserve(nWidth
, nHeight
);
170 if (aTexture
&& pData
== nullptr)
173 aTexture
.CopyData(nWidth
, nHeight
, nFormat
, nType
, pData
);
178 std::vector
<GLuint
> PackedTextureAtlasManager::ReduceTextureNumber(int nMaxNumberOfTextures
)
180 std::vector
<GLuint
> aTextureIDs
;
181 while (int(maPackedTextures
.size()) > nMaxNumberOfTextures
)
183 // Remove oldest created texture
184 GLuint nTextureID
= maPackedTextures
[0]->mpTexture
->mnTexture
;
185 aTextureIDs
.push_back(nTextureID
);
186 maPackedTextures
.erase(maPackedTextures
.begin());
187 VCL_GL_INFO("PackedTextureAtlas::ReduceTextureNumber removing texture: " << nTextureID
<<
188 " atlases: " << maPackedTextures
.size());
193 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */