1 |
#include <vector> |
2 |
|
3 |
#include "salloc.h" |
4 |
|
5 |
struct rc_key_t |
6 |
{ |
7 |
GLenum mode; |
8 |
GLenum format; // 0, GL_T2F_V3F, GL_V2F |
9 |
GLuint texname; |
10 |
unsigned char r, g, b, a; |
11 |
|
12 |
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 |
} |
34 |
|
35 |
struct rc_t |
36 |
{ |
37 |
struct glyph_data |
38 |
{ |
39 |
uint8_t u, v, w, h; |
40 |
uint16_t x, y; |
41 |
}; |
42 |
|
43 |
struct array_t |
44 |
: std::vector<uint8_t, slice_allocator<uint8_t>> |
45 |
{ |
46 |
using std::vector<uint8_t, slice_allocator<uint8_t>>::vector; |
47 |
|
48 |
template<typename T> |
49 |
T &append () |
50 |
{ |
51 |
auto ofs = size (); |
52 |
resize (ofs + sizeof (T)); |
53 |
return *(T *)(data () + ofs); |
54 |
} |
55 |
|
56 |
void v2f (float x, float y) |
57 |
{ |
58 |
auto &vec = append<float[2]> (); |
59 |
vec[0] = x / 2; |
60 |
vec[1] = y / 2; |
61 |
} |
62 |
|
63 |
void t2f_v3f (float u, float v, float x, float y, float z) |
64 |
{ |
65 |
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 |
} |
72 |
|
73 |
void glyph (int u, int v, int w, int h, int x, int y) |
74 |
{ |
75 |
if (w && h) |
76 |
{ |
77 |
auto &c = append<glyph_data> (); |
78 |
|
79 |
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 |
} |
86 |
} |
87 |
}; |
88 |
|
89 |
int drawcount = 0; |
90 |
ska::flat_hash_map<rc_key_t, array_t, std::hash<rc_key_t>, std::equal_to<rc_key_t>, slice_allocator<rc_key_t>> h; |
91 |
|
92 |
void clear () |
93 |
{ |
94 |
drawcount = 0; |
95 |
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 |
// reduces storage requirements from 80 bytes/char to 8 |
136 |
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 |
|
157 |
if (ecb_expect_false (++drawcount == 16)) |
158 |
for (auto &&it = h.begin (); it != h.end (); ++it) |
159 |
it->second.shrink_to_fit (); |
160 |
} |
161 |
}; |
162 |
|