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/.
12 #include <sal/config.h>
13 #include <vcl/opengl/OpenGLContext.hxx>
14 #include <vcl/opengl/OpenGLHelper.hxx>
16 #include "opengl/framebuffer.hxx"
17 #include "opengl/texture.hxx"
19 #include "opengl/PackedTextureAtlas.hxx"
23 tools::Rectangle mRectangle
;
24 std::unique_ptr
<Node
> mLeftNode
;
25 std::unique_ptr
<Node
> mRightNode
;
28 explicit Node(int nWidth
, int nHeight
);
29 explicit Node(tools::Rectangle
& aRectangle
);
32 Node
* insert(int nWidth
, int nHeight
, int nPadding
);
35 Node::Node(int nWidth
, int nHeight
)
36 : mRectangle(tools::Rectangle(Point(), Size(nWidth
, nHeight
)))
42 Node::Node(tools::Rectangle
& aRectangle
)
43 : mRectangle(aRectangle
)
51 return mLeftNode
.get() == nullptr &&
52 mRightNode
.get() == nullptr;
55 Node
* Node::insert(int nWidth
, int nHeight
, int nPadding
)
59 Node
* pNewNode
= mLeftNode
->insert(nWidth
, nHeight
, nPadding
);
61 if (pNewNode
!= nullptr)
64 return mRightNode
->insert(nWidth
, nHeight
, nPadding
);
73 if (nWidth
> mRectangle
.GetWidth() || nHeight
> mRectangle
.GetHeight())
78 if (nWidth
== mRectangle
.GetWidth() && nHeight
== mRectangle
.GetHeight())
84 int dw
= mRectangle
.GetWidth() - nWidth
;
85 int dh
= mRectangle
.GetHeight() - nHeight
;
87 tools::Rectangle aLeftRect
;
88 tools::Rectangle aRightRect
;
91 aLeftRect
= tools::Rectangle(Point(mRectangle
.Left(), mRectangle
.Top()),
92 Size(nWidth
, mRectangle
.GetHeight()));
93 aRightRect
= tools::Rectangle(Point(nPadding
+ mRectangle
.Left() + nWidth
, mRectangle
.Top()),
94 Size(mRectangle
.GetWidth() - nWidth
- nPadding
, mRectangle
.GetHeight()));
98 aLeftRect
= tools::Rectangle(Point(mRectangle
.Left(), mRectangle
.Top()),
99 Size(mRectangle
.GetWidth(), nHeight
));
100 aRightRect
= tools::Rectangle(Point(mRectangle
.Left(), nPadding
+ mRectangle
.Top() + nHeight
),
101 Size(mRectangle
.GetWidth(), mRectangle
.GetHeight() - nHeight
- nPadding
));
104 mLeftNode
.reset(new Node(aLeftRect
));
105 mRightNode
.reset(new Node(aRightRect
));
107 return mLeftNode
->insert(nWidth
, nHeight
, nPadding
);
113 std::shared_ptr
<ImplOpenGLTexture
> mpTexture
;
114 std::unique_ptr
<Node
> mpRootNode
;
116 PackedTexture(int nWidth
, int nHeight
)
117 : mpTexture(new ImplOpenGLTexture(nWidth
, nHeight
, true))
118 , mpRootNode(new Node(nWidth
, nHeight
))
122 PackedTextureAtlasManager::PackedTextureAtlasManager(int nTextureWidth
, int nTextureHeight
)
123 : mnTextureWidth(nTextureWidth
)
124 , mnTextureHeight(nTextureHeight
)
128 PackedTextureAtlasManager::~PackedTextureAtlasManager()
130 for (std::unique_ptr
<PackedTexture
>& pPackedTexture
: maPackedTextures
)
132 // Free texture early in VCL shutdown while we have a context.
133 pPackedTexture
->mpTexture
.reset();
137 void PackedTextureAtlasManager::CreateNewTexture()
139 std::unique_ptr
<PackedTexture
> pPackedTexture(new PackedTexture(mnTextureWidth
, mnTextureHeight
));
140 GLuint nTextureID
= pPackedTexture
->mpTexture
->mnTexture
;
141 maPackedTextures
.push_back(std::move(pPackedTexture
));
142 VCL_GL_INFO("PackedTextureAtlas::CreateNewTexture adding texture: " << nTextureID
<<
143 " atlases: " << maPackedTextures
.size());
146 OpenGLTexture
PackedTextureAtlasManager::Reserve(int nWidth
, int nHeight
)
148 for (std::unique_ptr
<PackedTexture
>& pPackedTexture
: maPackedTextures
)
150 Node
* pNode
= pPackedTexture
->mpRootNode
->insert(nWidth
, nHeight
, 1);
151 if (pNode
!= nullptr)
153 return OpenGLTexture(pPackedTexture
->mpTexture
, pNode
->mRectangle
, -1);
157 std::unique_ptr
<PackedTexture
>& pPackedTexture
= maPackedTextures
.back();
158 Node
* pNode
= pPackedTexture
->mpRootNode
->insert(nWidth
, nHeight
, 1);
159 if (pNode
!= nullptr)
161 return OpenGLTexture(pPackedTexture
->mpTexture
, pNode
->mRectangle
, -1);
163 return OpenGLTexture();
166 OpenGLTexture
PackedTextureAtlasManager::InsertBuffer(int nWidth
, int nHeight
, int nFormat
, int nType
, sal_uInt8
* pData
)
168 OpenGLTexture aTexture
= Reserve(nWidth
, nHeight
);
169 if (aTexture
&& pData
== nullptr)
172 aTexture
.CopyData(nWidth
, nHeight
, nFormat
, nType
, pData
);
177 std::vector
<GLuint
> PackedTextureAtlasManager::ReduceTextureNumber(int nMaxNumberOfTextures
)
179 std::vector
<GLuint
> aTextureIDs
;
180 while (int(maPackedTextures
.size()) > nMaxNumberOfTextures
)
182 // Remove oldest created texture
183 GLuint nTextureID
= maPackedTextures
[0]->mpTexture
->mnTexture
;
184 aTextureIDs
.push_back(nTextureID
);
185 maPackedTextures
.erase(maPackedTextures
.begin());
186 VCL_GL_INFO("PackedTextureAtlas::ReduceTextureNumber removing texture: " << nTextureID
<<
187 " atlases: " << maPackedTextures
.size());
192 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */