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

# 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 root 1.8 // required as bug-workaround for apple/ati/...
23     static unsigned char tc_temptile [TC_WIDTH * TC_HEIGHT];
24    
25 root 1.1 #include <glib.h>
26    
27 root 1.2 int tc_generation;
28    
29 root 1.1 typedef struct tc_texture {
30     struct tc_texture *next;
31     GLuint name;
32     int avail;
33 root 1.5 char *saved; /* stores saved texture data */
34 root 1.1 } 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 root 1.5 tc_clear (void)
46 root 1.1 {
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 root 1.3 del_texture (first_texture->name);
56 root 1.1 g_slice_free (tc_texture, first_texture);
57     first_texture = next;
58     }
59 root 1.2
60     ++tc_generation;
61 root 1.1 }
62    
63     void
64 root 1.7 tex_backup (tc_texture *tex)
65 root 1.5 {
66 root 1.7 tex->saved = g_slice_alloc (TC_WIDTH * TC_HEIGHT);
67 root 1.5
68 root 1.7 glBindTexture (GL_TEXTURE_2D, tex->name);
69     glGetTexImage (GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved);
70 root 1.5 }
71    
72     void
73 root 1.7 tex_restore (tc_texture *tex)
74 root 1.5 {
75 root 1.7 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 root 1.5
80 root 1.7 g_slice_free1 (TC_WIDTH * TC_HEIGHT, tex->saved);
81     tex->saved = 0;
82     }
83 root 1.5
84 root 1.7 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 root 1.5
93 root 1.7 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 root 1.5 }
101    
102     void
103 root 1.1 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 root 1.5 match->next = first_texture;
127 root 1.1 first_texture = match;
128 root 1.5 match->name = gen_texture ();
129     match->avail = TC_HEIGHT;
130     match->saved = 0;
131 root 1.1
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 root 1.8
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 root 1.1 }
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     }