--- deliantra/Deliantra-Client/rendercache.c 2007/08/11 11:07:09 1.1 +++ deliantra/Deliantra-Client/rendercache.c 2018/11/18 03:10:35 1.12 @@ -1,114 +1,154 @@ -typedef struct { - GLenum mode; - GLenum format; // GL_T2F_V3F, GL_V2F - GLint texname; - unsigned char r, g, b, a; -} rc_key_t; - -typedef struct { - HV *hv; -} rc_t; - -typedef SV rc_array_t; - -static rc_t * -rc_alloc () -{ - rc_t *rc = g_slice_new0 (rc_t); - rc->hv = newHV (); - - return rc; -} - -static void -rc_free (rc_t *rc) -{ - SvREFCNT_dec (rc->hv); - g_slice_free (rc_t, rc); -} - -static void -rc_clear (rc_t *rc) -{ - hv_clear (rc->hv); -} +#include -static rc_array_t * -rc_array (rc_t *rc, rc_key_t *k) +struct rc_key_t { - SV *sv = *hv_fetch (rc->hv, (char *)k, sizeof (*k), 1); + GLenum mode; + GLenum format; // 0, GL_T2F_V3F, GL_V2F + GLuint texname; + unsigned char r, g, b, a; - if (SvTYPE (sv) != SVt_PV) + bool operator == (const rc_key_t &o) const + { + return mode == o.mode + && format == o.format + && texname == o.texname + && r == o.r + && g == o.g + && b == o.b + && a == o.a; + } +}; + +namespace std { + template <> + struct hash + { + size_t operator () (const rc_key_t &v) const { - sv_upgrade (sv, SVt_PV); - SvPOK_only (sv); + return v.mode + (v.format << 4) + v.texname + (v.r << 8) + (v.g << 16) + (v.b << 24) + v.a; } - - return sv; -} - -static void -rc_v2f (rc_array_t *arr, float x, float y) -{ - STRLEN len = SvCUR (arr) + sizeof (float) * 5; - SvGROW (arr, len); - - ((float *)SvEND (arr))[0] = x; - ((float *)SvEND (arr))[1] = y; - - SvCUR_set (arr, len); + }; } -static void -rc_t2f_v3f (rc_array_t *arr, float u, float v, float x, float y, float z) +struct rc_t { - STRLEN len = SvCUR (arr) + sizeof (float) * 5; - SvGROW (arr, len); - - ((float *)SvEND (arr))[0] = u; - ((float *)SvEND (arr))[1] = v; + struct glyph_data + { + uint8_t u, v, w, h; + uint16_t x, y; + }; - ((float *)SvEND (arr))[2] = x; - ((float *)SvEND (arr))[3] = y; - ((float *)SvEND (arr))[4] = z; + struct array_t + : std::vector + { + using std::vector::vector; - SvCUR_set (arr, len); -} + template + T &append () + { + auto ofs = size (); + resize (ofs + sizeof (T)); + return *(T *)(data () + ofs); + } -static void -rc_draw (rc_t *rc) -{ - HE *he; + void v2f (float x, float y) + { + auto &vec = append (); + vec[0] = x / 2; + vec[1] = y / 2; + } - hv_iterinit (rc->hv); - while ((he = hv_iternext (rc->hv))) + void t2f_v3f (float u, float v, float x, float y, float z) { - rc_key_t *key = (rc_key_t *)HeKEY (he); - rc_array_t *arr = HeVAL (he); - STRLEN len; - char *arr_pv = SvPV (arr, len); - GLsizei stride; - - stride = key->format == GL_T2F_V3F ? sizeof (float) * 5 - : key->format == GL_V2F ? sizeof (float) * 2 - : 65536; + auto &vec = append (); + vec[0] = u; + vec[1] = v; + vec[2] = x; + vec[3] = y; + vec[4] = z; + } - if (key->texname) + void glyph (int u, int v, int w, int h, int x, int y) + { + if (w && h) { - glBindTexture (GL_TEXTURE_2D, key->texname); - glEnable (GL_TEXTURE_2D); - } - else - glDisable (GL_TEXTURE_2D); + auto &c = append (); - glColor4ub (key->r, key->g, key->b, key->a); - glInterleavedArrays (key->format, 0, (void *)arr_pv); - glDrawArrays (key->mode, 0, len / stride); + c.u = u; + c.v = v; + c.w = w; + c.h = h; + c.x = x + w; + c.y = y + h; + } } + }; - glDisable (GL_TEXTURE_2D); -} - - + ska::flat_hash_map h; + void clear () + { + h.clear (); + } + + array_t &array (const rc_key_t &k) + { + return h[k]; + } + + void draw () + { + for (auto &&it = h.begin (); it != h.end (); ++it) + { + rc_key_t &key = it->first; + array_t &arr = it->second; + GLsizei stride; + + if (key.texname) + { + glBindTexture (GL_TEXTURE_2D, key.texname); + glEnable (GL_TEXTURE_2D); + } + else + glDisable (GL_TEXTURE_2D); + + glColor4ub (key.r, key.g, key.b, key.a); + + if (key.format) + { + stride = key.format == GL_T2F_V3F ? sizeof (float) * 5 + : key.format == GL_V2F ? sizeof (float) * 2 + : 65536; + + glInterleavedArrays (key.format, 0, (void *)arr.data ()); + //glLockArraysEXT (0, len / stride); + glDrawArrays (key.mode, 0, arr.size () / stride); + //glUnlockArraysEXT (); + } + else + { + // optimised character quad storage. slower but nice on memory. + // reduces storage requirements from 80 bytes/char to 6-8 + auto *c = (glyph_data *) arr.data (); + auto *e = (glyph_data *)(arr.data () + arr.size ()); + + glBegin (key.mode); // practically must be quads + + while (c < e) + { + glTexCoord2f ( c->u * (1.f / TC_WIDTH), c->v * (1.f / TC_HEIGHT)); glVertex2i (c->x - c->w, c->y - c->h); + glTexCoord2f ((c->u + c->w) * (1.f / TC_WIDTH), c->v * (1.f / TC_HEIGHT)); glVertex2i (c->x , c->y - c->h); + glTexCoord2f ((c->u + c->w) * (1.f / TC_WIDTH), (c->v + c->h) * (1.f / TC_HEIGHT)); glVertex2i (c->x , c->y ); + glTexCoord2f ( c->u * (1.f / TC_WIDTH), (c->v + c->h) * (1.f / TC_HEIGHT)); glVertex2i (c->x - c->w, c->y ); + + ++c; + } + + glEnd (); + } + } + + glDisable (GL_TEXTURE_2D); + } +};