1 |
root |
1.11 |
#include <vector> |
2 |
|
|
|
3 |
root |
1.15 |
#include "salloc.h" |
4 |
|
|
|
5 |
root |
1.11 |
struct rc_key_t |
6 |
|
|
{ |
7 |
root |
1.1 |
GLenum mode; |
8 |
root |
1.3 |
GLenum format; // 0, GL_T2F_V3F, GL_V2F |
9 |
root |
1.7 |
GLuint texname; |
10 |
root |
1.1 |
unsigned char r, g, b, a; |
11 |
|
|
|
12 |
root |
1.11 |
bool operator == (const rc_key_t &o) const |
13 |
|
|
{ |
14 |
|
|
return mode == o.mode |
15 |
|
|
&& format == o.format |
16 |
|
|
&& texname == o.texname |
17 |
|
|
&& r == o.r |
18 |
|
|
&& g == o.g |
19 |
|
|
&& b == o.b |
20 |
|
|
&& a == o.a; |
21 |
|
|
} |
22 |
|
|
}; |
23 |
|
|
|
24 |
|
|
namespace std { |
25 |
|
|
template <> |
26 |
|
|
struct hash<rc_key_t> |
27 |
|
|
{ |
28 |
|
|
size_t operator () (const rc_key_t &v) const |
29 |
|
|
{ |
30 |
|
|
return v.mode + (v.format << 4) + v.texname + (v.r << 8) + (v.g << 16) + (v.b << 24) + v.a; |
31 |
|
|
} |
32 |
|
|
}; |
33 |
root |
1.1 |
} |
34 |
|
|
|
35 |
root |
1.11 |
struct rc_t |
36 |
root |
1.1 |
{ |
37 |
root |
1.11 |
struct glyph_data |
38 |
|
|
{ |
39 |
|
|
uint8_t u, v, w, h; |
40 |
|
|
uint16_t x, y; |
41 |
|
|
}; |
42 |
root |
1.1 |
|
43 |
root |
1.11 |
struct array_t |
44 |
root |
1.15 |
: std::vector<uint8_t, slice_allocator<uint8_t>> |
45 |
root |
1.11 |
{ |
46 |
root |
1.15 |
using std::vector<uint8_t, slice_allocator<uint8_t>>::vector; |
47 |
root |
1.1 |
|
48 |
root |
1.11 |
template<typename T> |
49 |
|
|
T &append () |
50 |
root |
1.1 |
{ |
51 |
root |
1.11 |
auto ofs = size (); |
52 |
|
|
resize (ofs + sizeof (T)); |
53 |
|
|
return *(T *)(data () + ofs); |
54 |
root |
1.1 |
} |
55 |
|
|
|
56 |
root |
1.11 |
void v2f (float x, float y) |
57 |
|
|
{ |
58 |
|
|
auto &vec = append<float[2]> (); |
59 |
root |
1.12 |
vec[0] = x / 2; |
60 |
|
|
vec[1] = y / 2; |
61 |
root |
1.11 |
} |
62 |
root |
1.1 |
|
63 |
root |
1.11 |
void t2f_v3f (float u, float v, float x, float y, float z) |
64 |
root |
1.9 |
{ |
65 |
root |
1.11 |
auto &vec = append<float[5]> (); |
66 |
|
|
vec[0] = u; |
67 |
|
|
vec[1] = v; |
68 |
|
|
vec[2] = x; |
69 |
|
|
vec[3] = y; |
70 |
|
|
vec[4] = z; |
71 |
root |
1.9 |
} |
72 |
root |
1.1 |
|
73 |
root |
1.11 |
void glyph (int u, int v, int w, int h, int x, int y) |
74 |
root |
1.1 |
{ |
75 |
root |
1.11 |
if (w && h) |
76 |
root |
1.4 |
{ |
77 |
root |
1.11 |
auto &c = append<glyph_data> (); |
78 |
root |
1.3 |
|
79 |
root |
1.11 |
c.u = u; |
80 |
|
|
c.v = v; |
81 |
|
|
c.w = w; |
82 |
|
|
c.h = h; |
83 |
|
|
c.x = x + w; |
84 |
|
|
c.y = y + h; |
85 |
root |
1.4 |
} |
86 |
root |
1.1 |
} |
87 |
root |
1.11 |
}; |
88 |
root |
1.1 |
|
89 |
root |
1.14 |
int drawcount = 0; |
90 |
root |
1.11 |
ska::flat_hash_map<rc_key_t, array_t> h; |
91 |
root |
1.1 |
|
92 |
root |
1.11 |
void clear () |
93 |
|
|
{ |
94 |
root |
1.14 |
drawcount = 0; |
95 |
root |
1.11 |
h.clear (); |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
array_t &array (const rc_key_t &k) |
99 |
|
|
{ |
100 |
|
|
return h[k]; |
101 |
|
|
} |
102 |
|
|
|
103 |
|
|
void draw () |
104 |
|
|
{ |
105 |
|
|
for (auto &&it = h.begin (); it != h.end (); ++it) |
106 |
|
|
{ |
107 |
|
|
rc_key_t &key = it->first; |
108 |
|
|
array_t &arr = it->second; |
109 |
|
|
GLsizei stride; |
110 |
|
|
|
111 |
|
|
if (key.texname) |
112 |
|
|
{ |
113 |
|
|
glBindTexture (GL_TEXTURE_2D, key.texname); |
114 |
|
|
glEnable (GL_TEXTURE_2D); |
115 |
|
|
} |
116 |
|
|
else |
117 |
|
|
glDisable (GL_TEXTURE_2D); |
118 |
|
|
|
119 |
|
|
glColor4ub (key.r, key.g, key.b, key.a); |
120 |
|
|
|
121 |
|
|
if (key.format) |
122 |
|
|
{ |
123 |
|
|
stride = key.format == GL_T2F_V3F ? sizeof (float) * 5 |
124 |
|
|
: key.format == GL_V2F ? sizeof (float) * 2 |
125 |
|
|
: 65536; |
126 |
|
|
|
127 |
|
|
glInterleavedArrays (key.format, 0, (void *)arr.data ()); |
128 |
|
|
//glLockArraysEXT (0, len / stride); |
129 |
|
|
glDrawArrays (key.mode, 0, arr.size () / stride); |
130 |
|
|
//glUnlockArraysEXT (); |
131 |
|
|
} |
132 |
|
|
else |
133 |
|
|
{ |
134 |
|
|
// optimised character quad storage. slower but nice on memory. |
135 |
root |
1.13 |
// reduces storage requirements from 80 bytes/char to 8 |
136 |
root |
1.11 |
auto *c = (glyph_data *) arr.data (); |
137 |
|
|
auto *e = (glyph_data *)(arr.data () + arr.size ()); |
138 |
|
|
|
139 |
|
|
glBegin (key.mode); // practically must be quads |
140 |
|
|
|
141 |
|
|
while (c < e) |
142 |
|
|
{ |
143 |
|
|
glTexCoord2f ( c->u * (1.f / TC_WIDTH), c->v * (1.f / TC_HEIGHT)); glVertex2i (c->x - c->w, c->y - c->h); |
144 |
|
|
glTexCoord2f ((c->u + c->w) * (1.f / TC_WIDTH), c->v * (1.f / TC_HEIGHT)); glVertex2i (c->x , c->y - c->h); |
145 |
|
|
glTexCoord2f ((c->u + c->w) * (1.f / TC_WIDTH), (c->v + c->h) * (1.f / TC_HEIGHT)); glVertex2i (c->x , c->y ); |
146 |
|
|
glTexCoord2f ( c->u * (1.f / TC_WIDTH), (c->v + c->h) * (1.f / TC_HEIGHT)); glVertex2i (c->x - c->w, c->y ); |
147 |
|
|
|
148 |
|
|
++c; |
149 |
|
|
} |
150 |
|
|
|
151 |
|
|
glEnd (); |
152 |
|
|
} |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
glDisable (GL_TEXTURE_2D); |
156 |
root |
1.14 |
|
157 |
|
|
if (ecb_expect_false (++drawcount == 16)) |
158 |
|
|
for (auto &&it = h.begin (); it != h.end (); ++it) |
159 |
|
|
it->second.shrink_to_fit (); |
160 |
root |
1.11 |
} |
161 |
|
|
}; |
162 |
root |
1.1 |
|