1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 **************************************************************************/
26 // File: vogl_texenv_state.cpp
27 #include "vogl_texenv_state.h"
29 vogl_texenv_state::vogl_texenv_state()
35 vogl_texenv_state::~vogl_texenv_state()
40 bool vogl_texenv_state::snapshot(const vogl_context_info &context_info)
48 bool any_gl_errors = false;
52 vogl_scoped_state_saver state_saver(cGSTActiveTexture);
54 if (vogl_check_gl_error())
57 for (uint texcoord_index = 0; texcoord_index < context_info.get_max_texture_coords(); texcoord_index++)
59 GL_ENTRYPOINT(glActiveTexture)(GL_TEXTURE0 + texcoord_index);
61 if (vogl_check_gl_error())
64 #define GET_FLOAT(target, idx, pname) \
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])); \
73 #define GET_INT(target, idx, pname) \
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])); \
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);
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},
120 #define GET_FLOAT(target, idx, pname) \
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])); \
129 #define GET_INT(target, idx, pname) \
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])); \
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);
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);
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);
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);
157 if (vogl_check_gl_error())
158 any_gl_errors = true;
164 vogl_error_printf("%s: GL error while enumerating texenv/texgen params\n", VOGL_METHOD_NAME);
174 bool vogl_texenv_state::set_texenv_parameter(GLenum target, uint index, GLenum pname) const
178 const vogl_state_vector *pState_vec = m_params.find_value(target);
182 const vogl_state_data *pData = pState_vec->find(pname, index);
190 if (pData->get_num_elements() > cMaxElements)
196 if ((pData->get_data_type() == cSTFloat) || (pData->get_data_type() == cSTDouble))
198 float fvals[cMaxElements];
199 pData->get_float(fvals);
200 if (pData->get_num_elements() == 1)
201 GL_ENTRYPOINT(glTexEnvf)(target, pname, fvals[0]);
203 GL_ENTRYPOINT(glTexEnvfv)(target, pname, fvals);
207 int ivals[cMaxElements];
208 pData->get_int(ivals);
209 if (pData->get_num_elements() == 1)
210 GL_ENTRYPOINT(glTexEnvi)(target, pname, ivals[0]);
212 GL_ENTRYPOINT(glTexEnviv)(target, pname, ivals);
215 return !vogl_check_gl_error();
218 bool vogl_texenv_state::set_texgen_parameter(GLenum coord, uint index, GLenum pname) const
222 const vogl_state_vector *pState_vec = m_params.find_value(coord);
226 const vogl_state_data *pData = pState_vec->find(pname, index);
234 if (pData->get_num_elements() > cMaxElements)
240 if ((pData->get_data_type() == cSTFloat) || (pData->get_data_type() == cSTDouble))
242 float fvals[cMaxElements];
243 pData->get_float(fvals);
244 if (pData->get_num_elements() == 1)
245 GL_ENTRYPOINT(glTexGenf)(coord, pname, fvals[0]);
247 GL_ENTRYPOINT(glTexGenfv)(coord, pname, fvals);
251 int ivals[cMaxElements];
252 pData->get_int(ivals);
253 if (pData->get_num_elements() == 1)
254 GL_ENTRYPOINT(glTexGeni)(coord, pname, ivals[0]);
256 GL_ENTRYPOINT(glTexGeniv)(coord, pname, ivals);
259 return !vogl_check_gl_error();
262 bool vogl_texenv_state::restore(const vogl_context_info &context_info) const
274 vogl_scoped_state_saver state_saver(cGSTActiveTexture, cGSTMatrixMode);
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)();
281 bool any_gl_errors = false;
282 if (vogl_check_gl_error())
283 any_gl_errors = true;
285 for (uint texcoord_index = 0; texcoord_index < context_info.get_max_texture_coords(); texcoord_index++)
287 GL_ENTRYPOINT(glActiveTexture)(GL_TEXTURE0 + texcoord_index);
289 if (vogl_check_gl_error())
290 any_gl_errors = true;
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);
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);
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);
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);
321 if (vogl_check_gl_error())
322 any_gl_errors = true;
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);
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);
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);
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);
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);
346 if (vogl_check_gl_error())
347 any_gl_errors = true;
350 GL_ENTRYPOINT(glPopMatrix)();
352 if (vogl_check_gl_error())
353 any_gl_errors = true;
355 return !any_gl_errors;
358 void vogl_texenv_state::clear()
366 bool vogl_texenv_state::serialize(json_node &node, vogl_blob_manager &blob_manager) const
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))
383 bool vogl_texenv_state::deserialize(const json_node &node, const vogl_blob_manager &blob_manager)
389 if (!node.is_object() || !node.are_all_children_objects_or_arrays())
392 for (uint i = 0; i < node.size(); i++)
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)
399 if (!m_params[static_cast<GLenum>(enum_val)].deserialize(*node.get_child(i), blob_manager))
408 const vogl_state_vector &vogl_texenv_state::get_state(GLenum target) const
410 texenv_map::const_iterator iter = m_params.find(target);
411 VOGL_ASSERT(iter != m_params.end());