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

# Content
1 // all these must be powers of two
2 // width and height better be <=256 as we use bytes in the rendercache
3 #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 extern int tc_generation;
13
14 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 int tc_generation;
23
24 typedef struct tc_texture {
25 struct tc_texture *next;
26 GLuint name;
27 int avail;
28 char *saved; /* stores saved texture data */
29 } 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 tc_clear (void)
41 {
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 del_texture (first_texture->name);
51 g_slice_free (tc_texture, first_texture);
52 first_texture = next;
53 }
54
55 ++tc_generation;
56 }
57
58 void
59 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 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 match->next = first_texture;
117 first_texture = match;
118 match->name = gen_texture ();
119 match->avail = TC_HEIGHT;
120 match->saved = 0;
121
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 }