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

# User Rev Content
1 root 1.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 root 1.2 extern int tc_generation;
12    
13 root 1.1 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 root 1.2 int tc_generation;
22    
23 root 1.1 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 root 1.2
53     ++tc_generation;
54 root 1.1 }
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     }