]> git.tdb.fi Git - gldbg.git/blob - flavors/gl/source/texturestate.cpp
More complete support for textures
[gldbg.git] / flavors / gl / source / texturestate.cpp
1 #include "enums.h"
2 #include "strformat.h"
3 #include "texturestate.h"
4
5 using namespace std;
6
7 TexImageState::TexImageState():
8         width(0),
9         height(0),
10         depth(0),
11         internal_format(0)
12 { }
13
14 void TexImageState::set_1d(GLenum ifmt, unsigned wd)
15 {
16         set_3d(ifmt, wd, 0, 0);
17 }
18
19 void TexImageState::set_2d(GLenum ifmt, unsigned wd, unsigned ht)
20 {
21         set_3d(ifmt, wd, ht, 0);
22 }
23
24 void TexImageState::set_3d(GLenum ifmt, unsigned wd, unsigned ht, unsigned dp)
25 {
26         width = wd;
27         height = ht;
28         depth = dp;
29         internal_format = ifmt;
30 }
31
32 string TexImageState::describe() const
33 {
34         string descr = strformat("%d", width);
35         if(height)
36         {
37                 descr += strformat("x%d", height);
38                 if(depth)
39                         descr += strformat("x%d", height);
40         }
41         descr += strformat(", %s", describe_enum(internal_format, "PixelFormat"));
42         return descr;
43 }
44
45
46 GLenum texture_cube_faces[6] = 
47 {
48         GL_TEXTURE_CUBE_MAP_POSITIVE_X,
49         GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
50         GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
51         GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
52         GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
53         GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
54 };
55
56 TextureState::TextureState():
57         id(0),
58         target(0),
59         min_filter(GL_LINEAR_MIPMAP_LINEAR),
60         mag_filter(GL_LINEAR),
61         wrap_s(GL_REPEAT),
62         wrap_t(GL_REPEAT),
63         wrap_r(GL_REPEAT),
64         compare_mode(GL_NONE),
65         compare_func(GL_LEQUAL),
66         generate_mipmap(false)
67 { }
68
69 TexImageState &TextureState::get_image(unsigned level)
70 {
71         if(images.size()<=level)
72                 images.resize(level+1);
73         return images[level];
74 }
75
76 void TextureState::set_image_1d(unsigned level, GLenum ifmt, unsigned wd)
77 {
78         get_image(level).set_1d(ifmt, wd);
79         if(level==0 && generate_mipmap)
80                 create_mipmaps();
81 }
82
83 void TextureState::set_image_2d(unsigned level, GLenum ifmt, unsigned wd, unsigned ht)
84 {
85         get_image(level).set_2d(ifmt, wd, ht);
86         if(level==0 && generate_mipmap)
87                 create_mipmaps();
88 }
89
90 void TextureState::set_face_image_2d(GLenum face, unsigned level, GLenum ifmt, unsigned wd, unsigned ht)
91 {
92         unsigned index = 0;
93         for(; (index<6 && texture_cube_faces[index]!=face); ++index) ;
94         if(index>=6)
95                 return;
96
97         set_image_2d(level*6+index, ifmt, wd, ht);
98 }
99
100 void TextureState::set_image_3d(unsigned level, GLenum ifmt, unsigned wd, unsigned ht, unsigned dp)
101 {
102         get_image(level).set_3d(ifmt, wd, ht, dp);
103         if(level==0 && generate_mipmap)
104                 create_mipmaps();
105 }
106
107 void TextureState::create_mipmaps(unsigned face)
108 {
109         unsigned stride = (target==GL_TEXTURE_CUBE_MAP ? 6 : 1);
110         if(face>=stride)
111                 face = 0;
112
113         unsigned wd = images[face].width;
114         unsigned ht = images[face].height;
115         unsigned dp = images[face].depth;
116         for(unsigned i=1;; ++i)
117         {
118                 if(wd<=1 && ht<=1 && dp<=1)
119                         break;
120
121                 if(wd>1)
122                         wd /= 2;
123                 if(ht>1)
124                         ht /= 2;
125                 if(dp>1)
126                         dp /= 2;
127
128                 get_image(i*stride+face).set_3d(images[0].internal_format, wd, ht, dp);
129         }
130 }
131
132 void TextureState::set_parameter(GLenum pname, const int *values)
133 {
134         if(pname==GL_TEXTURE_MIN_FILTER)
135                 min_filter = values[0];
136         else if(pname==GL_TEXTURE_MAG_FILTER)
137                 mag_filter = values[0];
138         else if(pname==GL_TEXTURE_WRAP_S)
139                 wrap_s = values[0];
140         else if(pname==GL_TEXTURE_WRAP_T)
141                 wrap_t = values[0];
142         else if(pname==GL_TEXTURE_WRAP_R)
143                 wrap_r = values[0];
144         else if(pname==GL_TEXTURE_COMPARE_MODE)
145                 compare_mode = values[0];
146         else if(pname==GL_TEXTURE_COMPARE_FUNC)
147                 compare_func = values[0];
148         else if(pname==GL_GENERATE_MIPMAP)
149                 generate_mipmap = values[0];
150 }
151
152 string TextureState::describe() const
153 {
154         string descr = describe_enum(target, "TextureTarget");
155         if(images.empty())
156                 descr += ", undefined";
157         else if(target==GL_TEXTURE_CUBE_MAP)
158         {
159                 bool homogeneous = true;
160                 for(unsigned i=1; (homogeneous && i<6); ++i)
161                         homogeneous = (images[i].width==images[0].width && images[i].height==images[0].height &&
162                                 images[i].internal_format==images[0].internal_format);
163                 if(homogeneous)
164                         descr += ", "+images.front().describe();
165                 else
166                         descr += ", heterogeneous faces";
167         }
168         else
169                 descr += ", "+images.front().describe();
170         return descr;
171 }
172
173
174 TexUnitState::Binding *TexUnitState::get_binding(GLenum target)
175 {
176         if(target==GL_TEXTURE_1D)
177                 return &binding_1d;
178         else if(target==GL_TEXTURE_2D)
179                 return &binding_2d;
180         else if(target==GL_TEXTURE_3D)
181                 return &binding_3d;
182         else if(target==GL_TEXTURE_CUBE_MAP)
183                 return &binding_cube;
184         else
185                 return 0;
186 }
187
188 const TexUnitState::Binding *TexUnitState::get_binding(GLenum target) const
189 {
190         return const_cast<TexUnitState *>(this)->get_binding(target);
191 }
192
193 void TexUnitState::set_current_texture(GLenum target, TextureState *tex)
194 {
195         if(Binding *binding = get_binding(target))
196                 binding->current = tex;
197 }
198
199 TextureState *TexUnitState::get_current_texture(GLenum target)
200 {
201         if(Binding *binding = get_binding(target))
202                 return binding->current;
203         else
204                 return 0;
205 }
206
207 const TextureState *TexUnitState::get_current_texture(GLenum target) const
208 {
209         return const_cast<TexUnitState *>(this)->get_current_texture(target);
210 }
211
212 bool TexUnitState::is_enabled(GLenum target) const
213 {
214         if(const Binding *binding = get_binding(target))
215                 return binding->enabled;
216         else
217                 return false;
218 }
219
220 string TexUnitState::describe_binding(GLenum target) const
221 {
222         if(const Binding *binding = get_binding(target))
223                 return binding->describe();
224         else
225                 return "None";
226 }
227
228
229 TexUnitState::Binding::Binding():
230         enabled(false),
231         current(0)
232 { }
233
234 string TexUnitState::Binding::describe() const
235 {
236         if(current)
237         {
238                 string descr = strformat("%d ", current->id);
239                 if(current->images.empty())
240                         descr += "(undefined)";
241                 else
242                         descr += "("+current->images.front().describe()+")";
243                 if(enabled)
244                         descr += ", enabled";
245                 return descr;
246         }
247         else if(enabled)
248                 return "None, enabled";
249         else
250                 return "None";
251 }