ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cf.schmorp.de/Deliantra-Client/texcache.c
Revision: 1.8
Committed: Sun Nov 29 14:45:12 2009 UTC (14 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_10, rel-2_11
Changes since 1.7: +11 -1 lines
Log Message:
*** empty log message ***

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 static void tc_get (tc_area *area, int width, int height);
15 static void tc_put (tc_area *area);
16 static void tc_clear (void);
17 static void tc_backup (void);
18 static void tc_restore (void);
19
20 /////////////////////////////////////////////////////////////////////////////
21
22 // required as bug-workaround for apple/ati/...
23 static unsigned char tc_temptile [TC_WIDTH * TC_HEIGHT];
24
25 #include <glib.h>
26
27 int tc_generation;
28
29 typedef struct tc_texture {
30 struct tc_texture *next;
31 GLuint name;
32 int avail;
33 char *saved; /* stores saved texture data */
34 } tc_texture;
35
36 typedef struct tc_slice {
37 GLuint name;
38 int avail, y;
39 } tc_slice;
40
41 static tc_slice slices[TC_HEIGHT / TC_ROUND];
42 static tc_texture *first_texture;
43
44 void
45 tc_clear (void)
46 {
47 int i;
48
49 for (i = TC_HEIGHT / TC_ROUND; i--; )
50 slices [i].name = 0;
51
52 while (first_texture)
53 {
54 tc_texture *next = first_texture->next;
55 del_texture (first_texture->name);
56 g_slice_free (tc_texture, first_texture);
57 first_texture = next;
58 }
59
60 ++tc_generation;
61 }
62
63 void
64 tex_backup (tc_texture *tex)
65 {
66 tex->saved = g_slice_alloc (TC_WIDTH * TC_HEIGHT);
67
68 glBindTexture (GL_TEXTURE_2D, tex->name);
69 glGetTexImage (GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
70 }
71
72 void
73 tex_restore (tc_texture *tex)
74 {
75 glBindTexture (GL_TEXTURE_2D, tex->name);
76 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
77 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
78 glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
79
80 g_slice_free1 (TC_WIDTH * TC_HEIGHT, tex->saved);
81 tex->saved = 0;
82 }
83
84 void
85 tc_backup (void)
86 {
87 tc_texture *tex;
88
89 for (tex = first_texture; tex; tex = tex->next)
90 tex_backup (tex);
91 }
92
93 void
94 tc_restore (void)
95 {
96 tc_texture *tex;
97
98 for (tex = first_texture; tex; tex = tex->next)
99 tex_restore (tex);
100 }
101
102 void
103 tc_get (tc_area *area, int width, int height)
104 {
105 int slice_height = MIN (height + TC_ROUND - 1, TC_HEIGHT) & ~(TC_ROUND - 1);
106 tc_slice *slice = slices + slice_height / TC_ROUND;
107
108 area->w = width;
109 area->h = height;
110
111 width = MIN (width, TC_WIDTH);
112
113 if (!slice->name || slice->avail < width)
114 {
115 // try to find a texture with enough space
116 tc_texture *tex, *match = 0;
117
118 for (tex = first_texture; tex; tex = tex->next)
119 if (tex->avail >= slice_height && (!match || match->avail > tex->avail))
120 match = tex;
121
122 // create a new texture if necessary
123 if (!match)
124 {
125 match = g_slice_new (tc_texture);
126 match->next = first_texture;
127 first_texture = match;
128 match->name = gen_texture ();
129 match->avail = TC_HEIGHT;
130 match->saved = 0;
131
132 glBindTexture (GL_TEXTURE_2D, match->name);
133 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
134 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
135
136 // the last parameter should be NULL, but way too amny drivers (ATI, Mesa) crash,
137 // so we better provide some random garbage data for them.
138 glTexImage2D (GL_TEXTURE_2D,
139 0, GL_ALPHA,
140 TC_WIDTH, TC_HEIGHT,
141 0, GL_ALPHA,
142 GL_UNSIGNED_BYTE, tc_temptile);
143 }
144
145 match->avail -= slice_height;
146
147 slice->name = match->name;
148 slice->avail = TC_WIDTH;
149 slice->y = match->avail;
150 }
151
152 slice->avail -= width;
153
154 area->name = slice->name;
155 area->x = slice->avail;
156 area->y = slice->y;
157 }
158
159 void
160 tc_put (tc_area *area)
161 {
162 // our management is too primitive to support this operation yet
163 }