1 | // all these must be powers of two |
1 | // all these must be powers of two |
|
|
2 | // width and height better be <=256 as we use bytes in the rendercache |
2 | #define TC_WIDTH 256 |
3 | #define TC_WIDTH 256 |
3 | #define TC_HEIGHT 256 |
4 | #define TC_HEIGHT 256 |
4 | #define TC_ROUND 4 |
5 | #define TC_ROUND 4 |
5 | |
6 | |
6 | typedef struct { |
7 | typedef struct { |
… | |
… | |
8 | int x, y, w, h; |
9 | int x, y, w, h; |
9 | } tc_area; |
10 | } tc_area; |
10 | |
11 | |
11 | extern int tc_generation; |
12 | extern int tc_generation; |
12 | |
13 | |
13 | void tc_get (tc_area *area, int width, int height); |
14 | static void tc_get (tc_area *area, int width, int height); |
14 | void tc_put (tc_area *area); |
15 | static void tc_put (tc_area *area); |
15 | void tc_clear (); |
16 | static void tc_clear (void); |
|
|
17 | static void tc_backup (void); |
|
|
18 | static void tc_restore (void); |
16 | |
19 | |
17 | ///////////////////////////////////////////////////////////////////////////// |
20 | ///////////////////////////////////////////////////////////////////////////// |
|
|
21 | |
|
|
22 | // required as bug-workaround for apple/ati/... |
|
|
23 | static unsigned char tc_temptile [TC_WIDTH * TC_HEIGHT]; |
18 | |
24 | |
19 | #include <glib.h> |
25 | #include <glib.h> |
20 | |
26 | |
21 | int tc_generation; |
27 | int tc_generation; |
22 | |
28 | |
23 | typedef struct tc_texture { |
29 | typedef struct tc_texture { |
24 | struct tc_texture *next; |
30 | struct tc_texture *next; |
25 | GLuint name; |
31 | GLuint name; |
26 | int avail; |
32 | int avail; |
|
|
33 | char *saved; /* stores saved texture data */ |
27 | } tc_texture; |
34 | } tc_texture; |
28 | |
35 | |
29 | typedef struct tc_slice { |
36 | typedef struct tc_slice { |
30 | GLuint name; |
37 | GLuint name; |
31 | int avail, y; |
38 | int avail, y; |
… | |
… | |
33 | |
40 | |
34 | static tc_slice slices[TC_HEIGHT / TC_ROUND]; |
41 | static tc_slice slices[TC_HEIGHT / TC_ROUND]; |
35 | static tc_texture *first_texture; |
42 | static tc_texture *first_texture; |
36 | |
43 | |
37 | void |
44 | void |
38 | tc_clear () |
45 | tc_clear (void) |
39 | { |
46 | { |
40 | int i; |
47 | int i; |
41 | |
48 | |
42 | for (i = TC_HEIGHT / TC_ROUND; i--; ) |
49 | for (i = TC_HEIGHT / TC_ROUND; i--; ) |
43 | slices [i].name = 0; |
50 | slices [i].name = 0; |
… | |
… | |
49 | g_slice_free (tc_texture, first_texture); |
56 | g_slice_free (tc_texture, first_texture); |
50 | first_texture = next; |
57 | first_texture = next; |
51 | } |
58 | } |
52 | |
59 | |
53 | ++tc_generation; |
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); |
54 | } |
100 | } |
55 | |
101 | |
56 | void |
102 | void |
57 | tc_get (tc_area *area, int width, int height) |
103 | tc_get (tc_area *area, int width, int height) |
58 | { |
104 | { |
… | |
… | |
75 | |
121 | |
76 | // create a new texture if necessary |
122 | // create a new texture if necessary |
77 | if (!match) |
123 | if (!match) |
78 | { |
124 | { |
79 | match = g_slice_new (tc_texture); |
125 | match = g_slice_new (tc_texture); |
80 | match->next = first_texture; |
126 | match->next = first_texture; |
81 | first_texture = match; |
127 | first_texture = match; |
82 | match->name = gen_texture (); |
128 | match->name = gen_texture (); |
83 | match->avail = TC_HEIGHT; |
129 | match->avail = TC_HEIGHT; |
|
|
130 | match->saved = 0; |
84 | |
131 | |
85 | glBindTexture (GL_TEXTURE_2D, match->name); |
132 | glBindTexture (GL_TEXTURE_2D, match->name); |
86 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
133 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
87 | glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
134 | 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); |
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); |
89 | } |
143 | } |
90 | |
144 | |
91 | match->avail -= slice_height; |
145 | match->avail -= slice_height; |
92 | |
146 | |
93 | slice->name = match->name; |
147 | slice->name = match->name; |