Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
bbc0e8eb
Commit
bbc0e8eb
authored
Jul 17, 2013
by
Maciej Suminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactorization of VBO_CONTAINER.
parent
99e88140
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
288 additions
and
293 deletions
+288
-293
vbo_container.cpp
common/gal/opengl/vbo_container.cpp
+193
-194
vbo_item.cpp
common/gal/opengl/vbo_item.cpp
+1
-2
vbo_container.h
include/gal/opengl/vbo_container.h
+71
-86
vbo_item.h
include/gal/opengl/vbo_item.h
+23
-11
No files found.
common/gal/opengl/vbo_container.cpp
View file @
bbc0e8eb
...
@@ -28,9 +28,8 @@
...
@@ -28,9 +28,8 @@
*/
*/
#include <gal/opengl/vbo_container.h>
#include <gal/opengl/vbo_container.h>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <list>
#include <boost/foreach.hpp>
#include <wx/log.h>
#include <wx/log.h>
#ifdef __WXDEBUG__
#ifdef __WXDEBUG__
#include <profile.h>
#include <profile.h>
...
@@ -39,7 +38,7 @@
...
@@ -39,7 +38,7 @@
using
namespace
KiGfx
;
using
namespace
KiGfx
;
VBO_CONTAINER
::
VBO_CONTAINER
(
unsigned
int
aSize
)
:
VBO_CONTAINER
::
VBO_CONTAINER
(
unsigned
int
aSize
)
:
m_freeSpace
(
aSize
),
m_currentSize
(
aSize
),
itemStarted
(
fals
e
),
m_transform
(
NULL
),
m_freeSpace
(
aSize
),
m_currentSize
(
aSize
),
m_initialSize
(
aSiz
e
),
m_transform
(
NULL
),
m_failed
(
false
)
m_failed
(
false
)
{
{
// By default no shader is used
// By default no shader is used
...
@@ -58,114 +57,42 @@ VBO_CONTAINER::~VBO_CONTAINER()
...
@@ -58,114 +57,42 @@ VBO_CONTAINER::~VBO_CONTAINER()
}
}
void
VBO_CONTAINER
::
StartItem
(
VBO_ITEM
*
a
Vbo
Item
)
void
VBO_CONTAINER
::
StartItem
(
VBO_ITEM
*
aItem
)
{
{
itemStarted
=
true
;
m_item
=
aItem
;
item
=
aVboItem
;
m_itemSize
=
aItem
->
GetSize
()
;
itemSize
=
0
;
m_chunkSize
=
m_itemSize
;
// Reserve minimal sensible chunk size (at least to store a single triangle)
if
(
m_itemSize
==
0
)
itemChunkSize
=
3
;
m_items
.
insert
(
m_item
);
// The item was not stored before
allocate
(
aVboItem
,
itemChunkSize
);
else
m_chunkOffset
=
m_item
->
GetOffset
();
}
}
void
VBO_CONTAINER
::
EndItem
()
void
VBO_CONTAINER
::
EndItem
()
{
{
if
(
itemSize
<
itemC
hunkSize
)
if
(
m_itemSize
<
m_c
hunkSize
)
{
{
// There is some memory left, so we should return it to the pool
// Add the not used memory back to the pool
int
itemChunkOffset
=
item
->
GetOffset
();
m_freeChunks
.
insert
(
Chunk
(
m_chunkSize
-
m_itemSize
,
m_chunkOffset
+
m_itemSize
)
);
m_freeSpace
+=
(
m_chunkSize
-
m_itemSize
);
m_reservedChunks
.
erase
(
item
);
m_reservedChunks
.
insert
(
ReservedChunk
(
item
,
Chunk
(
itemSize
,
itemChunkOffset
)
)
);
m_freeChunks
.
insert
(
Chunk
(
itemChunkSize
-
itemSize
,
itemChunkOffset
+
itemSize
)
);
m_freeSpace
+=
(
itemChunkSize
-
itemSize
);
}
}
item
=
NULL
;
m_item
=
NULL
;
itemStarted
=
false
;
}
}
void
VBO_CONTAINER
::
Add
(
VBO_ITEM
*
aVboItem
,
const
VBO_VERTEX
*
aVertex
,
unsigned
int
aSize
)
void
VBO_CONTAINER
::
Add
(
const
VBO_VERTEX
*
aVertex
,
unsigned
int
aSize
)
{
{
unsigned
int
offset
;
// Pointer to the vertex that we are currently adding
VBO_VERTEX
*
vertexPtr
;
VBO_VERTEX
*
vertexPtr
=
allocate
(
aSize
)
;
if
(
m_failed
)
if
(
vertexPtr
==
NULL
)
return
;
return
;
if
(
itemStarted
)
// There is an item being created with an unknown size..
{
unsigned
int
itemChunkOffset
;
// ..and unfortunately does not fit into currently reserved chunk
if
(
itemSize
+
aSize
>
itemChunkSize
)
{
// Find the previous chunk for the item and change mark it as NULL
// so it will not be removed during a possible defragmentation
ReservedChunkMap
::
iterator
it
=
m_reservedChunks
.
find
(
item
);
m_reservedChunks
.
insert
(
ReservedChunk
(
static_cast
<
VBO_ITEM
*>
(
NULL
),
it
->
second
)
);
m_reservedChunks
.
erase
(
it
);
// Reserve bigger memory fo r the current item
int
newSize
=
(
2
*
itemSize
)
+
aSize
;
itemChunkOffset
=
allocate
(
aVboItem
,
newSize
);
aVboItem
->
SetOffset
(
itemChunkOffset
);
// Check if there was no error
if
(
itemChunkOffset
>
m_currentSize
)
{
m_failed
=
true
;
return
;
}
it
=
m_reservedChunks
.
find
(
static_cast
<
VBO_ITEM
*>
(
NULL
)
);
// Check if the chunk was not reallocated after defragmentation
int
oldItemChunkOffset
=
getChunkOffset
(
*
it
);
// Free the space previously used by the chunk
freeChunk
(
it
);
// Copy all the old data
memcpy
(
&
m_vertices
[
itemChunkOffset
],
&
m_vertices
[
oldItemChunkOffset
],
itemSize
*
VBO_ITEM
::
VertByteSize
);
itemChunkSize
=
newSize
;
}
else
{
itemChunkOffset
=
item
->
GetOffset
();
}
// Store new vertices in the chunk reserved for the unknown-sized item
offset
=
itemChunkOffset
+
itemSize
;
itemSize
+=
aSize
;
}
else
{
// Add vertices to previously already finished item
wxASSERT_MSG
(
false
,
wxT
(
"Warning: not tested yet"
)
);
ReservedChunkMap
::
iterator
it
=
m_reservedChunks
.
find
(
aVboItem
);
unsigned
int
chunkSize
=
getChunkSize
(
*
it
);
unsigned
int
itemSize
=
aVboItem
->
GetSize
();
if
(
chunkSize
<
itemSize
+
aSize
)
{
resizeChunk
(
aVboItem
,
itemSize
+
aSize
);
it
=
m_reservedChunks
.
find
(
aVboItem
);
}
offset
=
getChunkOffset
(
*
it
)
+
itemSize
;
}
for
(
unsigned
int
i
=
0
;
i
<
aSize
;
++
i
)
for
(
unsigned
int
i
=
0
;
i
<
aSize
;
++
i
)
{
{
// Pointer to the vertex that we are currently adding
vertexPtr
=
&
m_vertices
[
offset
+
i
];
// Modify the vertex according to the currently used transformations
// Modify the vertex according to the currently used transformations
if
(
m_transform
!=
NULL
)
if
(
m_transform
!=
NULL
)
{
{
...
@@ -197,6 +124,8 @@ void VBO_CONTAINER::Add( VBO_ITEM* aVboItem, const VBO_VERTEX* aVertex, unsigned
...
@@ -197,6 +124,8 @@ void VBO_CONTAINER::Add( VBO_ITEM* aVboItem, const VBO_VERTEX* aVertex, unsigned
{
{
vertexPtr
->
shader
[
j
]
=
m_shader
[
j
];
vertexPtr
->
shader
[
j
]
=
m_shader
[
j
];
}
}
vertexPtr
++
;
}
}
}
}
...
@@ -206,41 +135,90 @@ void VBO_CONTAINER::Clear()
...
@@ -206,41 +135,90 @@ void VBO_CONTAINER::Clear()
{
{
// Change size to the default one
// Change size to the default one
m_vertices
=
static_cast
<
VBO_VERTEX
*>
(
realloc
(
m_vertices
,
m_vertices
=
static_cast
<
VBO_VERTEX
*>
(
realloc
(
m_vertices
,
defaultInitSize
*
sizeof
(
VBO_VERTEX
)
)
);
m_initialSize
*
sizeof
(
VBO_VERTEX
)
)
);
// Set the size of all the stored VERTEX_ITEMs to 0, so it is clear that they are not held
// in the container anymore
Items
::
iterator
it
;
for
(
it
=
m_items
.
begin
();
it
!=
m_items
.
end
();
++
it
)
{
(
*
it
)
->
setSize
(
0
);
}
m_items
.
clear
();
// Reset state variables
// Reset state variables
m_freeSpace
=
defaultInitSize
;
m_currentSize
=
defaultInitSize
;
itemStarted
=
false
;
m_transform
=
NULL
;
m_transform
=
NULL
;
m_failed
=
false
;
m_failed
=
false
;
// By default no shader is used
// By default no shader is used
m_shader
[
0
]
=
0
;
m_shader
[
0
]
=
0
;
m_freeChunks
.
clear
();
m_reservedChunks
.
clear
();
// In the beginning there is only free space
// In the beginning there is only free space
m_freeSpace
=
m_initialSize
;
m_currentSize
=
m_initialSize
;
m_freeChunks
.
clear
();
m_freeChunks
.
insert
(
Chunk
(
m_freeSpace
,
0
)
);
m_freeChunks
.
insert
(
Chunk
(
m_freeSpace
,
0
)
);
}
}
void
VBO_CONTAINER
::
Free
(
VBO_ITEM
*
aItem
)
{
freeItem
(
aItem
);
// Dynamic memory freeing, there is no point in holding
// a large amount of memory when there is no use for it
if
(
m_freeSpace
>
(
m_currentSize
/
2
)
&&
m_currentSize
>
defaultInitSize
)
{
resizeContainer
(
m_currentSize
/
2
);
}
}
VBO_VERTEX
*
VBO_CONTAINER
::
GetAllVertices
()
const
VBO_VERTEX
*
VBO_CONTAINER
::
GetAllVertices
()
const
{
{
return
m_vertices
;
return
m_vertices
;
}
}
VBO_VERTEX
*
VBO_CONTAINER
::
GetVertices
(
const
VBO_ITEM
*
a
Vbo
Item
)
const
VBO_VERTEX
*
VBO_CONTAINER
::
GetVertices
(
const
VBO_ITEM
*
aItem
)
const
{
{
int
offset
=
a
Vbo
Item
->
GetOffset
();
int
offset
=
aItem
->
GetOffset
();
return
&
m_vertices
[
offset
];
return
&
m_vertices
[
offset
];
}
}
VBO_VERTEX
*
VBO_CONTAINER
::
allocate
(
unsigned
int
aSize
)
{
wxASSERT
(
m_item
!=
NULL
);
if
(
m_failed
)
return
NULL
;
if
(
m_itemSize
+
aSize
>
m_chunkSize
)
{
// There is not enough space in the currently reserved chunk, so we have to resize it
// Reserve a bigger memory chunk for the current item
m_chunkSize
=
std
::
max
(
(
2
*
m_itemSize
)
+
aSize
,
(
unsigned
)
3
);
// Save the current size before reallocating
m_chunkOffset
=
reallocate
(
m_chunkSize
);
if
(
m_chunkOffset
>
m_currentSize
)
{
m_failed
=
true
;
return
NULL
;
}
}
VBO_VERTEX
*
reserved
=
&
m_vertices
[
m_chunkOffset
+
m_itemSize
];
m_itemSize
+=
aSize
;
m_item
->
setSize
(
m_itemSize
);
return
reserved
;
}
unsigned
int
VBO_CONTAINER
::
allocate
(
VBO_ITEM
*
aVboItem
,
unsigned
int
aSize
)
unsigned
int
VBO_CONTAINER
::
reallocate
(
unsigned
int
aSize
)
{
{
// Is there enough space to store vertices?
// Is there enough space to store vertices?
if
(
m_freeSpace
<
aSize
)
if
(
m_freeSpace
<
aSize
)
...
@@ -259,74 +237,68 @@ unsigned int VBO_CONTAINER::allocate( VBO_ITEM* aVboItem, unsigned int aSize )
...
@@ -259,74 +237,68 @@ unsigned int VBO_CONTAINER::allocate( VBO_ITEM* aVboItem, unsigned int aSize )
result
=
resizeContainer
(
getPowerOf2
(
m_currentSize
*
2
+
aSize
)
);
result
=
resizeContainer
(
getPowerOf2
(
m_currentSize
*
2
+
aSize
)
);
}
}
// An error has occurred
if
(
!
result
)
if
(
!
result
)
{
return
UINT_MAX
;
return
UINT_MAX
;
}
}
}
// Look for the
space with
at least given size
// Look for the
free space of
at least given size
FreeChunkMap
::
iterator
it
=
m_freeChunks
.
lower_bound
(
aSize
);
FreeChunkMap
::
iterator
newChunk
=
m_freeChunks
.
lower_bound
(
aSize
);
if
(
it
==
m_freeChunks
.
end
()
)
if
(
newChunk
==
m_freeChunks
.
end
()
)
{
{
//
This means that there is enough space for
//
In the case when there is enough space to store the vertices,
//
storing vertices, but the space is not continous
//
but the free space is not continous we should defragment the container
if
(
!
defragment
()
)
if
(
!
defragment
()
)
{
return
UINT_MAX
;
return
UINT_MAX
;
}
// Update the current offset
m_chunkOffset
=
m_item
->
GetOffset
();
// We can take the first free chunk, as there is only one after defragmentation
// We can take the first free chunk, as there is only one after defragmentation
// and we can be sure that it provides enough space to store the object
// and we can be sure that it provides enough space to store the object
it
=
m_freeChunks
.
begin
();
newChunk
=
m_freeChunks
.
begin
();
}
}
unsigned
int
chunkSize
=
it
->
first
;
// Parameters of the allocated cuhnk
unsigned
int
chunkOffset
=
it
->
second
;
unsigned
int
chunkSize
=
newChunk
->
first
;
unsigned
int
chunkOffset
=
newChunk
->
second
;
m_freeChunks
.
erase
(
it
);
wxASSERT
(
chunkSize
>=
aSize
);
wxASSERT
(
chunkSize
>=
aSize
);
wxASSERT
(
chunkOffset
<
m_currentSize
);
// Check if the item was previously stored in the container
if
(
m_itemSize
>
0
)
{
// The item was reallocated, so we have to copy all the old data to the new place
memcpy
(
&
m_vertices
[
chunkOffset
],
&
m_vertices
[
m_chunkOffset
],
m_itemSize
*
VBO_ITEM
::
VertByteSize
);
// Free the space previously used by the chunk
m_freeChunks
.
insert
(
Chunk
(
m_itemSize
,
m_chunkOffset
)
);
m_freeSpace
+=
m_itemSize
;
}
// Remove the allocated chunk from the free space pool
m_freeChunks
.
erase
(
newChunk
);
m_freeSpace
-=
chunkSize
;
// If there is some space left, return it to the pool - add an entry for it
// If there is some space left, return it to the pool - add an entry for it
if
(
chunkSize
>
aSize
)
if
(
chunkSize
>
aSize
)
{
{
m_freeChunks
.
insert
(
Chunk
(
chunkSize
-
aSize
,
chunkOffset
+
aSize
)
);
m_freeChunks
.
insert
(
Chunk
(
chunkSize
-
aSize
,
chunkOffset
+
aSize
)
);
m_freeSpace
+=
chunkSize
-
aSize
;
}
}
m_freeSpace
-=
aSize
;
m_reservedChunks
.
insert
(
ReservedChunk
(
aVboItem
,
Chunk
(
aSize
,
chunkOffset
)
)
);
aVboItem
->
S
etOffset
(
chunkOffset
);
m_item
->
s
etOffset
(
chunkOffset
);
return
chunkOffset
;
return
chunkOffset
;
}
}
void
VBO_CONTAINER
::
freeChunk
(
const
ReservedChunkMap
::
iterator
&
aChunk
)
{
// Remove the chunk from the reserved chunks map and add to the free chunks map
int
size
=
getChunkSize
(
*
aChunk
);
int
offset
=
getChunkOffset
(
*
aChunk
);
m_reservedChunks
.
erase
(
aChunk
);
m_freeChunks
.
insert
(
Chunk
(
size
,
offset
)
);
m_freeSpace
+=
size
;
}
bool
VBO_CONTAINER
::
defragment
(
VBO_VERTEX
*
aTarget
)
bool
VBO_CONTAINER
::
defragment
(
VBO_VERTEX
*
aTarget
)
{
{
if
(
m_freeChunks
.
size
()
<=
1
)
{
// There is no point in defragmenting, as there is only one or no free chunks
return
true
;
}
if
(
aTarget
==
NULL
)
if
(
aTarget
==
NULL
)
{
{
// No target was specified, so we have to allocate our own space
// No target was specified, so we have to
re
allocate our own space
aTarget
=
static_cast
<
VBO_VERTEX
*>
(
malloc
(
m_currentSize
*
sizeof
(
VBO_VERTEX
)
)
);
aTarget
=
static_cast
<
VBO_VERTEX
*>
(
malloc
(
m_currentSize
*
sizeof
(
VBO_VERTEX
)
)
);
if
(
aTarget
==
NULL
)
if
(
aTarget
==
NULL
)
{
{
...
@@ -336,20 +308,18 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
...
@@ -336,20 +308,18 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
}
}
int
newOffset
=
0
;
int
newOffset
=
0
;
ReservedChunkMap
::
iterator
it
,
it_end
;
Items
::
iterator
it
,
it_end
;
for
(
it
=
m_
reservedChunks
.
begin
(),
it_end
=
m_reservedChunk
s
.
end
();
it
!=
it_end
;
++
it
)
for
(
it
=
m_
items
.
begin
(),
it_end
=
m_item
s
.
end
();
it
!=
it_end
;
++
it
)
{
{
VBO_ITEM
*
vboItem
=
getChunkVboItem
(
*
it
)
;
VBO_ITEM
*
item
=
*
it
;
int
itemOffset
=
getChunkOffset
(
*
it
);
int
itemOffset
=
item
->
GetOffset
(
);
int
itemSize
=
getChunkSize
(
*
it
);
int
itemSize
=
item
->
GetSize
(
);
// Move an item to the new container
// Move an item to the new container
memcpy
(
&
aTarget
[
newOffset
],
&
m_vertices
[
itemOffset
],
itemSize
*
VBO_ITEM
::
VertByteSize
);
memcpy
(
&
aTarget
[
newOffset
],
&
m_vertices
[
itemOffset
],
itemSize
*
VBO_ITEM
::
VertByteSize
);
// Update new offset
// Update its offset
if
(
vboItem
)
item
->
setOffset
(
newOffset
);
vboItem
->
SetOffset
(
newOffset
);
setChunkOffset
(
*
it
,
newOffset
);
// Move to the next free space
// Move to the next free space
newOffset
+=
itemSize
;
newOffset
+=
itemSize
;
...
@@ -360,28 +330,52 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
...
@@ -360,28 +330,52 @@ bool VBO_CONTAINER::defragment( VBO_VERTEX* aTarget )
// Now there is only one big chunk of free memory
// Now there is only one big chunk of free memory
m_freeChunks
.
clear
();
m_freeChunks
.
clear
();
m_freeChunks
.
insert
(
Chunk
(
m_freeSpace
,
m_currentSize
-
m_freeSpace
)
);
m_freeChunks
.
insert
(
Chunk
(
m_freeSpace
,
reservedSpace
()
)
);
return
true
;
return
true
;
}
}
void
VBO_CONTAINER
::
resizeChunk
(
VBO_ITEM
*
aVboItem
,
int
aNewSize
)
void
VBO_CONTAINER
::
mergeFreeChunks
(
)
{
{
wxASSERT_MSG
(
false
,
wxT
(
"Warning: not tested yet"
)
);
if
(
m_freeChunks
.
size
()
<
2
)
// There are no chunks that can be merged
return
;
// TODO ESPECIALLY test the case of shrinking chunk
// Reversed free chunks map - this one stores chunk size with its offset as the key
ReservedChunkMap
::
iterator
it
=
m_reservedChunks
.
find
(
aVboItem
);
std
::
list
<
Chunk
>
freeChunks
;
int
size
=
getChunkSize
(
*
it
);
int
offset
=
getChunkOffset
(
*
it
);
int
newOffset
=
allocate
(
aVboItem
,
aNewSize
);
FreeChunkMap
::
const_iterator
it
,
it_end
;
memcpy
(
&
m_vertices
[
newOffset
],
&
m_vertices
[
offset
],
size
*
VBO_ITEM
::
VertByteSize
);
for
(
it
=
m_freeChunks
.
begin
(),
it_end
=
m_freeChunks
.
end
();
it
!=
it_end
;
++
it
)
{
freeChunks
.
push_back
(
std
::
make_pair
(
it
->
second
,
it
->
first
)
);
}
m_freeChunks
.
clear
();
freeChunks
.
sort
();
// Remove the chunk from the reserved chunks map and add to the free chunks map
std
::
list
<
Chunk
>::
const_iterator
itf
,
itf_end
;
m_reservedChunks
.
erase
(
it
);
unsigned
int
offset
=
freeChunks
.
front
().
first
;
m_freeChunks
.
insert
(
Chunk
(
size
,
offset
)
);
unsigned
int
size
=
freeChunks
.
front
().
second
;
m_freeSpace
+=
size
;
freeChunks
.
pop_front
();
for
(
itf
=
freeChunks
.
begin
(),
itf_end
=
freeChunks
.
end
();
itf
!=
itf_end
;
++
itf
)
{
if
(
itf
->
first
==
offset
+
size
)
{
// These chunks can be merged, so just increase the current chunk size and go on
size
+=
itf
->
second
;
}
else
{
// These chunks cannot be merged
// So store the previous one
m_freeChunks
.
insert
(
std
::
make_pair
(
size
,
offset
)
);
// and let's check the next chunk
offset
=
itf
->
first
;
size
=
itf
->
second
;
}
}
// Add the last one
m_freeChunks
.
insert
(
std
::
make_pair
(
size
,
offset
)
);
}
}
...
@@ -391,8 +385,9 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
...
@@ -391,8 +385,9 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
if
(
aNewSize
<
m_currentSize
)
if
(
aNewSize
<
m_currentSize
)
{
{
// Shrinking container
// Sanity check, no shrinking if we cannot fit all the data
// Sanity check, no shrinking if we cannot fit all the data
if
(
(
m_currentSize
-
m_freeSpace
)
>
aNewSize
)
if
(
reservedSpace
(
)
>
aNewSize
)
return
false
;
return
false
;
newContainer
=
static_cast
<
VBO_VERTEX
*>
(
malloc
(
aNewSize
*
sizeof
(
VBO_VERTEX
)
)
);
newContainer
=
static_cast
<
VBO_VERTEX
*>
(
malloc
(
aNewSize
*
sizeof
(
VBO_VERTEX
)
)
);
...
@@ -404,52 +399,56 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
...
@@ -404,52 +399,56 @@ bool VBO_CONTAINER::resizeContainer( unsigned int aNewSize )
// Defragment directly to the new, smaller container
// Defragment directly to the new, smaller container
defragment
(
newContainer
);
defragment
(
newContainer
);
// We have to correct freeChunks after defragmentation
m_freeChunks
.
clear
();
m_freeChunks
.
insert
(
Chunk
(
aNewSize
-
reservedSpace
(),
reservedSpace
()
)
);
}
}
else
else
{
{
// Enlarging container
newContainer
=
static_cast
<
VBO_VERTEX
*>
(
realloc
(
m_vertices
,
aNewSize
*
sizeof
(
VBO_VERTEX
)
)
);
newContainer
=
static_cast
<
VBO_VERTEX
*>
(
realloc
(
m_vertices
,
aNewSize
*
sizeof
(
VBO_VERTEX
)
)
);
if
(
newContainer
==
NULL
)
if
(
newContainer
==
NULL
)
{
{
wxLogError
(
wxT
(
"Run out of memory"
)
);
wxLogError
(
wxT
(
"Run out of memory"
)
);
return
false
;
return
false
;
}
}
}
m_vertices
=
newContainer
;
// Update variables
// Add an entry for the new memory chunk at the end of the container
unsigned
int
lastFreeSize
=
0
;
m_freeChunks
.
insert
(
Chunk
(
aNewSize
-
m_currentSize
,
m_currentSize
)
);
unsigned
int
lastFreeOffset
=
0
;
// Search for the last free chunk *at the end of the container* (not the last chunk in general)
FreeChunkMap
::
reverse_iterator
lastFree
,
freeEnd
;
for
(
lastFree
=
m_freeChunks
.
rbegin
(),
freeEnd
=
m_freeChunks
.
rend
();
lastFree
!=
freeEnd
&&
lastFreeSize
+
lastFreeOffset
!=
m_currentSize
;
++
lastFree
)
{
lastFreeSize
=
getChunkSize
(
*
lastFree
);
lastFreeOffset
=
getChunkOffset
(
*
lastFree
);
}
}
if
(
lastFreeSize
+
lastFreeOffset
==
m_currentSize
)
m_vertices
=
newContainer
;
{
// We found a chunk at the end of the container
m_freeChunks
.
erase
(
lastFree
.
base
()
);
// so we can merge it with the new freeChunk chunk
m_freeChunks
.
insert
(
Chunk
(
aNewSize
-
m_currentSize
+
lastFreeSize
,
// size
m_currentSize
-
lastFreeSize
)
);
// offset
}
else
{
// As there is no free chunk at the end of container - simply add a new entry
if
(
aNewSize
>
m_currentSize
)
// only in the case of enlargement
{
m_freeChunks
.
insert
(
Chunk
(
aNewSize
-
m_currentSize
,
// size
m_currentSize
)
);
// offset
}
}
m_freeSpace
+=
(
aNewSize
-
m_currentSize
);
m_freeSpace
+=
(
aNewSize
-
m_currentSize
);
m_currentSize
=
aNewSize
;
m_currentSize
=
aNewSize
;
return
true
;
return
true
;
}
}
void
VBO_CONTAINER
::
freeItem
(
VBO_ITEM
*
aItem
)
{
int
size
=
aItem
->
GetSize
();
int
offset
=
aItem
->
GetOffset
();
m_freeChunks
.
insert
(
Chunk
(
size
,
offset
)
);
m_freeSpace
+=
size
;
m_items
.
erase
(
aItem
);
// Item size is set to 0, so it means that it is not stored in the container
aItem
->
setSize
(
0
);
}
void
VBO_CONTAINER
::
test
()
const
{
unsigned
int
freeSpace
=
0
;
FreeChunkMap
::
const_iterator
it
,
it_end
;
// Check if the amount of free memory stored as chunks is the same as reported by m_freeSpace
for
(
it
=
m_freeChunks
.
begin
(),
it_end
=
m_freeChunks
.
end
();
it
!=
it_end
;
++
it
)
freeSpace
+=
it
->
first
;
wxASSERT
(
freeSpace
==
m_freeSpace
);
}
common/gal/opengl/vbo_item.cpp
View file @
bbc0e8eb
...
@@ -52,9 +52,8 @@ VBO_ITEM::~VBO_ITEM()
...
@@ -52,9 +52,8 @@ VBO_ITEM::~VBO_ITEM()
void
VBO_ITEM
::
PushVertex
(
const
VBO_VERTEX
*
aVertex
)
void
VBO_ITEM
::
PushVertex
(
const
VBO_VERTEX
*
aVertex
)
{
{
m_container
->
Add
(
this
,
aVertex
);
m_container
->
Add
(
aVertex
);
m_size
++
;
m_isDirty
=
true
;
m_isDirty
=
true
;
}
}
...
...
include/gal/opengl/vbo_container.h
View file @
bbc0e8eb
...
@@ -35,8 +35,7 @@
...
@@ -35,8 +35,7 @@
#include <gal/opengl/vbo_item.h>
#include <gal/opengl/vbo_item.h>
#include <gal/color4d.h>
#include <gal/color4d.h>
#include <map>
#include <map>
#include <boost/unordered_map.hpp>
#include <set>
#include <wx/log.h>
namespace
KiGfx
namespace
KiGfx
{
{
...
@@ -47,23 +46,22 @@ class VBO_CONTAINER
...
@@ -47,23 +46,22 @@ class VBO_CONTAINER
{
{
public
:
public
:
VBO_CONTAINER
(
unsigned
int
aSize
=
defaultInitSize
);
VBO_CONTAINER
(
unsigned
int
aSize
=
defaultInitSize
);
~
VBO_CONTAINER
();
virtual
~
VBO_CONTAINER
();
///< Maps size of free memory chunks to their offsets
///< Maps size of free memory chunks to their offsets
typedef
std
::
pair
<
const
unsigned
int
,
unsigned
int
>
Chunk
;
typedef
std
::
pair
<
const
unsigned
int
,
unsigned
int
>
Chunk
;
typedef
std
::
multimap
<
const
unsigned
int
,
unsigned
int
>
FreeChunkMap
;
typedef
std
::
multimap
<
const
unsigned
int
,
unsigned
int
>
FreeChunkMap
;
///< Maps VBO_ITEMs to reserved memory chunks offsets & sizes
/// List of all the stored items
typedef
std
::
pair
<
VBO_ITEM
*
const
,
Chunk
>
ReservedChunk
;
typedef
std
::
set
<
VBO_ITEM
*>
Items
;
typedef
boost
::
unordered_map
<
VBO_ITEM
*
const
,
Chunk
>
ReservedChunkMap
;
/**
/**
* Function StartItem()
* Function StartItem()
* S
tarts an unknown sized item. After calling the function it is possible to add vertices
* S
ets an item to start its modifications. After calling the function it is possible to add
* using function Add().
*
vertices
using function Add().
* @param a
Vbo
Item is the item that is going to store vertices in the container.
* @param aItem is the item that is going to store vertices in the container.
*/
*/
void
StartItem
(
VBO_ITEM
*
a
Vbo
Item
);
void
StartItem
(
VBO_ITEM
*
aItem
);
/**
/**
* Function EndItem()
* Function EndItem()
...
@@ -74,30 +72,20 @@ public:
...
@@ -74,30 +72,20 @@ public:
/**
/**
* Function Add()
* Function Add()
* Stores given number of vertices in the container for the specific VBO_ITEM.
* Stores given number of vertices in the container for the specific VBO_ITEM (started by
* @param aVboItem is the owner of the vertices.
* StartItem() function).
* @param aItem is the owner of the vertices.
* @param aVertex are vertices data to be stored.
* @param aVertex are vertices data to be stored.
* @param aSize is the number of vertices to be added.
* @param aSize is the number of vertices to be added.
*/
*/
void
Add
(
VBO_ITEM
*
aVboItem
,
const
VBO_VERTEX
*
aVertex
,
unsigned
int
aSize
=
1
);
void
Add
(
const
VBO_VERTEX
*
aVertex
,
unsigned
int
aSize
=
1
);
/**
/**
* Function Free()
* Function Free()
* Frees the chunk reserved by the a
Vbo
Item.
* Frees the chunk reserved by the aItem.
* @param a
Vbo
Item is the owner of the chunk to be freed.
* @param aItem is the owner of the chunk to be freed.
*/
*/
inline
void
Free
(
VBO_ITEM
*
aVboItem
)
void
Free
(
VBO_ITEM
*
aItem
);
{
ReservedChunkMap
::
iterator
it
=
m_reservedChunks
.
find
(
aVboItem
);
freeChunk
(
it
);
// Dynamic memory freeing, there is no point in holding
// a large amount of memory when there is no use for it
if
(
m_freeSpace
>
(
m_currentSize
/
2
)
)
{
resizeContainer
(
m_currentSize
/
2
);
}
}
/**
/**
* Function Clear()
* Function Clear()
...
@@ -115,9 +103,9 @@ public:
...
@@ -115,9 +103,9 @@ public:
/**
/**
* Function GetVertices()
* Function GetVertices()
* Returns vertices stored by the specific item.
* Returns vertices stored by the specific item.
* @a
Vbo
Item is the specific item.
* @aItem is the specific item.
*/
*/
VBO_VERTEX
*
GetVertices
(
const
VBO_ITEM
*
a
Vbo
Item
)
const
;
VBO_VERTEX
*
GetVertices
(
const
VBO_ITEM
*
aItem
)
const
;
/**
/**
* Function GetVertices()
* Function GetVertices()
...
@@ -208,51 +196,50 @@ public:
...
@@ -208,51 +196,50 @@ public:
private
:
private
:
///< Stores size & offset of free chunks.
///< Stores size & offset of free chunks.
FreeChunkMap
m_freeChunks
;
FreeChunkMap
m_freeChunks
;
///< Stores owners (VBO_ITEM*) of reserved chunks and their size & offset.
///< Stored VERTEX_ITEMs
ReservedChunkMap
m_reservedChunks
;
Items
m_items
;
/**
* Function allocate()
* Allocates the given amount of memory for the current VBO_ITEM (set by StartItem() function).
* @param aSize is the number of vertices that are requested to be allocated.
* @return Pointer to the allocated space.
*/
VBO_VERTEX
*
allocate
(
unsigned
int
aSize
);
/**
/**
* Function allocate()
* Function reallocate()
* Finds an offset where the number of vertices can be stored in a continous space. If there is
* Resizes the chunk that stores the current item to the given size.
* no such chunk, appropriate amount of memory is allocated first.
* @param aVboItem is the owner of vertices to be stored.
* @param aSize is the number of vertices to be stored.
* @param aSize is the number of vertices to be stored.
* @return Offset of the new chunk.
*/
*/
unsigned
int
allocate
(
VBO_ITEM
*
aVboItem
,
unsigned
int
aSize
);
unsigned
int
reallocate
(
unsigned
int
aSize
);
/**
/**
* Function getChunkSize()
* Function getChunkSize()
* Returns size of the given chunk
(works both for reserved and free chunks)
.
* Returns size of the given chunk.
* @param aChunk is the chunk.
* @param aChunk is the chunk.
* @return Size of the chunk.
*/
*/
inline
int
getChunkSize
(
const
Chunk
&
aChunk
)
const
inline
unsigned
int
getChunkSize
(
const
Chunk
&
aChunk
)
const
{
{
return
aChunk
.
first
;
return
aChunk
.
first
;
}
}
inline
int
getChunkSize
(
const
ReservedChunk
&
aChunk
)
const
{
return
aChunk
.
second
.
first
;
}
/**
/**
* Function getChunkOffset()
* Function getChunkOffset()
* Returns offset of the given chunk
(works both for reserved and free chunks)
.
* Returns offset of the given chunk.
* @param aChunk is the chunk.
* @param aChunk is the chunk.
* @return Offset of the chunk.
*/
*/
inline
unsigned
int
getChunkOffset
(
const
Chunk
&
aChunk
)
const
inline
unsigned
int
getChunkOffset
(
const
Chunk
&
aChunk
)
const
{
{
return
aChunk
.
second
;
return
aChunk
.
second
;
}
}
inline
unsigned
int
getChunkOffset
(
const
ReservedChunk
&
aChunk
)
const
{
return
aChunk
.
second
.
second
;
}
/**
/**
* Function
g
etChunkOffset()
* Function
s
etChunkOffset()
* Up
adtes offset of the given chunk (works both for reserved and free chunks)
.
* Up
dates offset of the given chunk
.
* !! IMPORTANT: it does not reallocate the chunk, it just changes its properties.
* !! IMPORTANT: it does not reallocate the chunk, it just changes its properties.
* @param aChunk is the chunk.
* @param aChunk is the chunk.
*/
*/
...
@@ -261,51 +248,45 @@ private:
...
@@ -261,51 +248,45 @@ private:
aChunk
.
second
=
aOffset
;
aChunk
.
second
=
aOffset
;
}
}
inline
void
setChunkOffset
(
ReservedChunk
&
aChunk
,
unsigned
int
aOffset
)
const
{
aChunk
.
second
.
second
=
aOffset
;
}
/**
* Function getChunkVboItem()
* Returns owner of the given reserved chunk.
* @param aChunk is the chunk.
*/
inline
VBO_ITEM
*
getChunkVboItem
(
const
ReservedChunk
&
aChunk
)
const
{
return
aChunk
.
first
;
}
/**
/**
* Function defragment()
* Function defragment()
* Removes empty spaces between chunks, so after that there is a long continous space
* Removes empty spaces between chunks, so after that there is a long continous space
* for storing vertices at the and of the container.
* for storing vertices at the and of the container.
* @return false in case of failure (eg. memory shortage)
* @return false in case of failure (eg. memory shortage)
.
*/
*/
bool
defragment
(
VBO_VERTEX
*
aTarget
=
NULL
);
bool
defragment
(
VBO_VERTEX
*
aTarget
=
NULL
);
/**
/**
* Function resizeChunk()
* Function mergeFreeChunks()
* Changes size of the chunk that stores vertices of aVboItem.
* Looks for consecutive free memory chunks and merges them, decreasing fragmentation of
* @param aVboItem is the item for which reserved space size should be changed.
* memory.
* @param aNewSize is the new size for the aVboItem, expressed in vertices number.
*/
*/
void
resizeChunk
(
VBO_ITEM
*
aVboItem
,
int
aNewSize
);
void
mergeFreeChunks
(
);
/**
/**
* Function resizeContainer()
* Function resizeContainer()
* Prepares a bigger container of a given size.
* Prepares a bigger container of a given size.
* @param aNewSize is the new size of container, expressed in vertices
* @param aNewSize is the new size of container, expressed in vertices
* @return false in case of failure (eg. memory shortage)
* @return false in case of failure (eg. memory shortage)
.
*/
*/
bool
resizeContainer
(
unsigned
int
aNewSize
);
bool
resizeContainer
(
unsigned
int
aNewSize
);
/**
/**
* Function free
Chunk
()
* Function free
Item
()
* Frees the space
described in aChunk
and returns it to the free space pool.
* Frees the space
occupied by the item
and returns it to the free space pool.
* @param a
Chunk is a space
to be freed.
* @param a
Item is the item
to be freed.
*/
*/
void
freeChunk
(
const
ReservedChunkMap
::
iterator
&
aChunk
);
void
freeItem
(
VBO_ITEM
*
aItem
);
/**
* Function reservedSpace()
* Returns size of the reserved memory space.
* @return Size of the reserved memory space (expressed as a number of vertices).
*/
unsigned
int
reservedSpace
()
{
return
m_currentSize
-
m_freeSpace
;
}
///< How many vertices we can store in the container
///< How many vertices we can store in the container
unsigned
int
m_freeSpace
;
unsigned
int
m_freeSpace
;
...
@@ -316,25 +297,26 @@ private:
...
@@ -316,25 +297,26 @@ private:
///< Actual storage memory
///< Actual storage memory
VBO_VERTEX
*
m_vertices
;
VBO_VERTEX
*
m_vertices
;
///<
A flag saying if there is the item with an unknown size being added
///<
Initial size, used on clearing the container
bool
itemStarted
;
unsigned
int
m_initialSize
;
///< Variables holding the state of the item currently being added
///< Variables holding the state of the item currently being modified
unsigned
int
itemSize
;
unsigned
int
m_itemSize
;
unsigned
int
itemChunkSize
;
unsigned
int
m_chunkSize
;
VBO_ITEM
*
item
;
unsigned
int
m_chunkOffset
;
VBO_ITEM
*
m_item
;
///< Color used for new vertices pushed.
///< Color used for
the
new vertices pushed.
GLubyte
m_color
[
VBO_ITEM
::
ColorStride
];
GLubyte
m_color
[
VBO_ITEM
::
ColorStride
];
///< Shader and its parameters used for new vertices pushed
///< Shader and its parameters used for new vertices pushed
GLfloat
m_shader
[
VBO_ITEM
::
ShaderStride
];
GLfloat
m_shader
[
VBO_ITEM
::
ShaderStride
];
///< Current transform matrix applied for every new vertex pushed.
///< Current transform matrix applied for every new vertex pushed.
const
glm
::
mat4
*
m_transform
;
const
glm
::
mat4
*
m_transform
;
///< Failure flag
///< Failure flag
bool
m_failed
;
bool
m_failed
;
/**
/**
* Function getPowerOf2()
* Function getPowerOf2()
...
@@ -353,6 +335,9 @@ private:
...
@@ -353,6 +335,9 @@ private:
///< Default initial size of a container (expressed in vertices)
///< Default initial size of a container (expressed in vertices)
static
const
unsigned
int
defaultInitSize
=
1048576
;
static
const
unsigned
int
defaultInitSize
=
1048576
;
///< Basic tests for the container, use only for debugging.
void
test
()
const
;
};
};
}
// namespace KiGfx
}
// namespace KiGfx
...
...
include/gal/opengl/vbo_item.h
View file @
bbc0e8eb
...
@@ -47,6 +47,8 @@ class VBO_CONTAINER;
...
@@ -47,6 +47,8 @@ class VBO_CONTAINER;
class
VBO_ITEM
class
VBO_ITEM
{
{
friend
class
VBO_CONTAINER
;
public
:
public
:
VBO_ITEM
(
VBO_CONTAINER
*
aContainer
);
VBO_ITEM
(
VBO_CONTAINER
*
aContainer
);
~
VBO_ITEM
();
~
VBO_ITEM
();
...
@@ -89,16 +91,6 @@ public:
...
@@ -89,16 +91,6 @@ public:
return
m_size
;
return
m_size
;
}
}
/**
* Function SetOffset()
* Sets data offset in the VBO.
* @param aOffset is the offset expressed as a number of vertices.
*/
inline
void
SetOffset
(
unsigned
int
aOffset
)
{
m_offset
=
aOffset
;
}
/**
/**
* Function GetOffset()
* Function GetOffset()
* Returns data offset in the VBO.
* Returns data offset in the VBO.
...
@@ -149,7 +141,7 @@ public:
...
@@ -149,7 +141,7 @@ public:
static
const
unsigned
int
IndByteSize
=
sizeof
(
GLuint
);
static
const
unsigned
int
IndByteSize
=
sizeof
(
GLuint
);
pr
ivate
:
pr
otected
:
///< Offset and size of data stored in the VBO_CONTAINER.
///< Offset and size of data stored in the VBO_CONTAINER.
unsigned
int
m_offset
;
unsigned
int
m_offset
;
unsigned
int
m_size
;
unsigned
int
m_size
;
...
@@ -159,6 +151,26 @@ private:
...
@@ -159,6 +151,26 @@ private:
///< Flag telling if the item should be recached in VBO or not.
///< Flag telling if the item should be recached in VBO or not.
bool
m_isDirty
;
bool
m_isDirty
;
/**
* Function setSize()
* Sets data size in the VBO.
* @param aSize is the size expressed as a number of vertices.
*/
void
setSize
(
unsigned
int
aSize
)
{
m_size
=
aSize
;
}
/**
* Function setOffset()
* Sets data offset in the VBO.
* @param aOffset is the offset expressed as a number of vertices.
*/
inline
void
setOffset
(
unsigned
int
aOffset
)
{
m_offset
=
aOffset
;
}
};
};
}
// namespace KiGfx
}
// namespace KiGfx
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment