]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_texenv_state.cpp
Initial vogl checkin
[vogl] / src / voglcommon / vogl_texenv_state.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 // File: vogl_texenv_state.cpp
27 #include "vogl_texenv_state.h"
28
29 vogl_texenv_state::vogl_texenv_state()
30     : m_valid(false)
31 {
32     VOGL_FUNC_TRACER
33 }
34
35 vogl_texenv_state::~vogl_texenv_state()
36 {
37     VOGL_FUNC_TRACER
38 }
39
40 bool vogl_texenv_state::snapshot(const vogl_context_info &context_info)
41 {
42     VOGL_FUNC_TRACER
43
44     clear();
45
46     VOGL_CHECK_GL_ERROR;
47
48     bool any_gl_errors = false;
49
50     VOGL_CHECK_GL_ERROR;
51
52     vogl_scoped_state_saver state_saver(cGSTActiveTexture);
53
54     if (vogl_check_gl_error())
55         any_gl_errors = true;
56
57     for (uint texcoord_index = 0; texcoord_index < context_info.get_max_texture_coords(); texcoord_index++)
58     {
59         GL_ENTRYPOINT(glActiveTexture)(GL_TEXTURE0 + texcoord_index);
60
61         if (vogl_check_gl_error())
62             any_gl_errors = true;
63
64 #define GET_FLOAT(target, idx, pname)                                   \
65     do                                                                  \
66     {                                                                   \
67         float values[4] = { 0, 0, 0, 0 };                               \
68         GL_ENTRYPOINT(glGetTexEnvfv)(target, pname, values);            \
69         if (vogl_check_gl_error())                                       \
70             any_gl_errors = true;                                       \
71         m_params[target].insert(pname, idx, values, sizeof(values[0])); \
72     } while (0)
73 #define GET_INT(target, idx, pname)                                     \
74     do                                                                  \
75     {                                                                   \
76         int values[4] = { 0, 0, 0, 0 };                                 \
77         GL_ENTRYPOINT(glGetTexEnviv)(target, pname, values);            \
78         if (vogl_check_gl_error())                                       \
79             any_gl_errors = true;                                       \
80         m_params[target].insert(pname, idx, values, sizeof(values[0])); \
81     } while (0)
82         GET_FLOAT(GL_TEXTURE_FILTER_CONTROL, texcoord_index, GL_TEXTURE_LOD_BIAS);
83         GET_INT(GL_POINT_SPRITE, texcoord_index, GL_COORD_REPLACE);
84         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_TEXTURE_ENV_MODE);
85         GET_FLOAT(GL_TEXTURE_ENV, texcoord_index, GL_TEXTURE_ENV_COLOR);
86         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_COMBINE_RGB);
87         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_COMBINE_ALPHA);
88         GET_FLOAT(GL_TEXTURE_ENV, texcoord_index, GL_RGB_SCALE);
89         GET_FLOAT(GL_TEXTURE_ENV, texcoord_index, GL_ALPHA_SCALE);
90         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC0_RGB);
91         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC1_RGB);
92         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC2_RGB);
93         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC0_ALPHA);
94         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC1_ALPHA);
95         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC2_ALPHA);
96         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND0_RGB);
97         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND1_RGB);
98         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND2_RGB);
99         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND0_ALPHA);
100         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND1_ALPHA);
101         GET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND2_ALPHA);
102
103 // TODO:
104 //{ "glGetTexEnv",      'E',    1,      "GL_SOURCE3_RGB_NV",  0x8583},
105 //{ "glGetTexEnv",      'E',    1,      "GL_SOURCE3_ALPHA_NV",  0x858B},
106 //{ "glGetTexEnv",      'E',    1,      "GL_OPERAND3_RGB_NV",  0x8593},
107 //{ "glGetTexEnv",      'E',    1,      "GL_OPERAND3_ALPHA_NV",  0x859B},
108 //{ "glGetTexEnv",      'E',    1,      "GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV",  0x86D9},
109 //{ "glGetTexEnv",      'E',    1,      "GL_SHADER_OPERATION_NV",  0x86DF},
110 //{ "glGetTexEnv",      'E',    4,      "GL_CULL_MODES_NV",  0x86E0},
111 //{ "glGetTexEnv",      'F',    4,      "GL_OFFSET_TEXTURE_MATRIX_NV",  0x86E1},
112 //{ "glGetTexEnv",      'F',    1,      "GL_OFFSET_TEXTURE_SCALE_NV",  0x86E2},
113 //{ "glGetTexEnv",      'F',    1,      "GL_OFFSET_TEXTURE_BIAS_NV",  0x86E3},
114 //{ "glGetTexEnv",      'E',    1,      "GL_PREVIOUS_TEXTURE_INPUT_NV",  0x86E4},
115 //{ "glGetTexEnv",      'F',    3,      "GL_CONST_EYE_NV",  0x86E5},
116 //{ "glGetTexEnv",      'E',    1,      "GL_BUMP_TARGET_ATI",  0x877C},
117 #undef GET_FLOAT
118 #undef GET_INT
119
120 #define GET_FLOAT(target, idx, pname)                                   \
121     do                                                                  \
122     {                                                                   \
123         float values[4] = { 0, 0, 0, 0 };                               \
124         GL_ENTRYPOINT(glGetTexGenfv)(target, pname, values);            \
125         if (vogl_check_gl_error())                                       \
126             any_gl_errors = true;                                       \
127         m_params[target].insert(pname, idx, values, sizeof(values[0])); \
128     } while (0)
129 #define GET_INT(target, idx, pname)                                     \
130     do                                                                  \
131     {                                                                   \
132         int values[4] = { 0, 0, 0, 0 };                                 \
133         GL_ENTRYPOINT(glGetTexGeniv)(target, pname, values);            \
134         if (vogl_check_gl_error())                                       \
135             any_gl_errors = true;                                       \
136         m_params[target].insert(pname, idx, values, sizeof(values[0])); \
137     } while (0)
138         GET_INT(GL_S, texcoord_index, GL_TEXTURE_GEN_MODE);
139         GET_FLOAT(GL_S, texcoord_index, GL_OBJECT_PLANE);
140         GET_FLOAT(GL_S, texcoord_index, GL_EYE_PLANE);
141
142         GET_INT(GL_T, texcoord_index, GL_TEXTURE_GEN_MODE);
143         GET_FLOAT(GL_T, texcoord_index, GL_OBJECT_PLANE);
144         GET_FLOAT(GL_T, texcoord_index, GL_EYE_PLANE);
145
146         GET_INT(GL_R, texcoord_index, GL_TEXTURE_GEN_MODE);
147         GET_FLOAT(GL_R, texcoord_index, GL_OBJECT_PLANE);
148         GET_FLOAT(GL_R, texcoord_index, GL_EYE_PLANE);
149
150         GET_INT(GL_Q, texcoord_index, GL_TEXTURE_GEN_MODE);
151         GET_FLOAT(GL_Q, texcoord_index, GL_OBJECT_PLANE);
152         GET_FLOAT(GL_Q, texcoord_index, GL_EYE_PLANE);
153 #undef GET_DBL
154 #undef GET_INT
155     }
156
157     if (vogl_check_gl_error())
158         any_gl_errors = true;
159
160     if (any_gl_errors)
161     {
162         clear();
163
164         vogl_error_printf("%s: GL error while enumerating texenv/texgen params\n", VOGL_METHOD_NAME);
165
166         return false;
167     }
168
169     m_valid = true;
170
171     return true;
172 }
173
174 bool vogl_texenv_state::set_texenv_parameter(GLenum target, uint index, GLenum pname) const
175 {
176     VOGL_FUNC_TRACER
177
178     const vogl_state_vector *pState_vec = m_params.find_value(target);
179     if (!pState_vec)
180         return false;
181
182     const vogl_state_data *pData = pState_vec->find(pname, index);
183     if (!pData)
184         return false;
185
186     enum
187     {
188         cMaxElements = 4
189     };
190     if (pData->get_num_elements() > cMaxElements)
191     {
192         VOGL_ASSERT_ALWAYS;
193         return false;
194     }
195
196     if ((pData->get_data_type() == cSTFloat) || (pData->get_data_type() == cSTDouble))
197     {
198         float fvals[cMaxElements];
199         pData->get_float(fvals);
200         if (pData->get_num_elements() == 1)
201             GL_ENTRYPOINT(glTexEnvf)(target, pname, fvals[0]);
202         else
203             GL_ENTRYPOINT(glTexEnvfv)(target, pname, fvals);
204     }
205     else
206     {
207         int ivals[cMaxElements];
208         pData->get_int(ivals);
209         if (pData->get_num_elements() == 1)
210             GL_ENTRYPOINT(glTexEnvi)(target, pname, ivals[0]);
211         else
212             GL_ENTRYPOINT(glTexEnviv)(target, pname, ivals);
213     }
214
215     return !vogl_check_gl_error();
216 }
217
218 bool vogl_texenv_state::set_texgen_parameter(GLenum coord, uint index, GLenum pname) const
219 {
220     VOGL_FUNC_TRACER
221
222     const vogl_state_vector *pState_vec = m_params.find_value(coord);
223     if (!pState_vec)
224         return false;
225
226     const vogl_state_data *pData = pState_vec->find(pname, index);
227     if (!pData)
228         return false;
229
230     enum
231     {
232         cMaxElements = 4
233     };
234     if (pData->get_num_elements() > cMaxElements)
235     {
236         VOGL_ASSERT_ALWAYS;
237         return false;
238     }
239
240     if ((pData->get_data_type() == cSTFloat) || (pData->get_data_type() == cSTDouble))
241     {
242         float fvals[cMaxElements];
243         pData->get_float(fvals);
244         if (pData->get_num_elements() == 1)
245             GL_ENTRYPOINT(glTexGenf)(coord, pname, fvals[0]);
246         else
247             GL_ENTRYPOINT(glTexGenfv)(coord, pname, fvals);
248     }
249     else
250     {
251         int ivals[cMaxElements];
252         pData->get_int(ivals);
253         if (pData->get_num_elements() == 1)
254             GL_ENTRYPOINT(glTexGeni)(coord, pname, ivals[0]);
255         else
256             GL_ENTRYPOINT(glTexGeniv)(coord, pname, ivals);
257     }
258
259     return !vogl_check_gl_error();
260 }
261
262 bool vogl_texenv_state::restore(const vogl_context_info &context_info) const
263 {
264     VOGL_FUNC_TRACER
265
266     if (!m_valid)
267     {
268         VOGL_ASSERT_ALWAYS;
269         return false;
270     }
271
272     VOGL_CHECK_GL_ERROR;
273
274     vogl_scoped_state_saver state_saver(cGSTActiveTexture, cGSTMatrixMode);
275
276     // So we can set the texgen GL_EYE_PLANE matrix without it getting transformed.
277     GL_ENTRYPOINT(glMatrixMode)(GL_MODELVIEW);
278     GL_ENTRYPOINT(glPushMatrix)();
279     GL_ENTRYPOINT(glLoadIdentity)();
280
281     bool any_gl_errors = false;
282     if (vogl_check_gl_error())
283         any_gl_errors = true;
284
285     for (uint texcoord_index = 0; texcoord_index < context_info.get_max_texture_coords(); texcoord_index++)
286     {
287         GL_ENTRYPOINT(glActiveTexture)(GL_TEXTURE0 + texcoord_index);
288
289         if (vogl_check_gl_error())
290             any_gl_errors = true;
291
292 #define SET_FLOAT(target, idx, pname) set_texenv_parameter(target, idx, pname);
293 #define SET_INT(target, idx, pname) set_texenv_parameter(target, idx, pname);
294
295         SET_FLOAT(GL_TEXTURE_FILTER_CONTROL, texcoord_index, GL_TEXTURE_LOD_BIAS);
296         SET_INT(GL_POINT_SPRITE, texcoord_index, GL_COORD_REPLACE);
297         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_TEXTURE_ENV_MODE);
298         SET_FLOAT(GL_TEXTURE_ENV, texcoord_index, GL_TEXTURE_ENV_COLOR);
299         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_COMBINE_RGB);
300         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_COMBINE_ALPHA);
301         SET_FLOAT(GL_TEXTURE_ENV, texcoord_index, GL_RGB_SCALE);
302         SET_FLOAT(GL_TEXTURE_ENV, texcoord_index, GL_ALPHA_SCALE);
303
304         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC0_RGB);
305         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC1_RGB);
306         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC2_RGB);
307         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC0_ALPHA);
308         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC1_ALPHA);
309         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_SRC2_ALPHA);
310
311         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND0_RGB);
312         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND1_RGB);
313         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND2_RGB);
314         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND0_ALPHA);
315         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND1_ALPHA);
316         SET_INT(GL_TEXTURE_ENV, texcoord_index, GL_OPERAND2_ALPHA);
317
318 #undef SET_FLOAT
319 #undef SET_INT
320
321         if (vogl_check_gl_error())
322             any_gl_errors = true;
323
324 #define SET_DBL(target, idx, pname) set_texgen_parameter(target, idx, pname);
325 #define SET_INT(target, idx, pname) set_texgen_parameter(target, idx, pname);
326
327         SET_INT(GL_S, texcoord_index, GL_TEXTURE_GEN_MODE);
328         SET_DBL(GL_S, texcoord_index, GL_OBJECT_PLANE);
329         SET_DBL(GL_S, texcoord_index, GL_EYE_PLANE);
330
331         SET_INT(GL_T, texcoord_index, GL_TEXTURE_GEN_MODE);
332         SET_DBL(GL_T, texcoord_index, GL_OBJECT_PLANE);
333         SET_DBL(GL_T, texcoord_index, GL_EYE_PLANE);
334
335         SET_INT(GL_R, texcoord_index, GL_TEXTURE_GEN_MODE);
336         SET_DBL(GL_R, texcoord_index, GL_OBJECT_PLANE);
337         SET_DBL(GL_R, texcoord_index, GL_EYE_PLANE);
338
339         SET_INT(GL_Q, texcoord_index, GL_TEXTURE_GEN_MODE);
340         SET_DBL(GL_Q, texcoord_index, GL_OBJECT_PLANE);
341         SET_DBL(GL_Q, texcoord_index, GL_EYE_PLANE);
342
343 #undef SET_DBL
344 #undef SET_INT
345
346         if (vogl_check_gl_error())
347             any_gl_errors = true;
348     }
349
350     GL_ENTRYPOINT(glPopMatrix)();
351
352     if (vogl_check_gl_error())
353         any_gl_errors = true;
354
355     return !any_gl_errors;
356 }
357
358 void vogl_texenv_state::clear()
359 {
360     VOGL_FUNC_TRACER
361
362     m_params.clear();
363     m_valid = false;
364 }
365
366 bool vogl_texenv_state::serialize(json_node &node, vogl_blob_manager &blob_manager) const
367 {
368     VOGL_FUNC_TRACER
369
370     if (!m_valid)
371     {
372         VOGL_ASSERT_ALWAYS;
373         return false;
374     }
375
376     for (texenv_map::const_iterator it = m_params.begin(); it != m_params.end(); ++it)
377         if (!it->second.serialize(node.add_object(g_gl_enums.find_gl_name(it->first)), blob_manager))
378             return false;
379
380     return true;
381 }
382
383 bool vogl_texenv_state::deserialize(const json_node &node, const vogl_blob_manager &blob_manager)
384 {
385     VOGL_FUNC_TRACER
386
387     clear();
388
389     if (!node.is_object() || !node.are_all_children_objects_or_arrays())
390         return false;
391
392     for (uint i = 0; i < node.size(); i++)
393     {
394         const dynamic_string &name = node.get_key(i);
395         uint64_t enum_val = g_gl_enums.find_enum(name);
396         if (enum_val == gl_enums::cUnknownEnum)
397             return false;
398
399         if (!m_params[static_cast<GLenum>(enum_val)].deserialize(*node.get_child(i), blob_manager))
400             return false;
401     }
402
403     m_valid = true;
404
405     return true;
406 }
407
408 const vogl_state_vector &vogl_texenv_state::get_state(GLenum target) const
409 {
410     texenv_map::const_iterator iter = m_params.find(target);
411     VOGL_ASSERT(iter != m_params.end());
412
413     return iter->second;
414 }