ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cf.schmorp.de/Deliantra-Client/texcache.c
Revision: 1.5
Committed: Tue Dec 25 18:58:32 2007 UTC (16 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +40 -4 lines
Log Message:
save/restore textures in a safer way, also save/restore glyph cache

File Contents

# User Rev Content
1 root 1.1 // all these must be powers of two
2 root 1.4 // width and height better be <=256 as we use bytes in the rendercache
3 root 1.1 #define TC_WIDTH 256
4     #define TC_HEIGHT 256
5     #define TC_ROUND 4
6    
7     typedef struct {
8     GLuint name;
9     int x, y, w, h;
10     } tc_area;
11    
12 root 1.2 extern int tc_generation;
13    
14 root 1.1 void tc_get (tc_area *area, int width, int height);
15     void tc_put (tc_area *area);
16     void tc_clear ();
17    
18     /////////////////////////////////////////////////////////////////////////////
19    
20     #include <glib.h>
21    
22 root 1.2 int tc_generation;
23    
24 root 1.1 typedef struct tc_texture {
25     struct tc_texture *next;
26     GLuint name;
27     int avail;
28 root 1.5 char *saved; /* stores saved texture data */
29 root 1.1 } tc_texture;
30    
31     typedef struct tc_slice {
32     GLuint name;
33     int avail, y;
34     } tc_slice;
35    
36     static tc_slice slices[TC_HEIGHT / TC_ROUND];
37     static tc_texture *first_texture;
38    
39     void
40 root 1.5 tc_clear (void)
41 root 1.1 {
42     int i;
43    
44     for (i = TC_HEIGHT / TC_ROUND; i--; )
45     slices [i].name = 0;
46    
47     while (first_texture)
48     {
49     tc_texture *next = first_texture->next;
50 root 1.3 del_texture (first_texture->name);
51 root 1.1 g_slice_free (tc_texture, first_texture);
52     first_texture = next;
53     }
54 root 1.2
55     ++tc_generation;
56 root 1.1 }
57    
58     void
59 root 1.5 tc_backup (void)
60     {
61     tc_texture *tex = first_texture;
62     while (tex)
63     {
64     tex->saved = g_slice_alloc (TC_WIDTH * TC_HEIGHT);
65    
66     glBindTexture (GL_TEXTURE_2D, tex->name);
67     glGetTexImage (GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
68    
69     tex = tex->next;
70     }
71     }
72    
73     void
74     tc_restore (void)
75     {
76     tc_texture *tex = first_texture;
77    
78     while (tex)
79     {
80     glBindTexture (GL_TEXTURE_2D, tex->name);
81     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
82     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
83     glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
84    
85     g_slice_free1 (TC_WIDTH * TC_HEIGHT, tex->saved);
86     tex->saved = 0;
87    
88     tex = tex->next;
89     }
90     }
91    
92     void
93 root 1.1 tc_get (tc_area *area, int width, int height)
94     {
95     int slice_height = MIN (height + TC_ROUND - 1, TC_HEIGHT) & ~(TC_ROUND - 1);
96     tc_slice *slice = slices + slice_height / TC_ROUND;
97    
98     area->w = width;
99     area->h = height;
100    
101     width = MIN (width, TC_WIDTH);
102    
103     if (!slice->name || slice->avail < width)
104     {
105     // try to find a texture with enough space
106     tc_texture *tex, *match = 0;
107    
108     for (tex = first_texture; tex; tex = tex->next)
109     if (tex->avail >= slice_height && (!match || match->avail > tex->avail))
110     match = tex;
111    
112     // create a new texture if necessary
113     if (!match)
114     {
115     match = g_slice_new (tc_texture);
116 root 1.5 match->next = first_texture;
117 root 1.1 first_texture = match;
118 root 1.5 match->name = gen_texture ();
119     match->avail = TC_HEIGHT;
120     match->saved = 0;
121 root 1.1
122     glBindTexture (GL_TEXTURE_2D, match->name);
123     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
124     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
125     glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
126     }
127    
128     match->avail -= slice_height;
129    
130     slice->name = match->name;
131     slice->avail = TC_WIDTH;
132     slice->y = match->avail;
133     }
134    
135     slice->avail -= width;
136    
137     area->name = slice->name;
138     area->x = slice->avail;
139     area->y = slice->y;
140     }
141    
142     void
143     tc_put (tc_area *area)
144     {
145     // our management is too primitive to support this operation yet
146     }