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

# 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.6 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 root 1.1
20     /////////////////////////////////////////////////////////////////////////////
21    
22     #include <glib.h>
23    
24 root 1.2 int tc_generation;
25    
26 root 1.1 typedef struct tc_texture {
27     struct tc_texture *next;
28     GLuint name;
29     int avail;
30 root 1.5 char *saved; /* stores saved texture data */
31 root 1.1 } 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 root 1.5 tc_clear (void)
43 root 1.1 {
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 root 1.3 del_texture (first_texture->name);
53 root 1.1 g_slice_free (tc_texture, first_texture);
54     first_texture = next;
55     }
56 root 1.2
57     ++tc_generation;
58 root 1.1 }
59    
60     void
61 root 1.7 tex_backup (tc_texture *tex)
62 root 1.5 {
63 root 1.7 tex->saved = g_slice_alloc (TC_WIDTH * TC_HEIGHT);
64 root 1.5
65 root 1.7 glBindTexture (GL_TEXTURE_2D, tex->name);
66     glGetTexImage (GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
67 root 1.5 }
68    
69     void
70 root 1.7 tex_restore (tc_texture *tex)
71 root 1.5 {
72 root 1.7 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 root 1.5
77 root 1.7 g_slice_free1 (TC_WIDTH * TC_HEIGHT, tex->saved);
78     tex->saved = 0;
79     }
80 root 1.5
81 root 1.7 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 root 1.5
90 root 1.7 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 root 1.5 }
98    
99     void
100 root 1.1 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 root 1.5 match->next = first_texture;
124 root 1.1 first_texture = match;
125 root 1.5 match->name = gen_texture ();
126     match->avail = TC_HEIGHT;
127     match->saved = 0;
128 root 1.1
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     }