aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp')
-rw-r--r--libraries/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp154
1 files changed, 154 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp b/libraries/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp
new file mode 100644
index 0000000..8d3dd45
--- /dev/null
+++ b/libraries/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp
@@ -0,0 +1,154 @@
1
2//#define ENABLE_LOG_PRINTF
3
4#include "evas_direct3d_vertex_buffer_cache.h"
5#include "evas_direct3d_device.h"
6
7#include <assert.h>
8
9
10Ref<D3DVertexBufferCache> D3DVertexBufferCache::_this;
11
12D3DVertexBufferCache::D3DVertexBufferCache()
13{
14 size_border_low = 0.6; // We can reuse buffer on 60%
15 size_border_high = 0.2; // We can reallocate the buffer on 20%
16}
17
18D3DVertexBufferCache::~D3DVertexBufferCache()
19{
20 Uninitialize();
21}
22
23D3DVertexBufferCache *D3DVertexBufferCache::Current()
24{
25 if (_this.IsNull())
26 _this = new D3DVertexBufferCache();
27 return _this;
28}
29
30void D3DVertexBufferCache::SetCurrent(D3DVertexBufferCache *obj)
31{
32 _this = obj;
33}
34
35void D3DVertexBufferCache::Uninitialize()
36{
37 for (int i = 0; i < _cache.Length(); i++)
38 {
39 assert(_cache[i].vb != NULL);
40 _cache[i].vb->Release();
41 }
42 _cache.Resize();
43}
44
45bool D3DVertexBufferCache::InitBuffer(D3DDevice *d3d, BYTE *data, int size, CacheEntryInfo &info)
46{
47 assert(d3d != NULL);
48 assert(data != NULL);
49 assert(size > 0);
50
51 int best = FindBestEntry(size);
52 CacheEntry *ce = NULL;
53
54 // Reallocate
55 if (best >= 0 && _cache[best].size < size)
56 {
57 DeleteEntry(best);
58 best = -1;
59 }
60
61 // New
62 if (best < 0)
63 {
64 CacheEntry new_entry;
65 if (!CreateEntry(d3d, new_entry, size))
66 {
67 WRN("Failed to create new vbcache entry");
68 return false;
69 }
70 _cache.Add(new_entry);
71 info.id = _cache.Length() - 1;
72 ce = _cache.Last();
73 }
74 else
75 {
76 info.id = best;
77 ce = &_cache[best];
78 }
79
80 assert(ce != NULL);
81 if (!InsertData(*ce, data, size))
82 {
83 WRN("Failed to insert vbcache data");
84 return false;
85 }
86 return true;
87}
88
89bool D3DVertexBufferCache::SelectBufferToDevice(D3DDevice *device, int id, int vertex_size)
90{
91 if (id < 0 || id >= _cache.Length())
92 return false;
93 return SUCCEEDED(device->GetDevice()->SetStreamSource(0, _cache[id].vb, 0, vertex_size));
94}
95
96int D3DVertexBufferCache::FindBestEntry(int size)
97{
98 // Search for buffer that fits in borders
99 for (int i = 0; i < _cache.Length(); i++)
100 {
101 const int vs = _cache[i].size;
102 if (size >= (vs - FLOAT(vs) * size_border_low) && size <= vs)
103 return i;
104 }
105 bool less_than_all = true;
106 for (int i = 0; i < _cache.Length(); i++)
107 {
108 const int vs = _cache[i].size;
109 if (size >= (vs - FLOAT(vs) * size_border_low))
110 less_than_all = false;
111 }
112 // Requested size is too small to reuse in any buffer
113 if (less_than_all)
114 return -1;
115 // Search for buffer that can be reallocated
116 for (int i = 0; i < _cache.Length(); i++)
117 {
118 const int vs = _cache[i].size;
119 if (size <= (vs + FLOAT(vs) * size_border_high))
120 return i;
121 }
122 // No buffer can be reused or reallocated, create a new one
123 return -1;
124}
125
126bool D3DVertexBufferCache::CreateEntry(D3DDevice *d3d, CacheEntry &entry, int size)
127{
128 assert(d3d != NULL);
129 if (FAILED(d3d->GetDevice()->CreateVertexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
130 0, D3DPOOL_DEFAULT, &entry.vb, NULL)))
131 {
132 return false;
133 }
134 entry.size = size;
135 return true;
136}
137
138void D3DVertexBufferCache::DeleteEntry(int id)
139{
140 if (id < 0 || id >= _cache.Length())
141 return;
142 assert(_cache[id].vb != NULL);
143 _cache[id].vb->Release();
144 _cache.Replace(id);
145}
146
147bool D3DVertexBufferCache::InsertData(CacheEntry &entry, BYTE *data, int size)
148{
149 BYTE *ptr = NULL;
150 if (FAILED(entry.vb->Lock(0, size, (void **)&ptr, D3DLOCK_DISCARD)))
151 return false;
152 CopyMemory(ptr, data, size);
153 return SUCCEEDED(entry.vb->Unlock());
154}