ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/texcache.c
Revision: 1.2
Committed: Tue Jul 4 23:56:34 2006 UTC (17 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-0_97, rel-0_52, rel-0_53, rel-0_51, rel-0_2, rel-0_5
Changes since 1.1: +6 -0 lines
Log Message:
There is of course no way to clear glyph caches in stupid pango, so we
have to add a generation counter to each and every glyph structure and
check it on every access.

File Contents

# Content
1 // all these must be powers of two
2 #define TC_WIDTH 256
3 #define TC_HEIGHT 256
4 #define TC_ROUND 4
5
6 typedef struct {
7 GLuint name;
8 int x, y, w, h;
9 } tc_area;
10
11 extern int tc_generation;
12
13 void tc_get (tc_area *area, int width, int height);
14 void tc_put (tc_area *area);
15 void tc_clear ();
16
17 /////////////////////////////////////////////////////////////////////////////
18
19 #include <glib.h>
20
21 int tc_generation;
22
23 typedef struct tc_texture {
24 struct tc_texture *next;
25 GLuint name;
26 int avail;
27 } tc_texture;
28
29 typedef struct tc_slice {
30 GLuint name;
31 int avail, y;
32 } tc_slice;
33
34 static tc_slice slices[TC_HEIGHT / TC_ROUND];
35 static tc_texture *first_texture;
36
37 void
38 tc_clear ()
39 {
40 int i;
41
42 for (i = TC_HEIGHT / TC_ROUND; i--; )
43 slices [i].name = 0;
44
45 while (first_texture)
46 {
47 tc_texture *next = first_texture->next;
48 glDeleteTextures (1, &first_texture->name);
49 g_slice_free (tc_texture, first_texture);
50 first_texture = next;
51 }
52
53 ++tc_generation;
54 }
55
56 void
57 tc_get (tc_area *area, int width, int height)
58 {
59 int slice_height = MIN (height + TC_ROUND - 1, TC_HEIGHT) & ~(TC_ROUND - 1);
60 tc_slice *slice = slices + slice_height / TC_ROUND;
61
62 area->w = width;
63 area->h = height;
64
65 width = MIN (width, TC_WIDTH);
66
67 if (!slice->name || slice->avail < width)
68 {
69 // try to find a texture with enough space
70 tc_texture *tex, *match = 0;
71
72 for (tex = first_texture; tex; tex = tex->next)
73 if (tex->avail >= slice_height && (!match || match->avail > tex->avail))
74 match = tex;
75
76 // create a new texture if necessary
77 if (!match)
78 {
79 match = g_slice_new (tc_texture);
80 match->next = first_texture;
81 first_texture = match;
82 glGenTextures (1, &match->name);
83 match->avail = TC_HEIGHT;
84
85 glBindTexture (GL_TEXTURE_2D, match->name);
86 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
87 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
88 glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
89 }
90
91 match->avail -= slice_height;
92
93 slice->name = match->name;
94 slice->avail = TC_WIDTH;
95 slice->y = match->avail;
96 }
97
98 slice->avail -= width;
99
100 area->name = slice->name;
101 area->x = slice->avail;
102 area->y = slice->y;
103 }
104
105 void
106 tc_put (tc_area *area)
107 {
108 // our management is too primitive to support this operation yet
109 }