00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "glut-state.h"
00036
00037 #include "perf/perf.h"
00038
00039
00040 namespace glut {
00041
00042
00043
00044 State::~State(void) throw() { }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 class StateImpl : public State {
00059 public:
00060
00061 ~StateImpl(void) throw() { }
00062 StateImpl(void) throw() { }
00063
00064
00065 void snapshotFromOpenGL(void);
00066
00067
00068 void dump(IN const char * msg) const throw();
00069 void diff(IN const State * other) const throw();
00070
00071 private:
00072
00073 enum eType {
00074 eType_Bool = 1,
00075 eType_Int = 2,
00076 eType_Float = 3,
00077 eType_Double = 4,
00078
00079
00080 eType_Invalid = 0
00081 };
00082
00083 struct value_t {
00084 value_t(void) throw() { this->clear(); }
00085 void clear(void) throw() {
00086 type = eType_Invalid;
00087 count = 0;
00088 }
00089
00090 const char * getTypeString(void) const throw() {
00091 switch (type) {
00092 case eType_Bool: return "Boolean";
00093 case eType_Int: return "Integer";
00094 case eType_Float: return "Float";
00095 case eType_Double: return "Double";
00096 default:
00097 ASSERT(false, "bad type: %d", type);
00098 }
00099 return NULL;
00100 }
00101
00102 char * addValueToString(IN char * buffer,
00103 IN int index) const throw() {
00104 ASSERT(index >= 0 && index <= 3,
00105 "bad index: %d", index);
00106
00107 if (index >= count) {
00108
00109 return buffer;
00110 }
00111
00112 switch (type) {
00113 case eType_Bool: sprintf(buffer, " %s", bVal[index] ? "true" : "false"); break;
00114 case eType_Int: sprintf(buffer, " %d", iVal[index]); break;
00115 case eType_Float: sprintf(buffer, " %f", fVal[index]); break;
00116 case eType_Double: sprintf(buffer, " %lf", dVal[index]); break;
00117 default: ASSERT(false, "bad type: %d", type);
00118 }
00119
00120 int len = strlen(buffer);
00121 return buffer + len;
00122 }
00123
00124 const char * getValueString(IN char * buffer) const throw() {
00125 ASSERT(buffer, "null");
00126 char * p = buffer;
00127 for (int i = 0; i < count; ++i) {
00128 p = this->addValueToString(p, i);
00129 }
00130 *p = 0;
00131 return buffer;
00132 }
00133
00134 void dump(IN const char * txt) const throw() {
00135 char buffer[256];
00136
00137 DPRINTF("%-19s %7s[%d] =%s", txt,
00138 this->getTypeString(), count,
00139 this->getValueString(buffer));
00140 }
00141
00142 eType type;
00143 int count;
00144 union {
00145 int iVal[4];
00146 float fVal[4];
00147 GLboolean bVal[4];
00148 double dVal[4];
00149 };
00150 };
00151
00152 typedef std::map<std::string, value_t> value_map_t;
00153
00154
00155 void verifyFields(IN const StateImpl * p) const throw();
00156 void addLightFields(IN int light);
00157 void getMatrixTrace(IN int matrix);
00158
00159
00160 value_map_t m_values;
00161 };
00162
00163
00164 #define GET_INTEGER(flag, valCount) \
00165 { \
00166 value_t v; \
00167 v.type = eType_Int; \
00168 v.count = valCount; \
00169 ASSERT(valCount > 0 && valCount < 5, \
00170 "Bad count for OpenGL int: %d", valCount); \
00171 glGetIntegerv( flag , v.iVal ); \
00172 m_values[ #flag ] = v; \
00173 }
00174
00175 #define GET_LIGHTF(light, flag, valCount) \
00176 { \
00177 value_t v; \
00178 v.type = eType_Float; \
00179 v.count = valCount; \
00180 ASSERT(valCount > 0 && valCount < 5, \
00181 "Bad count for OpenGL light float: %d", valCount); \
00182 glGetLightfv( light , flag , v.fVal ); \
00183 char buffer[64]; \
00184 buffer[0] = '0' + light - GL_LIGHT0; \
00185 buffer[1] = ':'; \
00186 strcpy(buffer + 2, #flag ); \
00187 m_values[ buffer ] = v; \
00188 }
00189
00190 #define GET_FLOAT(flag, valCount) \
00191 { \
00192 value_t v; \
00193 v.type = eType_Float; \
00194 v.count = valCount; \
00195 ASSERT(valCount > 0 && valCount < 5, \
00196 "Bad count for OpenGL int: %d", valCount); \
00197 glGetFloatv( flag , v.fVal ); \
00198 m_values[ #flag ] = v; \
00199 }
00200
00201 #define GET_BOOL(flag, valCount) \
00202 { \
00203 value_t v; \
00204 v.type = eType_Bool; \
00205 v.count = valCount; \
00206 ASSERT(valCount > 0 && valCount < 5, \
00207 "Bad count for OpenGL int: %d", valCount); \
00208 glGetBooleanv( flag , v.bVal ); \
00209 m_values[ #flag ] = v; \
00210 }
00211
00212 #define GET_TEXTUREI(flag, valCount) \
00213 { \
00214 value_t v; \
00215 v.type = eType_Int; \
00216 v.count = valCount; \
00217 ASSERT(valCount > 0 && valCount < 5, \
00218 "Bad count for OpenGL int: %d", valCount); \
00219 glGetTexParameteriv(GL_TEXTURE_2D, flag , v.iVal ); \
00220 m_values[ #flag ] = v; \
00221 }
00222
00223 #define GET_MATERIALF(flag, valCount) \
00224 { \
00225 value_t v; \
00226 v.type = eType_Float; \
00227 v.count = valCount; \
00228 ASSERT(valCount > 0 && valCount < 5, \
00229 "Bad count for OpenGL float: %d", valCount); \
00230 glGetMaterialfv(GL_FRONT, flag , v.fVal ); \
00231 m_values[ "getMaterial_" #flag ] = v; \
00232 }
00233
00234 #define GET_TEXENVI(flag, valCount) \
00235 { \
00236 value_t v; \
00237 v.type = eType_Int; \
00238 v.count = valCount; \
00239 ASSERT(valCount > 0 && valCount < 5, \
00240 "Bad count for openGl Int: %d", valCount); \
00241 glGetTexEnviv(GL_TEXTURE_ENV, flag , v.iVal ); \
00242 m_values[ #flag ] = v; \
00243 }
00244
00245 void
00246 StateImpl::addLightFields
00247 (
00248 IN int light
00249 )
00250 {
00251 ASSERT(light >= GL_LIGHT0 && light <= GL_LIGHT7,
00252 "Bad GL light enum: %d", light);
00253
00254 GET_LIGHTF( light, GL_AMBIENT, 4);
00255 GET_LIGHTF( light, GL_DIFFUSE, 4);
00256 GET_LIGHTF( light, GL_SPECULAR, 4);
00257 GET_LIGHTF( light, GL_POSITION, 4);
00258 GET_LIGHTF( light, GL_SPOT_DIRECTION, 3);
00259 GET_LIGHTF( light, GL_SPOT_CUTOFF, 1);
00260 }
00261
00262
00263
00264 void
00265 StateImpl::getMatrixTrace
00266 (
00267 IN int matrix
00268 )
00269 {
00270 float m[16];
00271 glGetFloatv(matrix, m);
00272
00273 float trace = 0.0;
00274 for (int i = 0; i < 3; ++i) {
00275 int idx = 5 * i;
00276 trace += m[idx];
00277 }
00278
00279 char buffer[32];
00280 sprintf(buffer, "MATRIX_TRACE_%d", matrix);
00281
00282 value_t v;
00283 v.type = eType_Float;
00284 v.count = 1;
00285 v.fVal[0] = trace;
00286
00287 m_values[buffer] = v;
00288
00289
00290 DPRINTF("Matrix %d", matrix);
00291 const float * p = m;
00292 for (int i = 0; i < 4; ++i, p += 4) {
00293 DPRINTF(" %5.2f %5.2f %5.2f %5.2f",
00294 p[0], p[1], p[2], p[3]);
00295 }
00296 }
00297
00298
00299
00300 void
00301 StateImpl::snapshotFromOpenGL
00302 (
00303 void
00304 )
00305 {
00306
00307
00308 GET_INTEGER( GL_ALPHA_BITS, 1);
00309 GET_FLOAT( GL_ALPHA_SCALE, 1);
00310 GET_BOOL( GL_ALPHA_TEST, 1);
00311 GET_INTEGER( GL_ALPHA_TEST_FUNC, 1);
00312 GET_FLOAT( GL_ALPHA_TEST_REF, 1);
00313 GET_INTEGER( GL_AUX_BUFFERS, 1);
00314 GET_BOOL( GL_BLEND, 1);
00315 GET_FLOAT( GL_BLEND_COLOR, 4);
00316 GET_INTEGER( GL_BLEND_DST, 1);
00317 GET_INTEGER( GL_BLEND_EQUATION, 1);
00318 GET_INTEGER( GL_BLEND_SRC, 1);
00319 GET_INTEGER( GL_BLUE_BITS, 1);
00320 GET_BOOL( GL_CLIP_PLANE0, 1);
00321 GET_BOOL( GL_CLIP_PLANE1, 1);
00322 GET_BOOL( GL_CLIP_PLANE2, 1);
00323 GET_BOOL( GL_CLIP_PLANE3, 1);
00324 GET_BOOL( GL_COLOR_ARRAY, 1);
00325 GET_INTEGER( GL_COLOR_ARRAY_SIZE, 1);
00326 GET_FLOAT( GL_COLOR_CLEAR_VALUE, 4);
00327 GET_INTEGER( GL_COLOR_LOGIC_OP, 1);
00328 GET_BOOL( GL_COLOR_MATERIAL, 1);
00329 GET_INTEGER( GL_COLOR_MATERIAL_FACE, 1);
00330 GET_INTEGER( GL_COLOR_MATERIAL_PARAMETER, 1);
00331 GET_INTEGER( GL_COLOR_WRITEMASK, 4);
00332 GET_BOOL( GL_CULL_FACE, 1);
00333 GET_INTEGER( GL_CULL_FACE_MODE, 1);
00334 GET_FLOAT( GL_CURRENT_COLOR, 4);
00335 GET_FLOAT( GL_CURRENT_NORMAL, 3);
00336 GET_INTEGER( GL_DEPTH_BITS, 1);
00337 GET_BOOL( GL_DOUBLEBUFFER, 1);
00338 GET_INTEGER( GL_DRAW_BUFFER, 1);
00339 GET_BOOL( GL_FOG, 1);
00340 GET_FLOAT( GL_FOG_COLOR, 4);
00341 GET_INTEGER( GL_FRONT_FACE, 1);
00342 GET_INTEGER( GL_GREEN_BITS, 1);
00343 GET_BOOL( GL_LIGHT0, 1);
00344 GET_BOOL( GL_LIGHT1, 1);
00345 GET_BOOL( GL_LIGHT2, 1);
00346 GET_BOOL( GL_LIGHT3, 1);
00347 GET_BOOL( GL_LIGHT4, 1);
00348 GET_BOOL( GL_LIGHT5, 1);
00349 GET_BOOL( GL_LIGHT6, 1);
00350 GET_BOOL( GL_LIGHT7, 1);
00351 GET_BOOL( GL_LIGHTING, 1);
00352 GET_FLOAT( GL_LIGHT_MODEL_AMBIENT, 4);
00353 GET_INTEGER( GL_LOGIC_OP_MODE, 1);
00354 GET_INTEGER( GL_POLYGON_MODE, 1);
00355 GET_INTEGER( GL_POLYGON_OFFSET_FACTOR, 1);
00356 GET_INTEGER( GL_POLYGON_OFFSET_UNITS, 1);
00357 GET_BOOL( GL_POLYGON_OFFSET_FILL, 1);
00358 GET_BOOL( GL_POLYGON_OFFSET_LINE, 1);
00359 GET_BOOL( GL_POLYGON_OFFSET_POINT, 1);
00360 GET_BOOL( GL_POLYGON_SMOOTH, 1);
00361 GET_INTEGER( GL_PROJECTION_STACK_DEPTH, 1);
00362 GET_INTEGER( GL_RED_BITS, 1);
00363 GET_BOOL( GL_RGBA_MODE, 1);
00364 GET_INTEGER( GL_STENCIL_BITS, 1);
00365 GET_BOOL( GL_TEXTURE_2D, 1);
00366 GET_INTEGER( GL_TEXTURE_BINDING_2D, 1);
00367 GET_INTEGER( GL_VIEWPORT, 4);
00368
00369
00370 GET_TEXTUREI( GL_TEXTURE_MAG_FILTER, 1);
00371 GET_TEXTUREI( GL_TEXTURE_MIN_FILTER, 1);
00372 GET_TEXTUREI( GL_TEXTURE_MIN_LOD, 1);
00373 GET_TEXTUREI( GL_TEXTURE_MAX_LOD, 1);
00374 GET_TEXTUREI( GL_TEXTURE_BASE_LEVEL, 1);
00375 GET_TEXTUREI( GL_TEXTURE_MAX_LEVEL, 1);
00376 GET_TEXTUREI( GL_TEXTURE_WRAP_S, 1);
00377 GET_TEXTUREI( GL_TEXTURE_WRAP_T, 1);
00378 GET_TEXTUREI( GL_TEXTURE_WRAP_R, 1);
00379
00380 GET_TEXENVI( GL_TEXTURE_ENV_MODE, 1);
00381
00382
00383 GET_MATERIALF( GL_AMBIENT, 4);
00384 GET_MATERIALF( GL_DIFFUSE, 4);
00385 GET_MATERIALF( GL_SPECULAR, 4);
00386 GET_MATERIALF( GL_EMISSION, 4);
00387 GET_MATERIALF( GL_SHININESS, 1);
00388
00389
00390 this->getMatrixTrace(GL_MODELVIEW_MATRIX);
00391 this->getMatrixTrace(GL_PROJECTION_MATRIX);
00392 this->getMatrixTrace(GL_TEXTURE_MATRIX);
00393
00394
00395 this->addLightFields(GL_LIGHT0);
00396 this->addLightFields(GL_LIGHT1);
00397 this->addLightFields(GL_LIGHT2);
00398 this->addLightFields(GL_LIGHT3);
00399 this->addLightFields(GL_LIGHT4);
00400 }
00401
00402
00403
00404 void
00405 StateImpl::dump
00406 (
00407 IN const char * msg
00408 )
00409 const
00410 throw()
00411 {
00412 DPRINTF("%s: OpenGL State BEGIN --------------------------", msg);
00413
00414 for (value_map_t::const_iterator i = m_values.begin();
00415 i != m_values.end(); ++i) {
00416 const char * name = i->first.c_str();
00417 const value_t& v = i->second;
00418 v.dump(name);
00419 }
00420
00421 DPRINTF("%s: OpenGL State END ----------------------------", msg);
00422 }
00423
00424
00425
00426 void
00427 StateImpl::diff
00428 (
00429 IN const State * other
00430 )
00431 const
00432 throw()
00433 {
00434 ASSERT(other, "null");
00435 const StateImpl * p = dynamic_cast<const StateImpl*>(other);
00436 ASSERT(p, "other state object is not a StateImpl?");
00437
00438
00439 this->verifyFields(p);
00440
00441
00442
00443
00444 }
00445
00446
00447
00448 void
00449 StateImpl::verifyFields
00450 (
00451 IN const StateImpl * p
00452 )
00453 const
00454 throw()
00455 {
00456 ASSERT(p, "null");
00457
00458
00459 for (value_map_t::const_iterator i = m_values.begin();
00460 i != m_values.end(); ++i) {
00461 const char * name = i->first.c_str();
00462
00463
00464 value_map_t::const_iterator j = p->m_values.find(name);
00465 if (p->m_values.end() == j) {
00466 DPRINTF(" Missing a field! %s", name);
00467 continue;
00468 }
00469
00470 char buffer0[256];
00471 char buffer1[256];
00472 const value_t& v0 = i->second;
00473 const value_t& v1 = j->second;
00474
00475 v0.getValueString(buffer0);
00476 v1.getValueString(buffer1);
00477 if (strcmp(buffer0, buffer1)) {
00478 DPRINTF("%s: disagreement in values!", name);
00479 DPRINTF(" Type: %s[%d]", v0.getTypeString(), v0.count);
00480 DPRINTF(" our value: %s", buffer0);
00481 DPRINTF(" other value: %s", buffer1);
00482 }
00483 }
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 smart_ptr<State>
00495 State::snapshotFromOpenGL
00496 (
00497 void
00498 )
00499 {
00500 smart_ptr<StateImpl> local = new StateImpl;
00501 ASSERT(local, "out of memory");
00502
00503 local->snapshotFromOpenGL();
00504
00505 return local;
00506 }
00507
00508
00509
00510
00511 };
00512