ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/texcache.c
Revision: 1.7
Committed: Thu Nov 26 07:19:11 2009 UTC (14 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.6: +27 -22 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 #include <glib.h>
23
24 int tc_generation;
25
26 typedef struct tc_texture {
27 struct tc_texture *next;
28 GLuint name;
29 int avail;
30 char *saved; /* stores saved texture data */
31 } tc_texture;
32
33 typedef struct tc_slice {
34 GLuint name;
35 int avail, y;
36 } tc_slice;
37
38 static tc_slice slices[TC_HEIGHT / TC_ROUND];
39 static tc_texture *first_texture;
40
41 void
42 tc_clear (void)
43 {
44 int i;
45
46 for (i = TC_HEIGHT / TC_ROUND; i--; )
47 slices [i].name = 0;
48
49 while (first_texture)
50 {
51 tc_texture *next = first_texture->next;
52 del_texture (first_texture->name);
53 g_slice_free (tc_texture, first_texture);
54 first_texture = next;
55 }
56
57 ++tc_generation;
58 }
59
60 void
61 tex_backup (tc_texture *tex)
62 {
63 tex->saved = g_slice_alloc (TC_WIDTH * TC_HEIGHT);
64
65 glBindTexture (GL_TEXTURE_2D, tex->name);
66 glGetTexImage (GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
67 }
68
69 void
70 tex_restore (tc_texture *tex)
71 {
72 glBindTexture (GL_TEXTURE_2D, tex->name);
73 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
74 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
75 glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
76
77 g_slice_free1 (TC_WIDTH * TC_HEIGHT, tex->saved);
78 tex->saved = 0;
79 }
80
81 void
82 tc_backup (void)
83 {
84 tc_texture *tex;
85
86 for (tex = first_texture; tex; tex = tex->next)
87 tex_backup (tex);
88 }
89
90 void
91 tc_restore (void)
92 {
93 tc_texture *tex;
94
95 for (tex = first_texture; tex; tex = tex->next)
96 tex_restore (tex);
97 }
98
99 void
100 tc_get (tc_area *area, int width, int height)
101 {
102 int slice_height = MIN (height + TC_ROUND - 1, TC_HEIGHT) & ~(TC_ROUND - 1);
103 tc_slice *slice = slices + slice_height / TC_ROUND;
104
105 area->w = width;
106 area->h = height;
107
108 width = MIN (width, TC_WIDTH);
109
110 if (!slice->name || slice->avail < width)
111 {
112 // try to find a texture with enough space
113 tc_texture *tex, *match = 0;
114
115 for (tex = first_texture; tex; tex = tex->next)
116 if (tex->avail >= slice_height && (!match || match->avail > tex->avail))
117 match = tex;
118
119 // create a new texture if necessary
120 if (!match)
121 {
122 match = g_slice_new (tc_texture);
123 match->next = first_texture;
124 first_texture = match;
125 match->name = gen_texture ();
126 match->avail = TC_HEIGHT;
127 match->saved = 0;
128
129 glBindTexture (GL_TEXTURE_2D, match->name);
130 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
131 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
132 glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
133 }
134
135 match->avail -= slice_height;
136
137 slice->name = match->name;
138 slice->avail = TC_WIDTH;
139 slice->y = match->avail;
140 }
141
142 slice->avail -= width;
143
144 area->name = slice->name;
145 area->x = slice->avail;
146 area->y = slice->y;
147 }
148
149 void
150 tc_put (tc_area *area)
151 {
152 // our management is too primitive to support this operation yet
153 }