Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/crgsg/crGraphicsStateGuardian.cxx

Go to the documentation of this file.
00001 // Filename: chromium.GraphicsStateGuardian.cxx
00002 // Created by:  drose (02Feb99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "crGraphicsStateGuardian.h"
00020 #include "crSavedFrameBuffer.h"
00021 #include "crTextureContext.h"
00022 #include "crGeomNodeContext.h"
00023 #include "config_crgsg.h"
00024 
00025 #include "config_util.h"
00026 #include "directRenderTraverser.h"
00027 #include "cullTraverser.h"
00028 #include "displayRegion.h"
00029 #include "lensNode.h"
00030 #include "camera.h"
00031 #include "renderBuffer.h"
00032 #include "geom.h"
00033 #include "geomIssuer.h"
00034 #include "graphicsWindow.h"
00035 #include "graphicsChannel.h"
00036 #include "lens.h"
00037 #include "get_rel_pos.h"
00038 #include "perspectiveLens.h"
00039 #include "directionalLight.h"
00040 #include "pointLight.h"
00041 #include "spotlight.h"
00042 #include "GL/glu.h"
00043 #include "lensNode.h"
00044 #include "textureAttrib.h"
00045 #include "lightAttrib.h"
00046 #include "cullFaceAttrib.h"
00047 #include "transparencyAttrib.h"
00048 #include "depthTestAttrib.h"
00049 #include "depthWriteAttrib.h"
00050 #include "colorWriteAttrib.h"
00051 #include "texMatrixAttrib.h"
00052 #include "materialAttrib.h"
00053 #include "renderModeAttrib.h"
00054 #include "fogAttrib.h"
00055 #include "depthOffsetAttrib.h"
00056 #include "fog.h"
00057 #include "clockObject.h"
00058 #include "string_utils.h"
00059 #include "nodePath.h"
00060 #include "dcast.h"
00061 #include "pvector.h"
00062 
00063 #ifdef DO_PSTATS
00064 #include "pStatTimer.h"
00065 #endif
00066 
00067 #include <algorithm>
00068 
00069 #if 0
00070 #define chromium.GenTextures chromium.GenTexturesEXT
00071 #define chromium.PrioritizeTextures chromium.PrioritizeTexturesEXT
00072 #define chromium.BindTexture chromium.BindTextureEXT
00073 #define chromium.CopyTexImage2D chromium.CopyTexImage2DEXT
00074 #define chromium.DeleteTextures chromium.DeleteTexturesEXT
00075 #endif
00076 
00077 #if !defined(GL_BGR) && defined(GL_BGR_EXT)
00078 // These symbols are sometimes defined as _EXT variants.
00079 #define GL_BGR GL_BGR_EXT
00080 #define GL_BGRA GL_BGRA_EXT
00081 #endif
00082 
00083 TypeHandle CRGraphicsStateGuardian::_type_handle;
00084 SPUDispatchTable chromium;
00085 
00086 #if !defined(CPPPARSER) && defined(DO_PSTATS)
00087 PStatCollector CRGraphicsStateGuardian::_vertices_display_list_pcollector("Vertices:Display lists");
00088 #endif
00089 
00090 static void
00091 issue_vertex_gl(const Geom *geom, Geom::VertexIterator &viterator, 
00092                 GraphicsStateGuardianBase *) {
00093   const Vertexf &vertex = geom->get_next_vertex(viterator);
00094   // crgsg_cat.debug() << "Issuing vertex " << vertex << "\n";
00095   chromium.Vertex3fv(vertex.get_data());
00096 }
00097 
00098 static void
00099 issue_normal_gl(const Geom *geom, Geom::NormalIterator &niterator, 
00100                 GraphicsStateGuardianBase *) {
00101   const Normalf &normal = geom->get_next_normal(niterator);
00102   // crgsg_cat.debug() << "Issuing normal " << normal << "\n";
00103   chromium.Normal3fv(normal.get_data());
00104 }
00105 
00106 static void
00107 issue_texcoord_gl(const Geom *geom, Geom::TexCoordIterator &tciterator, 
00108                 GraphicsStateGuardianBase *) {
00109   const TexCoordf &texcoord = geom->get_next_texcoord(tciterator);
00110   //  crgsg_cat.debug() << "Issuing texcoord " << texcoord << "\n";
00111   chromium.TexCoord2fv(texcoord.get_data());
00112 }
00113 
00114 static void
00115 issue_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
00116                GraphicsStateGuardianBase *) {
00117   const Colorf &color = geom->get_next_color(citerator);
00118   //  crgsg_cat.debug() << "Issuing color " << color << "\n";
00119   chromium.Color4fv(color.get_data());
00120 }
00121 
00122 static void
00123 issue_transformed_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
00124                            GraphicsStateGuardianBase *gsg) {
00125   const CRGraphicsStateGuardian *crgsg = DCAST(CRGraphicsStateGuardian, gsg);
00126   const Colorf &color = geom->get_next_color(citerator);
00127   crgsg->issue_transformed_color(color);
00128 }
00129 
00130 ////////////////////////////////////////////////////////////////////
00131 //     Function: CRGraphicsStateGuardian::Constructor
00132 //       Access: Public
00133 //  Description:
00134 ////////////////////////////////////////////////////////////////////
00135 CRGraphicsStateGuardian::
00136 CRGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) {
00137   _clip_plane_enabled = (bool *)NULL;
00138   _cur_clip_plane_enabled = (bool *)NULL;
00139 
00140   // Create a default RenderTraverser.
00141   if (cr_cull_traversal) {
00142     _render_traverser =
00143       new CullTraverser(this, RenderRelation::get_class_type());
00144   } else {
00145     _render_traverser =
00146       new DirectRenderTraverser(this, RenderRelation::get_class_type());
00147   }
00148 
00149   reset();
00150 }
00151 
00152 ////////////////////////////////////////////////////////////////////
00153 //     Function: CRGraphicsStateGuardian::Destructor
00154 //       Access: Public
00155 //  Description:
00156 ////////////////////////////////////////////////////////////////////
00157 CRGraphicsStateGuardian::
00158 ~CRGraphicsStateGuardian() {
00159   free_pointers();
00160   release_all_textures();
00161   release_all_geoms();
00162 }
00163 
00164 ////////////////////////////////////////////////////////////////////
00165 //     Function: CRGraphicsStateGuardian::reset
00166 //       Access: Public, Virtual
00167 //  Description: Resets all internal state as if the gsg were newly
00168 //               created.
00169 ////////////////////////////////////////////////////////////////////
00170 void CRGraphicsStateGuardian::
00171 reset() {
00172   free_pointers();
00173   activate();
00174   GraphicsStateGuardian::reset();
00175 
00176   _buffer_mask = 0;
00177 
00178   // All GL implementations have the following buffers. (?)
00179   _buffer_mask = (RenderBuffer::T_color |
00180                   RenderBuffer::T_depth |
00181                   RenderBuffer::T_stencil |
00182                   RenderBuffer::T_accum);
00183 
00184   // Check to see if we have double-buffering.
00185   GLboolean has_back;
00186   chromium.GetBooleanv(GL_DOUBLEBUFFER, &has_back);
00187   if (!has_back) {
00188     _buffer_mask &= ~RenderBuffer::T_back;
00189   }
00190 
00191 #if 0
00192   //Note 8/01: This is incorrect for mono displays, if stereo is not in use, we need
00193   //           to use the GL_BACK constants and not the GL_BACK_LEFT ones, which
00194   //           under the RenderBuffer flag schemes require both left and right flags set.
00195 
00196   // Check to see if we have stereo (and therefore a right buffer).
00197   GLboolean has_stereo;
00198   chromium.GetBooleanv(GL_STEREO, &has_stereo);
00199   if (!has_stereo) {
00200     _buffer_mask &= ~RenderBuffer::T_right;
00201   }
00202 #endif
00203 
00204   // Set up our clear values to invalid values, so the chromium.Clear* calls
00205   // will be made initially.
00206   _clear_color_red = -1.0f;
00207   _clear_color_green = -1.0f;
00208   _clear_color_blue = -1.0f;
00209   _clear_color_alpha = -1.0f;
00210   _clear_depth = -1.0f;
00211   _clear_stencil = -1;
00212   _clear_accum_red = -1.0f;
00213   _clear_accum_green = -1.0f;
00214   _clear_accum_blue = -1.0f;
00215   _clear_accum_alpha = -1.0f;
00216 
00217   // Set up the specific state values to GL's known initial values.
00218   _draw_buffer_mode = (has_back) ? GL_BACK : GL_FRONT;
00219   _read_buffer_mode = (has_back) ? GL_BACK : GL_FRONT;
00220   _shade_model_mode = GL_SMOOTH;
00221   chromium.FrontFace(GL_CCW);
00222 
00223   _line_width = 1.0f;
00224   _point_size = 1.0f;
00225   _depth_mask = false;
00226   _fog_mode = GL_EXP;
00227   _alpha_func = GL_ALWAYS;
00228   _alpha_func_ref = 0;
00229   _polygon_mode = GL_FILL;
00230 
00231   _pack_alignment = 4;
00232   _unpack_alignment = 4;
00233 
00234   // Set up all the enabled/disabled flags to GL's known initial
00235   // values: everything off.
00236   _multisample_enabled = false;
00237   _line_smooth_enabled = false;
00238   _point_smooth_enabled = false;
00239   _scissor_enabled = false;
00240   _normals_enabled = false;
00241   _texturing_enabled = false;
00242   _multisample_alpha_one_enabled = false;
00243   _multisample_alpha_mask_enabled = false;
00244   _blend_enabled = false;
00245   _depth_test_enabled = false;
00246   _fog_enabled = false;
00247   _alpha_test_enabled = false;
00248   _polygon_offset_enabled = false;
00249   _decal_level = 0;
00250 
00251   // Dither is on by default in GL, let's turn it off
00252   _dither_enabled = true;
00253   enable_dither(false);
00254 
00255   // Stencil test is off by default
00256   _stencil_test_enabled = false;
00257   _stencil_func = GL_NOTEQUAL;
00258   _stencil_op = GL_REPLACE;
00259 
00260   // Antialiasing.
00261   enable_line_smooth(false);
00262   enable_multisample(true);
00263 
00264   // Should we normalize lighting normals?
00265   if (cr_auto_normalize_lighting) {
00266     chromium.Enable(GL_NORMALIZE);
00267   }
00268 
00269   // Set up the light id map
00270   GLint max_lights;
00271   chromium.GetIntegerv(GL_MAX_LIGHTS, &max_lights);
00272   init_lights(max_lights);
00273 
00274   // Set up the clip plane id map
00275   GLint max_clip_planes;
00276   chromium.GetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
00277   _max_clip_planes = max_clip_planes;
00278   _available_clip_plane_ids = PTA(PlaneNode*)::empty_array(_max_clip_planes);
00279   _clip_plane_enabled = new bool[_max_clip_planes];
00280   _cur_clip_plane_enabled = new bool[_max_clip_planes];
00281   int i;
00282   for (i = 0; i < _max_clip_planes; i++) {
00283     _available_clip_plane_ids[i] = NULL;
00284     _clip_plane_enabled[i] = false;
00285   }
00286 
00287   _current_projection_mat = LMatrix4f::ident_mat();
00288   _projection_mat_stack_count = 0;
00289 
00290   // Make sure the GL state matches all of our initial attribute
00291   // states.
00292   CPT(RenderAttrib) dta = DepthTestAttrib::make();
00293   CPT(RenderAttrib) dwa = DepthWriteAttrib::make();
00294   CPT(RenderAttrib) cfa = CullFaceAttrib::make();
00295   CPT(renderAttrib) ta = TextureAttrib::make_off();
00296 
00297   dta->issue(this);
00298   dwa->issue(this);
00299   cfa->issue(this);
00300   ta->issue(this);
00301 
00302   Material empty;
00303   apply_material(&empty);
00304 
00305   if (cr_cheap_textures) {
00306     crgsg_cat.info()
00307       << "Setting chromium.Hint() for fastest textures.\n";
00308     chromium.Hint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
00309   }
00310 
00311   // use per-vertex fog if per-pixel fog requires SW renderer
00312   chromium.Hint(GL_FOG_HINT,GL_DONT_CARE);
00313 
00314   _dithering_enabled = false;
00315 
00316   GLint iRedBits;
00317   chromium.GetIntegerv(GL_RED_BITS,&iRedBits);
00318   if(iRedBits<24) {
00319     chromium.Enable(GL_DITHER);
00320     _dithering_enabled = true;
00321     if(crgsg_cat.is_debug())
00322         crgsg_cat.debug() << "frame buffer depth < 8bits channel, enabling dithering\n";
00323   }
00324 }
00325 
00326 
00327 ////////////////////////////////////////////////////////////////////
00328 //     Function: CRGraphicsStateGuardian::clear
00329 //       Access: Public, Virtual
00330 //  Description: Clears all of the indicated buffers to their assigned
00331 //               colors.
00332 ////////////////////////////////////////////////////////////////////
00333 void CRGraphicsStateGuardian::
00334 clear(const RenderBuffer &buffer) {
00335   DO_PSTATS_STUFF(PStatTimer timer(_win->_clear_pcollector);)
00336   //  activate();
00337 
00338   nassertv(buffer._gsg == this);
00339   int buffer_type = buffer._buffer_type;
00340   GLbitfield mask = 0;
00341   CPT(RenderState) state = RenderState::make_identity();
00342 
00343   if (buffer_type & RenderBuffer::T_color) {
00344     call_glClearColor(_color_clear_value[0],
00345                       _color_clear_value[1],
00346                       _color_clear_value[2],
00347                       _color_clear_value[3]);
00348     state = state->set_attrib(ColorWriteAttrib::make(ColorWriteAttrib::M_on));
00349     mask |= GL_COLOR_BUFFER_BIT;
00350 
00351     set_draw_buffer(buffer);
00352   }
00353 
00354   if (buffer_type & RenderBuffer::T_depth) {
00355     call_glClearDepth(_depth_clear_value);
00356     mask |= GL_DEPTH_BUFFER_BIT;
00357 
00358     // In order to clear the depth buffer, the depth mask must enable
00359     // writing to the depth buffer.
00360     if (!_depth_mask) {
00361       state = state->set_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_on));
00362     }
00363   }
00364 
00365   if (buffer_type & RenderBuffer::T_stencil) {
00366     call_glClearStencil(_stencil_clear_value != false);
00367     mask |= GL_STENCIL_BUFFER_BIT;
00368   }
00369 
00370   if (buffer_type & RenderBuffer::T_accum) {
00371     call_glClearAccum(_accum_clear_value[0],
00372                       _accum_clear_value[1],
00373                       _accum_clear_value[2],
00374                       _accum_clear_value[3]);
00375     mask |= GL_ACCUM_BUFFER_BIT;
00376   }
00377 
00378 #ifdef GSG_VERBOSE
00379   crgsg_cat.debug() << "crClear(";
00380   if (mask & GL_COLOR_BUFFER_BIT) {
00381     crgsg_cat.debug(false) << "GL_COLOR_BUFFER_BIT|";
00382   }
00383   if (mask & GL_DEPTH_BUFFER_BIT) {
00384     crgsg_cat.debug(false) << "GL_DEPTH_BUFFER_BIT|";
00385   }
00386   if (mask & GL_STENCIL_BUFFER_BIT) {
00387     crgsg_cat.debug(false) << "GL_STENCIL_BUFFER_BIT|";
00388   }
00389   if (mask & GL_ACCUM_BUFFER_BIT) {
00390     crgsg_cat.debug(false) << "GL_ACCUM_BUFFER_BIT|";
00391   }
00392   crgsg_cat.debug(false) << ")" << endl;
00393 #endif
00394 
00395   modify_state(state);
00396   chromium.Clear(mask);
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: CRGraphicsStateGuardian::clear
00401 //       Access: Public, Virtual
00402 //  Description: Clears all of the indicated buffers to their assigned
00403 //               colors.
00404 ////////////////////////////////////////////////////////////////////
00405 void CRGraphicsStateGuardian::
00406 clear(const RenderBuffer &buffer, const DisplayRegion *region) {
00407   DisplayRegionStack old_dr = push_display_region(region);
00408   prepare_display_region();
00409   clear(buffer);
00410   pop_display_region(old_dr);
00411 }
00412 
00413 ////////////////////////////////////////////////////////////////////
00414 //     Function: CRGraphicsStateGuardian::prepare_display_region
00415 //       Access: Public, Virtual
00416 //  Description: Prepare a display region for rendering (set up
00417 //       scissor region and viewport)
00418 ////////////////////////////////////////////////////////////////////
00419 void CRGraphicsStateGuardian::
00420 prepare_display_region() {
00421   if (_current_display_region == (DisplayRegion*)0L) {
00422     crgsg_cat.error()
00423       << "Invalid NULL display region in prepare_display_region()\n";
00424     enable_scissor(false);
00425 
00426   } else if (_current_display_region != _actual_display_region) {
00427     _actual_display_region = _current_display_region;
00428 
00429     int l, b, w, h;
00430     _actual_display_region->get_region_pixels(l, b, w, h);
00431     GLint x = GLint(l);
00432     GLint y = GLint(b);
00433     GLsizei width = GLsizei(w);
00434     GLsizei height = GLsizei(h);
00435 
00436     enable_scissor( true );
00437     call_glScissor( x, y, width, height );
00438     call_glViewport( x, y, width, height );
00439   }
00440 }
00441 
00442 ////////////////////////////////////////////////////////////////////
00443 //     Function: CRGraphicsStateGuardian::prepare_lens
00444 //       Access: Public, Virtual
00445 //  Description: Makes the current lens (whichever lens was most
00446 //               recently specified with push_lens()) active, so that
00447 //               it will transform future rendered geometry.  Normally
00448 //               this is only called from the draw process, and
00449 //               usually it is called immediately after a call to
00450 //               push_lens().
00451 //
00452 //               The return value is true if the lens is acceptable,
00453 //               false if it is not.
00454 ////////////////////////////////////////////////////////////////////
00455 bool CRGraphicsStateGuardian::
00456 prepare_lens() {
00457   if (_current_lens == (Lens *)NULL) {
00458     return false;
00459   }
00460 
00461   if (!_current_lens->is_linear()) {
00462     return false;
00463   }
00464 
00465   const LMatrix4f &projection_mat = _current_lens->get_projection_mat();
00466 
00467   // The projection matrix must always be right-handed Y-up, even if
00468   // our coordinate system of choice is otherwise, because certain GL
00469   // calls (specifically chromium.TexGen(GL_SPHERE_MAP)) assume this kind of
00470   // a coordinate system.  Sigh.  In order to implement a Z-up (or
00471   // other arbitrary) coordinate system, we'll use a Y-up projection
00472   // matrix, and store the conversion to our coordinate system of
00473   // choice in the modelview matrix.
00474   LMatrix4f new_projection_mat =
00475     LMatrix4f::convert_mat(CS_yup_right, _current_lens->get_coordinate_system()) *
00476     projection_mat;
00477 
00478 #ifdef GSG_VERBOSE
00479   crgsg_cat.debug()
00480     << "crMatrixMode(GL_PROJECTION): " << new_projection_mat << endl;
00481 #endif
00482   chromium.MatrixMode(GL_PROJECTION);
00483   chromium.LoadMatrixf(new_projection_mat.get_data());
00484 
00485   return true;
00486 }
00487 
00488 ////////////////////////////////////////////////////////////////////
00489 //     Function: CRGraphicsStateGuardian::draw_point
00490 //       Access: Public, Virtual
00491 //  Description:
00492 ////////////////////////////////////////////////////////////////////
00493 void CRGraphicsStateGuardian::
00494 draw_point(GeomPoint *geom, GeomContext *) {
00495   //  activate();
00496 
00497 #ifdef GSG_VERBOSE
00498   crgsg_cat.debug() << "draw_point()" << endl;
00499 #endif
00500 #ifdef DO_PSTATS
00501   PStatTimer timer(_draw_primitive_pcollector);
00502   _vertices_other_pcollector.add_level(geom->get_num_vertices());
00503 #endif
00504 
00505   call_glPointSize(geom->get_size());
00506   issue_scene_graph_color();
00507 
00508   int nprims = geom->get_num_prims();
00509   Geom::VertexIterator vi = geom->make_vertex_iterator();
00510   Geom::NormalIterator ni = geom->make_normal_iterator();
00511   Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
00512   Geom::ColorIterator ci = geom->make_color_iterator();
00513 
00514   GeomIssuer::IssueColor *issue_color;
00515 
00516   if (!_color_transform_enabled && !_alpha_transform_enabled) {
00517     issue_color = issue_color_gl;
00518   }
00519   else {
00520     issue_color = issue_transformed_color_gl;
00521   }
00522 
00523   GeomIssuer issuer(geom, this,
00524                     issue_vertex_gl,
00525                     issue_normal_gl,
00526                     issue_texcoord_gl,
00527                     issue_color);
00528 
00529   // Draw overall
00530   issuer.issue_color(G_OVERALL, ci);
00531   issuer.issue_normal(G_OVERALL, ni);
00532 
00533   chromium.Begin(GL_POINTS);
00534 
00535   for (int i = 0; i < nprims; i++) {
00536     // Draw per primitive
00537     issuer.issue_color(G_PER_PRIM, ci);
00538     issuer.issue_normal(G_PER_PRIM, ni);
00539 
00540     // Draw per vertex, same thing.
00541     issuer.issue_color(G_PER_VERTEX, ci);
00542     issuer.issue_normal(G_PER_VERTEX, ni);
00543     issuer.issue_texcoord(G_PER_VERTEX, ti);
00544     issuer.issue_vertex(G_PER_VERTEX, vi);
00545   }
00546 
00547   chromium.End();
00548   report_errors();
00549 }
00550 
00551 ////////////////////////////////////////////////////////////////////
00552 //     Function: CRGraphicsStateGuardian::draw_line
00553 //       Access: Public, Virtual
00554 //  Description:
00555 ////////////////////////////////////////////////////////////////////
00556 void CRGraphicsStateGuardian::
00557 draw_line(GeomLine *geom, GeomContext *) {
00558   //  activate();
00559 
00560 #ifdef GSG_VERBOSE
00561   crgsg_cat.debug() << "draw_line()" << endl;
00562 #endif
00563 #ifdef DO_PSTATS
00564   PStatTimer timer(_draw_primitive_pcollector);
00565   _vertices_other_pcollector.add_level(geom->get_num_vertices());
00566 #endif
00567 
00568   call_glLineWidth(geom->get_width());
00569   issue_scene_graph_color();
00570 
00571   int nprims = geom->get_num_prims();
00572   Geom::VertexIterator vi = geom->make_vertex_iterator();
00573   Geom::ColorIterator ci = geom->make_color_iterator();
00574 
00575   GeomIssuer::IssueColor *issue_color;
00576 
00577   if (!_color_transform_enabled && !_alpha_transform_enabled) {
00578     issue_color = issue_color_gl;
00579   }
00580   else {
00581     issue_color = issue_transformed_color_gl;
00582   }
00583 
00584   GeomIssuer issuer(geom, this,
00585                     issue_vertex_gl,
00586                     issue_normal_gl,
00587                     issue_texcoord_gl,
00588                     issue_color);
00589 
00590   if (geom->get_binding(G_COLOR) == G_PER_VERTEX) {
00591     call_glShadeModel(GL_SMOOTH);
00592   } else {
00593     call_glShadeModel(GL_FLAT);
00594   }
00595 
00596   // Draw overall
00597   issuer.issue_color(G_OVERALL, ci);
00598 
00599   chromium.Begin(GL_LINES);
00600 
00601   for (int i = 0; i < nprims; i++) {
00602     // Draw per primitive
00603     issuer.issue_color(G_PER_PRIM, ci);
00604 
00605     for (int j = 0; j < 2; j++) {
00606       // Draw per vertex
00607       issuer.issue_color(G_PER_VERTEX, ci);
00608       issuer.issue_vertex(G_PER_VERTEX, vi);
00609     }
00610   }
00611 
00612   chromium.End();
00613   report_errors();
00614 }
00615 
00616 ////////////////////////////////////////////////////////////////////
00617 //     Function: CRGraphicsStateGuardian::draw_linestrip
00618 //       Access: Public, Virtual
00619 //  Description:
00620 ////////////////////////////////////////////////////////////////////
00621 void CRGraphicsStateGuardian::
00622 draw_linestrip(GeomLinestrip *geom, GeomContext *) {
00623   //  activate();
00624 
00625 #ifdef GSG_VERBOSE
00626   crgsg_cat.debug() << "draw_linestrip()" << endl;
00627 #endif
00628 
00629 #ifdef DO_PSTATS
00630   //  PStatTimer timer(_draw_primitive_pcollector);
00631   // Using PStatTimer may cause a compiler crash.
00632   _draw_primitive_pcollector.start();
00633   _vertices_other_pcollector.add_level(geom->get_num_vertices());
00634 #endif
00635 
00636   call_glLineWidth(geom->get_width());
00637   issue_scene_graph_color();
00638 
00639   int nprims = geom->get_num_prims();
00640   const int *plen = geom->get_lengths();
00641   Geom::VertexIterator vi = geom->make_vertex_iterator();
00642   Geom::ColorIterator ci = geom->make_color_iterator();
00643 
00644   GeomIssuer::IssueColor *issue_color;
00645 
00646   if (!_color_transform_enabled && !_alpha_transform_enabled) {
00647     issue_color = issue_color_gl;
00648   }
00649   else {
00650     issue_color = issue_transformed_color_gl;
00651   }
00652 
00653   GeomIssuer issuer(geom, this,
00654                     issue_vertex_gl,
00655                     issue_normal_gl,
00656                     issue_texcoord_gl,
00657                     issue_color);
00658 
00659   if (geom->get_binding(G_COLOR) == G_PER_VERTEX) {
00660     call_glShadeModel(GL_SMOOTH);
00661   } else {
00662     call_glShadeModel(GL_FLAT);
00663   }
00664 
00665   // Draw overall
00666   issuer.issue_color(G_OVERALL, ci);
00667 
00668   for (int i = 0; i < nprims; i++) {
00669     // Draw per primitive
00670     issuer.issue_color(G_PER_PRIM, ci);
00671 
00672     int num_verts = *(plen++);
00673     nassertv(num_verts >= 2);
00674 
00675     chromium.Begin(GL_LINE_STRIP);
00676 
00677     // Per-component attributes for the first line segment?
00678     issuer.issue_color(G_PER_COMPONENT, ci);
00679 
00680     // Draw the first 2 vertices
00681     int v;
00682     for (v = 0; v < 2; v++) {
00683       issuer.issue_color(G_PER_VERTEX, ci);
00684       issuer.issue_vertex(G_PER_VERTEX, vi);
00685     }
00686 
00687     // Now draw each of the remaining vertices.  Each vertex from
00688     // this point on defines a new line segment.
00689     for (v = 2; v < num_verts; v++) {
00690       // Per-component attributes?
00691       issuer.issue_color(G_PER_COMPONENT, ci);
00692 
00693       // Per-vertex attributes
00694       issuer.issue_color(G_PER_VERTEX, ci);
00695       issuer.issue_vertex(G_PER_VERTEX, vi);
00696     }
00697     chromium.End();
00698   }
00699   report_errors();
00700   DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
00701 }
00702 
00703 ////////////////////////////////////////////////////////////////////
00704 //     Function: CRGraphicsStateGuardian::draw_sprite
00705 //       Access: Public, Virtual
00706 //  Description: CSN, 7/11/00
00707 ////////////////////////////////////////////////////////////////////
00708 
00709 // this class exists because an alpha sort is necessary for correct
00710 // sprite rendering, and we can't simply sort the vertex arrays as
00711 // each vertex may or may not have corresponding information in the
00712 // x/y texel-world-ratio and rotation arrays.
00713 class WrappedSprite {
00714 public:
00715   Vertexf _v;
00716   Colorf _c;
00717   float _x_ratio;
00718   float _y_ratio;
00719   float _theta;
00720 };
00721 
00722 // this struct exists because the STL can sort faster than i can.
00723 struct draw_sprite_vertex_less {
00724   INLINE bool operator ()(const WrappedSprite& v0,
00725                           const WrappedSprite& v1) const {
00726     return v0._v[2] < v1._v[2]; }
00727 };
00728 
00729 void CRGraphicsStateGuardian::
00730 draw_sprite(GeomSprite *geom, GeomContext *) {
00731   // this is a little bit of a mess, but it's ok.  Here's the deal:
00732   // we want to draw, and draw quickly, an arbitrarily large number
00733   // of sprites all facing the screen.  Performing the billboard math
00734   // for ~1000 sprites is way too slow.  Ideally, we want one
00735   // matrix transformation that will handle everything, and this is
00736   // just about what ends up happening. We're getting the front-facing
00737   // effect by setting up a new frustum (of the same z-depth as the
00738   // current one) that is very small in x and y.  This way regularly
00739   // rendered triangles that might not be EXACTLY facing the camera
00740   // will certainly look close enough.  Then, we transform to camera-space
00741   // by hand and apply the inverse frustum to the transformed point.
00742   // For some cracked out reason, this actually works.
00743 #ifdef GSG_VERBOSE
00744   crgsg_cat.debug() << "draw_sprite()" << endl;
00745 #endif
00746 
00747   // get the array traversal set up.
00748   int nprims = geom->get_num_prims();
00749   if (nprims==0) {
00750       return;
00751   }
00752 
00753 #ifdef DO_PSTATS
00754   //  PStatTimer timer(_draw_primitive_pcollector);
00755   // Using PStatTimer may cause a compiler crash.
00756   _draw_primitive_pcollector.start();
00757   _vertices_other_pcollector.add_level(geom->get_num_vertices());
00758 #endif
00759 
00760   Geom::VertexIterator vi = geom->make_vertex_iterator();
00761   Geom::ColorIterator ci = geom->make_color_iterator();
00762 
00763   // need some interface so user can set 2d dimensions if no texture specified
00764   float tex_xsize = 1.0f;  
00765   float tex_ysize = 1.0f;
00766 
00767   Texture *tex = geom->get_texture();
00768   if(tex != NULL) {
00769     // set up the texture-rendering state
00770     modify_state(RenderState::make
00771                  (TextureAttrib::make(tex),
00772                   TextureApplyAttrib::make(TextureApplyAttrib::M_modulate)));
00773     tex_xsize = tex->_pbuffer->get_xsize();
00774     tex_ysize = tex->_pbuffer->get_ysize();
00775   }
00776 
00777   // save the modelview matrix
00778   const LMatrix4f &modelview_mat = _transform->get_mat();
00779 
00780   // We don't need to mess with the aspect ratio, since we are now
00781   // using the default projection matrix, which has the right aspect
00782   // ratio built in.
00783 
00784   // load up our own matrices
00785   chromium.MatrixMode(GL_MODELVIEW);
00786   chromium.LoadIdentity();
00787 
00788   // precomputation stuff
00789   float tex_left = geom->get_ll_uv()[0];
00790   float tex_right = geom->get_ur_uv()[0];
00791   float tex_bottom = geom->get_ll_uv()[1];
00792   float tex_top = geom->get_ur_uv()[1];
00793 
00794   float half_width =  0.5f * tex_xsize * fabs(tex_right - tex_left);
00795   float half_height = 0.5f * tex_ysize * fabs(tex_top - tex_bottom);
00796   float scaled_width = 0.0f;
00797   float scaled_height = 0.0f;
00798 
00799   // the user can override alpha sorting if they want
00800   bool alpha = false;
00801 
00802   if (!geom->get_alpha_disable()) {
00803     // figure out if alpha's enabled (if not, no reason to sort)
00804     const TransparencyAttrib *trans = _state->get_transparency();
00805     if (trans != (const TransparencyAttrib *)NULL) {
00806       alpha = (trans->get_mode() != TransparencyAttrib::M_none);
00807     }
00808   }
00809 
00810   // sort container and iterator
00811   pvector< WrappedSprite > cameraspace_vector;
00812   pvector< WrappedSprite >::iterator vec_iter;
00813 
00814   // inner loop vars
00815   int i;
00816   Vertexf source_vert, cameraspace_vert;
00817   float *x_walk = (float *)NULL;
00818   float *y_walk = (float *)NULL;
00819   float *theta_walk = (float *)NULL;
00820   float theta = 0.0f;
00821 
00822   nassertv(geom->get_x_bind_type() != G_PER_VERTEX);
00823   nassertv(geom->get_y_bind_type() != G_PER_VERTEX);
00824 
00825   // set up the non-built-in bindings
00826   bool x_overall = (geom->get_x_bind_type() == G_OVERALL);
00827   bool y_overall = (geom->get_y_bind_type() == G_OVERALL);
00828   bool theta_overall = (geom->get_theta_bind_type() == G_OVERALL);
00829   bool color_overall = (geom->get_binding(G_COLOR) == G_OVERALL);
00830   bool theta_on = !(geom->get_theta_bind_type() == G_OFF);
00831 
00832   // x direction
00833   if (x_overall)
00834     scaled_width = geom->_x_texel_ratio[0] * half_width;
00835   else {
00836     nassertv(((int)geom->_x_texel_ratio.size() >= geom->get_num_prims()));
00837     x_walk = &geom->_x_texel_ratio[0];
00838   }
00839 
00840   // y direction
00841   if (y_overall)
00842     scaled_height = geom->_y_texel_ratio[0] * half_height;
00843   else {
00844     nassertv(((int)geom->_y_texel_ratio.size() >= geom->get_num_prims()));
00845     y_walk = &geom->_y_texel_ratio[0];
00846   }
00847 
00848   // theta
00849   if (theta_on) {
00850     if (theta_overall)
00851       theta = geom->_theta[0];
00852     else {
00853       nassertv(((int)geom->_theta.size() >= geom->get_num_prims()));
00854       theta_walk = &geom->_theta[0];
00855     }
00856   }
00857 
00858   /////////////////////////////////////////////////////////////////////
00859   // INNER LOOP PART 1 STARTS HERE
00860   // Here we transform each point to cameraspace and fill our sort
00861   // vector with the final geometric information.
00862   /////////////////////////////////////////////////////////////////////
00863 
00864   cameraspace_vector.reserve(nprims);   //pre-alloc space for nprims
00865 
00866   // the state is set, start running the prims
00867   for (i = 0; i < nprims; i++) {
00868     WrappedSprite ws;
00869 
00870     source_vert = geom->get_next_vertex(vi);
00871 
00872     // this mult converts to y-up cameraspace.
00873     cameraspace_vert = source_vert * modelview_mat;
00874     // build the final object that will go into the vector.
00875     ws._v.set(cameraspace_vert[0],cameraspace_vert[1],cameraspace_vert[2]);
00876 
00877     if (!color_overall)
00878       ws._c = geom->get_next_color(ci);
00879     if (!x_overall)
00880       ws._x_ratio = *x_walk++;
00881     if (!y_overall)
00882       ws._y_ratio = *y_walk++;
00883     if (theta_on) {
00884       if (!theta_overall)
00885         ws._theta = *theta_walk++;
00886     }
00887 
00888     cameraspace_vector.push_back(ws);
00889   }
00890 
00891   // now the verts are properly sorted by alpha (if necessary).  Of course,
00892   // the sort is only local, not scene-global, so if you look closely you'll
00893   // notice that alphas may be screwy.  It's ok though, because this is fast.
00894   // if you want accuracy, use billboards and take the speed hit.
00895   if (alpha) {
00896     sort(cameraspace_vector.begin(), cameraspace_vector.end(),
00897          draw_sprite_vertex_less());
00898 
00899      if (_dithering_enabled)
00900          chromium.Disable(GL_DITHER);
00901   }
00902 
00903   Vertexf ul, ur, ll, lr;
00904 
00905   if (color_overall)
00906     chromium.Color4fv(geom->get_next_color(ci).get_data());
00907 
00908   ////////////////////////////////////////////////////////////////////////////
00909   // INNER LOOP PART 2 STARTS HERE
00910   // Now we run through the cameraspace vector and compute the geometry for each
00911   // tristrip.  This includes scaling as per the ratio arrays, as well as
00912   // rotating in the z.
00913   ////////////////////////////////////////////////////////////////////////////
00914 
00915   vec_iter = cameraspace_vector.begin();
00916   for (; vec_iter != cameraspace_vector.end(); vec_iter++) {
00917     WrappedSprite& cur_image = *vec_iter;
00918 
00919     // if not G_OVERALL, calculate the scale factors
00920     if (x_overall == false)
00921       scaled_width = cur_image._x_ratio * half_width;
00922 
00923     if (y_overall == false)
00924       scaled_height = cur_image._y_ratio * half_height;
00925 
00926     // if not G_OVERALL, do some trig for this z rotate
00927     if (theta_on) {
00928       if (theta_overall == false)
00929         theta = cur_image._theta;
00930 
00931       // create the rotated points
00932       LMatrix3f xform_mat = LMatrix3f::rotate_mat(theta) * LMatrix3f::scale_mat(scaled_width, scaled_height);
00933 
00934       ur = (LVector3f( 1,  1, 0) * xform_mat) + cur_image._v;
00935       ul = (LVector3f(-1,  1, 0) * xform_mat) + cur_image._v;
00936       lr = (LVector3f( 1, -1, 0) * xform_mat) + cur_image._v;
00937       ll = (LVector3f(-1, -1, 0) * xform_mat) + cur_image._v;
00938     }
00939     else {
00940       // create the normal points
00941       ur.set(scaled_width, scaled_height, 0);
00942       ul.set(-scaled_width, scaled_height, 0);
00943       lr.set(scaled_width, -scaled_height, 0);
00944       ll.set(-scaled_width, -scaled_height, 0);
00945 
00946       ur += cur_image._v;
00947       ul += cur_image._v;
00948       lr += cur_image._v;
00949       ll += cur_image._v;
00950     }
00951 
00952     // set the color
00953     if (color_overall == false)
00954       chromium.Color4fv(cur_image._c.get_data());
00955 
00956     // draw each one as a 2-element tri-strip
00957     chromium.Begin(GL_TRIANGLE_STRIP);
00958     chromium.Normal3f(0.0f, 0.0f, 1.0f);
00959     chromium.TexCoord2f(tex_left, tex_bottom);  chromium.Vertex3fv(ll.get_data());
00960     chromium.TexCoord2f(tex_right, tex_bottom); chromium.Vertex3fv(lr.get_data());
00961     chromium.TexCoord2f(tex_left, tex_top);     chromium.Vertex3fv(ul.get_data());
00962     chromium.TexCoord2f(tex_right, tex_top);    chromium.Vertex3fv(ur.get_data());
00963     chromium.End();
00964   }
00965 
00966   // restore the matrices
00967   chromium.LoadMatrixf(modelview_mat.get_data());
00968 
00969   if(alpha && _dithering_enabled)
00970      chromium.Enable(GL_DITHER);
00971 
00972   report_errors();
00973   DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
00974 }
00975 
00976 
00977 ////////////////////////////////////////////////////////////////////
00978 //     Function: CRGraphicsStateGuardian::draw_polygon
00979 //       Access: Public, Virtual
00980 //  Description:
00981 ////////////////////////////////////////////////////////////////////
00982 void CRGraphicsStateGuardian::
00983 draw_polygon(GeomPolygon *geom, GeomContext *) {
00984   //  activate();
00985 
00986 #ifdef GSG_VERBOSE
00987   crgsg_cat.debug() << "draw_polygon()" << endl;
00988 #endif
00989 
00990 #ifdef DO_PSTATS
00991   //  PStatTimer timer(_draw_primitive_pcollector);
00992   // Using PStatTimer may cause a compiler crash.
00993   _draw_primitive_pcollector.start();
00994   _vertices_other_pcollector.add_level(geom->get_num_vertices());
00995 #endif
00996 
00997   issue_scene_graph_color();
00998 
00999   int nprims = geom->get_num_prims();
01000   const int *plen = geom->get_lengths();
01001   Geom::VertexIterator vi = geom->make_vertex_iterator();
01002   Geom::NormalIterator ni = geom->make_normal_iterator();
01003   Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
01004   Geom::ColorIterator ci = geom->make_color_iterator();
01005 
01006   GeomIssuer::IssueColor *issue_color;
01007 
01008   if (!_color_transform_enabled && !_alpha_transform_enabled) {
01009     issue_color = issue_color_gl;
01010   }
01011   else {
01012     issue_color = issue_transformed_color_gl;
01013   }
01014 
01015   GeomIssuer issuer(geom, this,
01016                     issue_vertex_gl,
01017                     issue_normal_gl,
01018                     issue_texcoord_gl,
01019                     issue_color);
01020 
01021   // If we have per-vertex colors or normals, we need smooth shading.
01022   // Otherwise we want flat shading for performance reasons.
01023   if ((geom->get_binding(G_COLOR) == G_PER_VERTEX && wants_colors()) ||
01024       (geom->get_binding(G_NORMAL) == G_PER_VERTEX && wants_normals())) {
01025     call_glShadeModel(GL_SMOOTH);
01026   } else {
01027     call_glShadeModel(GL_FLAT);
01028   }
01029 
01030   // Draw overall
01031   issuer.issue_color(G_OVERALL, ci);
01032   issuer.issue_normal(G_OVERALL, ni);
01033 
01034   for (int i = 0; i < nprims; i++) {
01035     // Draw per primitive
01036     issuer.issue_color(G_PER_PRIM, ci);
01037     issuer.issue_normal(G_PER_PRIM, ni);
01038 
01039     int num_verts = *(plen++);
01040     nassertv(num_verts >= 3);
01041 
01042     chromium.Begin(GL_POLYGON);
01043 
01044     // Draw the vertices.
01045     int v;
01046     for (v = 0; v < num_verts; v++) {
01047       // Per-vertex attributes.
01048       issuer.issue_color(G_PER_VERTEX, ci);
01049       issuer.issue_normal(G_PER_VERTEX, ni);
01050       issuer.issue_texcoord(G_PER_VERTEX, ti);
01051       issuer.issue_vertex(G_PER_VERTEX, vi);
01052     }
01053     chromium.End();
01054   }
01055   report_errors();
01056   DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
01057 }
01058 
01059 ////////////////////////////////////////////////////////////////////
01060 //     Function: CRGraphicsStateGuardian::draw_tri
01061 //       Access: Public, Virtual
01062 //  Description:
01063 ////////////////////////////////////////////////////////////////////
01064 void CRGraphicsStateGuardian::
01065 draw_tri(GeomTri *geom, GeomContext *) {
01066   //  activate();
01067 
01068 #ifdef GSG_VERBOSE
01069   crgsg_cat.debug() << "draw_tri()" << endl;
01070 #endif
01071 
01072 #ifdef DO_PSTATS
01073   //  PStatTimer timer(_draw_primitive_pcollector);
01074   // Using PStatTimer may cause a compiler crash.
01075   _draw_primitive_pcollector.start();
01076   _vertices_tri_pcollector.add_level(geom->get_num_vertices());
01077 #endif
01078 
01079   issue_scene_graph_color();
01080 
01081   int nprims = geom->get_num_prims();
01082   Geom::VertexIterator vi = geom->make_vertex_iterator();
01083   Geom::NormalIterator ni = geom->make_normal_iterator();
01084   Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
01085   Geom::ColorIterator ci = geom->make_color_iterator();
01086 
01087   GeomIssuer::IssueColor *issue_color;
01088 
01089   if (!_color_transform_enabled && !_alpha_transform_enabled) {
01090     issue_color = issue_color_gl;
01091   }
01092   else {
01093     issue_color = issue_transformed_color_gl;
01094   }
01095 
01096   GeomIssuer issuer(geom, this,
01097                     issue_vertex_gl,
01098                     issue_normal_gl,
01099                     issue_texcoord_gl,
01100                     issue_color);
01101 
01102   // If we have per-vertex colors or normals, we need smooth shading.
01103   // Otherwise we want flat shading for performance reasons.
01104   if ((geom->get_binding(G_COLOR) == G_PER_VERTEX && wants_colors()) ||
01105       (geom->get_binding(G_NORMAL) == G_PER_VERTEX && wants_normals())) {
01106     call_glShadeModel(GL_SMOOTH);
01107   } else {
01108     call_glShadeModel(GL_FLAT);
01109   }
01110 
01111   // Draw overall
01112   issuer.issue_color(G_OVERALL, ci);
01113   issuer.issue_normal(G_OVERALL, ni);
01114 
01115   chromium.Begin(GL_TRIANGLES);
01116 
01117   for (int i = 0; i < nprims; i++) {
01118     // Draw per primitive
01119     issuer.issue_color(G_PER_PRIM, ci);
01120     issuer.issue_normal(G_PER_PRIM, ni);
01121 
01122     for (int j = 0; j < 3; j++) {
01123       // Draw per vertex
01124       issuer.issue_color(G_PER_VERTEX, ci);
01125       issuer.issue_normal(G_PER_VERTEX, ni);
01126       issuer.issue_texcoord(G_PER_VERTEX, ti);
01127       issuer.issue_vertex(G_PER_VERTEX, vi);
01128     }
01129   }
01130 
01131   chromium.End();
01132   report_errors();
01133 #ifdef DO_PSTATS
01134   _draw_primitive_pcollector.stop();
01135 #endif
01136 }
01137 
01138 ////////////////////////////////////////////////////////////////////
01139 //     Function: CRGraphicsStateGuardian::draw_quad
01140 //       Access: Public, Virtual
01141 //  Description:
01142 ////////////////////////////////////////////////////////////////////
01143 void CRGraphicsStateGuardian::
01144 draw_quad(GeomQuad *geom, GeomContext *) {
01145   //  activate();
01146 
01147 #ifdef GSG_VERBOSE
01148   crgsg_cat.debug() << "draw_quad()" << endl;
01149 #endif
01150 
01151 #ifdef DO_PSTATS
01152   //  PStatTimer timer(_draw_primitive_pcollector);
01153   // Using PStatTimer may cause a compiler crash.
01154   _draw_primitive_pcollector.start();
01155   _vertices_other_pcollector.add_level(geom->get_num_vertices());
01156 #endif
01157 
01158   issue_scene_graph_color();
01159 
01160   int nprims = geom->get_num_prims();
01161   Geom::VertexIterator vi = geom->make_vertex_iterator();
01162   Geom::NormalIterator ni = geom->make_normal_iterator();
01163   Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
01164   Geom::ColorIterator ci = geom->make_color_iterator();
01165 
01166   GeomIssuer::IssueColor *issue_color;
01167 
01168   if (!_color_transform_enabled && !_alpha_transform_enabled) {
01169     issue_color = issue_color_gl;
01170   }
01171   else {
01172     issue_color = issue_transformed_color_gl;
01173   }
01174 
01175   GeomIssuer issuer(geom, this,
01176                     issue_vertex_gl,
01177                     issue_normal_gl,
01178                     issue_texcoord_gl,
01179                     issue_color);
01180 
01181   // If we have per-vertex colors or normals, we need smooth shading.
01182   // Otherwise we want flat shading for performance reasons.
01183   if ((geom->get_binding(G_COLOR) == G_PER_VERTEX && wants_colors()) ||
01184       (geom->get_binding(G_NORMAL) == G_PER_VERTEX && wants_normals())) {
01185     call_glShadeModel(GL_SMOOTH);
01186   } else {
01187     call_glShadeModel(GL_FLAT);
01188   }
01189 
01190   // Draw overall
01191   issuer.issue_color(G_OVERALL, ci);
01192   issuer.issue_normal(G_OVERALL, ni);
01193 
01194   chromium.Begin(GL_QUADS);
01195 
01196   for (int i = 0; i < nprims; i++) {
01197     // Draw per primitive
01198     issuer.issue_color(G_PER_PRIM, ci);
01199     issuer.issue_normal(G_PER_PRIM, ni);
01200 
01201     for (int j = 0; j < 4; j++) {
01202       // Draw per vertex
01203       issuer.issue_color(G_PER_VERTEX, ci);
01204       issuer.issue_normal(G_PER_VERTEX, ni);
01205       issuer.issue_texcoord(G_PER_VERTEX, ti);
01206       issuer.issue_vertex(G_PER_VERTEX, vi);
01207     }
01208   }
01209 
01210   chromium.End();
01211   report_errors();
01212   DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
01213 }
01214 
01215 ////////////////////////////////////////////////////////////////////
01216 //     Function: CRGraphicsStateGuardian::draw_tristrip
01217 //       Access: Public, Virtual
01218 //  Description:
01219 ////////////////////////////////////////////////////////////////////
01220 void CRGraphicsStateGuardian::
01221 draw_tristrip(GeomTristrip *geom, GeomContext *) {
01222   //  activate();
01223 
01224 #ifdef GSG_VERBOSE
01225   crgsg_cat.debug() << "draw_tristrip()" << endl;
01226 #endif
01227 
01228 #ifdef DO_PSTATS
01229   //  PStatTimer timer(_draw_primitive_pcollector);
01230   // Using PStatTimer may cause a compiler crash.
01231   _draw_primitive_pcollector.start();
01232   _vertices_tristrip_pcollector.add_level(geom->get_num_vertices());
01233 #endif
01234 
01235   issue_scene_graph_color();
01236 
01237   int nprims = geom->get_num_prims();
01238   const int *plen = geom->get_lengths();
01239   Geom::VertexIterator vi = geom->make_vertex_iterator();
01240   Geom::NormalIterator ni = geom->make_normal_iterator();
01241   Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
01242   Geom::ColorIterator ci = geom->make_color_iterator();
01243 
01244   GeomIssuer::IssueColor *issue_color;
01245 
01246   if (!_color_transform_enabled && !_alpha_transform_enabled) {
01247     issue_color = issue_color_gl;
01248   }
01249   else {
01250     issue_color = issue_transformed_color_gl;
01251   }
01252 
01253   GeomIssuer issuer(geom, this,
01254                     issue_vertex_gl,
01255                     issue_normal_gl,
01256                     issue_texcoord_gl,
01257                     issue_color);
01258 
01259   // If we have per-vertex colors or normals, we need smooth shading.
01260   // Otherwise we want flat shading for performance reasons.
01261   if ((geom->get_binding(G_COLOR) == G_PER_VERTEX && wants_colors()) ||
01262       (geom->get_binding(G_NORMAL) == G_PER_VERTEX && wants_normals())) {
01263     call_glShadeModel(GL_SMOOTH);
01264   } else {
01265     call_glShadeModel(GL_FLAT);
01266   }
01267 
01268   // Draw overall
01269   issuer.issue_color(G_OVERALL, ci);
01270   issuer.issue_normal(G_OVERALL, ni);
01271 
01272   for (int i = 0; i < nprims; i++) {
01273     // Draw per primitive
01274     issuer.issue_color(G_PER_PRIM, ci);
01275     issuer.issue_normal(G_PER_PRIM, ni);
01276 
01277     int num_verts = *(plen++);
01278     nassertv(num_verts >= 3);
01279 
01280     chromium.Begin(GL_TRIANGLE_STRIP);
01281 
01282     // Per-component attributes for the first triangle?
01283     issuer.issue_color(G_PER_COMPONENT, ci);
01284     issuer.issue_normal(G_PER_COMPONENT, ni);
01285 
01286     // Draw the first three vertices.
01287     int v;
01288     for (v = 0; v < 3; v++) {
01289       issuer.issue_color(G_PER_VERTEX, ci);
01290       issuer.issue_normal(G_PER_VERTEX, ni);
01291       issuer.issue_texcoord(G_PER_VERTEX, ti);
01292       issuer.issue_vertex(G_PER_VERTEX, vi);
01293     }
01294 
01295     // Now draw each of the remaining vertices.  Each vertex from
01296     // this point on defines a new triangle.
01297     for (v = 3; v < num_verts; v++) {
01298       // Per-component attributes?
01299       issuer.issue_color(G_PER_COMPONENT, ci);
01300       issuer.issue_normal(G_PER_COMPONENT, ni);
01301 
01302       // Per-vertex attributes.
01303       issuer.issue_color(G_PER_VERTEX, ci);
01304       issuer.issue_normal(G_PER_VERTEX, ni);
01305       issuer.issue_texcoord(G_PER_VERTEX, ti);
01306       issuer.issue_vertex(G_PER_VERTEX, vi);
01307     }
01308     chromium.End();
01309   }
01310   report_errors();
01311   DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
01312 }
01313 
01314 ////////////////////////////////////////////////////////////////////
01315 //     Function: CRGraphicsStateGuardian::draw_trifan
01316 //       Access: Public, Virtual
01317 //  Description:
01318 ////////////////////////////////////////////////////////////////////
01319 void CRGraphicsStateGuardian::
01320 draw_trifan(GeomTrifan *geom, GeomContext *) {
01321   //  activate();
01322 
01323 #ifdef GSG_VERBOSE
01324   crgsg_cat.debug() << "draw_trifan()" << endl;
01325 #endif
01326 
01327 #ifdef DO_PSTATS
01328   //  PStatTimer timer(_draw_primitive_pcollector);
01329   // Using PStatTimer may cause a compiler crash.
01330   _draw_primitive_pcollector.start();
01331   _vertices_trifan_pcollector.add_level(geom->get_num_vertices());
01332 #endif
01333 
01334   issue_scene_graph_color();
01335 
01336   int nprims = geom->get_num_prims();
01337   const int *plen = geom->get_lengths();
01338   Geom::VertexIterator vi = geom->make_vertex_iterator();
01339   Geom::NormalIterator ni = geom->make_normal_iterator();
01340   Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
01341   Geom::ColorIterator ci = geom->make_color_iterator();
01342 
01343   GeomIssuer::IssueColor *issue_color;
01344 
01345   if (!_color_transform_enabled && !_alpha_transform_enabled) {
01346     issue_color = issue_color_gl;
01347   }
01348   else {
01349     issue_color = issue_transformed_color_gl;
01350   }
01351 
01352   GeomIssuer issuer(geom, this,
01353                     issue_vertex_gl,
01354                     issue_normal_gl,
01355                     issue_texcoord_gl,
01356                     issue_color);
01357 
01358   // If we have per-vertex colors or normals, we need smooth shading.
01359   // Otherwise we want flat shading for performance reasons.
01360   if ((geom->get_binding(G_COLOR) == G_PER_VERTEX && wants_colors()) ||
01361       (geom->get_binding(G_NORMAL) == G_PER_VERTEX && wants_normals())) {
01362     call_glShadeModel(GL_SMOOTH);
01363   } else {
01364     call_glShadeModel(GL_FLAT);
01365   }
01366 
01367   // Draw overall
01368   issuer.issue_color(G_OVERALL, ci);
01369   issuer.issue_normal(G_OVERALL, ni);
01370 
01371   for (int i = 0; i < nprims; i++) {
01372     // Draw per primitive
01373     issuer.issue_color(G_PER_PRIM, ci);
01374     issuer.issue_normal(G_PER_PRIM, ni);
01375 
01376     int num_verts = *(plen++);
01377     nassertv(num_verts >= 3);
01378 
01379     chromium.Begin(GL_TRIANGLE_FAN);
01380 
01381     // Per-component attributes for the first triangle?
01382     issuer.issue_color(G_PER_COMPONENT, ci);
01383     issuer.issue_normal(G_PER_COMPONENT, ni);
01384 
01385     // Draw the first three vertices.
01386     int v;
01387     for (v = 0; v < 3; v++) {
01388       issuer.issue_color(G_PER_VERTEX, ci);
01389       issuer.issue_normal(G_PER_VERTEX, ni);
01390       issuer.issue_texcoord(G_PER_VERTEX, ti);
01391       issuer.issue_vertex(G_PER_VERTEX, vi);
01392     }
01393 
01394     // Now draw each of the remaining vertices.  Each vertex from
01395     // this point on defines a new triangle.
01396     for (v = 3; v < num_verts; v++) {
01397       // Per-component attributes?
01398       issuer.issue_color(G_PER_COMPONENT, ci);
01399       issuer.issue_normal(G_PER_COMPONENT, ni);
01400 
01401       // Per-vertex attributes.
01402       issuer.issue_color(G_PER_VERTEX, ci);
01403       issuer.issue_normal(G_PER_VERTEX, ni);
01404       issuer.issue_texcoord(G_PER_VERTEX, ti);
01405       issuer.issue_vertex(G_PER_VERTEX, vi);
01406     }
01407     chromium.End();
01408   }
01409   report_errors();
01410   DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
01411 }
01412 
01413 
01414 ////////////////////////////////////////////////////////////////////
01415 //     Function: CRGraphicsStateGuardian::draw_sphere
01416 //       Access: Public, Virtual
01417 //  Description:
01418 ////////////////////////////////////////////////////////////////////
01419 void CRGraphicsStateGuardian::
01420 draw_sphere(GeomSphere *geom, GeomContext *) {
01421   //  activate();
01422 
01423 #ifdef GSG_VERBOSE
01424   crgsg_cat.debug() << "draw_sphere()" << endl;
01425 #endif
01426 
01427 #ifdef DO_PSTATS
01428   //  PStatTimer timer(_draw_primitive_pcollector);
01429   // Using PStatTimer may cause a compiler crash.
01430   _draw_primitive_pcollector.start();
01431   _vertices_other_pcollector.add_level(geom->get_num_vertices());
01432 #endif
01433 
01434   issue_scene_graph_color();
01435 
01436   int nprims = geom->get_num_prims();
01437   Geom::VertexIterator vi = geom->make_vertex_iterator();
01438   Geom::ColorIterator ci = geom->make_color_iterator();
01439 
01440   GeomIssuer::IssueColor *issue_color;
01441 
01442   if (!_color_transform_enabled && !_alpha_transform_enabled) {
01443     issue_color = issue_color_gl;
01444   }
01445   else {
01446     issue_color = issue_transformed_color_gl;
01447   }
01448 
01449   GeomIssuer issuer(geom, this,
01450                     issue_vertex_gl,
01451                     issue_normal_gl,
01452                     issue_texcoord_gl,
01453                     issue_color);
01454 
01455   if (wants_normals()) {
01456     call_glShadeModel(GL_SMOOTH);
01457   } else {
01458     call_glShadeModel(GL_FLAT);
01459   }
01460 
01461   // Draw overall
01462   issuer.issue_color(G_OVERALL, ci);
01463 
01464   GLUquadricObj *sph = gluNewQuadric();
01465   gluQuadricNormals(sph, wants_normals() ? (GLenum)GLU_SMOOTH : (GLenum)GLU_NONE);
01466   gluQuadricTexture(sph, wants_texcoords() ? (GLenum)GL_TRUE : (GLenum)GL_FALSE);
01467   gluQuadricOrientation(sph, (GLenum)GLU_OUTSIDE);
01468   gluQuadricDrawStyle(sph, (GLenum)GLU_FILL);
01469   //gluQuadricDrawStyle(sph, (GLenum)GLU_LINE);
01470 
01471   for (int i = 0; i < nprims; i++) {
01472     // Draw per primitive
01473     issuer.issue_color(G_PER_PRIM, ci);
01474 
01475     for (int j = 0; j < 2; j++) {
01476       // Draw per vertex
01477       issuer.issue_color(G_PER_VERTEX, ci);
01478     }
01479     Vertexf center = geom->get_next_vertex(vi);
01480     Vertexf edge = geom->get_next_vertex(vi);
01481     LVector3f v = edge - center;
01482     float r = sqrt(dot(v, v));
01483 
01484     // Since gluSphere doesn't have a center parameter, we have to use
01485     // a matrix transform.
01486 
01487     chromium.MatrixMode(GL_MODELVIEW);
01488     chromium.PushMatrix();
01489     chromium.MultMatrixf(LMatrix4f::translate_mat(center).get_data());
01490 
01491     // Now render the sphere using GLU calls.
01492     gluSphere(sph, r, 16, 10);
01493 
01494     chromium.MatrixMode(GL_MODELVIEW);
01495     chromium.PopMatrix();
01496   }
01497 
01498   gluDeleteQuadric(sph);
01499   report_errors();
01500   DO_PSTATS_STUFF(_draw_primitive_pcollector.stop());
01501 }
01502 
01503 ////////////////////////////////////////////////////////////////////
01504 //     Function: CRGraphicsStateGuardian::prepare_texture
01505 //       Access: Public, Virtual
01506 //  Description: Creates a new retained-mode representation of the
01507 //               given texture, and returns a newly-allocated
01508 //               TextureContext pointer to reference it.  It is the
01509 //               responsibility of the calling function to later
01510 //               call release_texture() with this same pointer (which
01511 //               will also delete the pointer).
01512 ////////////////////////////////////////////////////////////////////
01513 TextureContext *CRGraphicsStateGuardian::
01514 prepare_texture(Texture *tex) {
01515   //  activate();
01516   CRTextureContext *gtc = new CRTextureContext(tex);
01517   chromium.GenTextures(1, &gtc->_index);
01518 
01519   bind_texture(gtc);
01520   chromium.PrioritizeTextures(1, &gtc->_index, &gtc->_priority);
01521   specify_texture(tex);
01522   apply_texture_immediate(tex);
01523 
01524   bool inserted = mark_prepared_texture(gtc);
01525 
01526   // If this assertion fails, the same texture was prepared twice,
01527   // which shouldn't be possible, since the texture itself should
01528   // detect this.
01529   nassertr(inserted, NULL);
01530 
01531   report_errors();
01532   return gtc;
01533 }
01534 
01535 ////////////////////////////////////////////////////////////////////
01536 //     Function: CRGraphicsStateGuardian::apply_texture
01537 //       Access: Public, Virtual
01538 //  Description: Makes the texture the currently available texture for
01539 //               rendering.
01540 ////////////////////////////////////////////////////////////////////
01541 void CRGraphicsStateGuardian::
01542 apply_texture(TextureContext *tc) {
01543   //  activate();
01544   add_to_texture_record(tc);
01545   bind_texture(tc);
01546 
01547   int dirty = tc->get_dirty_flags();
01548   if ((dirty & (Texture::DF_wrap | Texture::DF_filter)) != 0) {
01549     // We need to re-specify the texture properties.
01550     specify_texture(tc->_texture);
01551   }
01552   if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) {
01553     // We need to re-apply the image.
01554     apply_texture_immediate(tc->_texture);
01555   }
01556 
01557   tc->clear_dirty_flags();
01558 
01559   report_errors();
01560 }
01561 
01562 ////////////////////////////////////////////////////////////////////
01563 //     Function: CRGraphicsStateGuardian::release_texture
01564 //       Access: Public, Virtual
01565 //  Description: Frees the GL resources previously allocated for the
01566 //               texture.
01567 ////////////////////////////////////////////////////////////////////
01568 void CRGraphicsStateGuardian::
01569 release_texture(TextureContext *tc) {
01570   //  activate();
01571   CRTextureContext *gtc = DCAST(CRTextureContext, tc);
01572   Texture *tex = tc->_texture;
01573 
01574   if (!is_closed()) {
01575     chromium.DeleteTextures(1, &gtc->_index);
01576   }
01577   gtc->_index = 0;
01578 
01579   bool erased = unmark_prepared_texture(gtc);
01580 
01581   // If this assertion fails, a texture was released that hadn't been
01582   // prepared (or a texture was released twice).
01583   nassertv(erased);
01584 
01585   tex->clear_gsg(this);
01586 
01587   delete gtc;
01588   report_errors();
01589 }
01590 
01591 ////////////////////////////////////////////////////////////////////
01592 //     Function: CRGraphicsStateGuardian::prepare_geom_node
01593 //       Access: Public, Virtual
01594 //  Description: Prepares the indicated GeomNode for retained-mode
01595 //               rendering.  If this function returns non-NULL, the
01596 //               value returned will be passed back to a future call
01597 //               to draw_geom_node(), which is expected to draw the
01598 //               contents of the node.
01599 ////////////////////////////////////////////////////////////////////
01600 GeomNodeContext *CRGraphicsStateGuardian::
01601 prepare_geom_node(GeomNode *node) {
01602 #if 0  // temporarily disabled until we bring to new scene graph
01603 
01604   // Make sure we have at least some static Geoms in the GeomNode;
01605   // otherwise there's no point in building a display list.
01606   int num_geoms = node->get_num_geoms();
01607   bool all_dynamic = true;
01608   int i;
01609 
01610   for (i = 0; (i < num_geoms) && all_dynamic; i++) {
01611     dDrawable *geom = node->get_geom(i);
01612     all_dynamic = geom->is_dynamic();
01613   }
01614   if (all_dynamic) {
01615     // Never mind.
01616     return (GeomNodeContext *)NULL;
01617   }
01618 
01619   // Ok, we've got something; use it.
01620   CRGeomNodeContext *ggnc = new CRGeomNodeContext(node);
01621   ggnc->_index = chromium.GenLists(1);
01622   if (ggnc->_index == 0) {
01623     crgsg_cat.error()
01624       << "Ran out of display list indices.\n";
01625     delete ggnc;
01626     return (GeomNodeContext *)NULL;
01627   }
01628 
01629   // We need to temporarily force normals and UV's on, so the display
01630   // list will have them built in.
01631   bool old_normals_enabled = _normals_enabled;
01632   bool old_texturing_enabled = _texturing_enabled;
01633   bool old_vertex_colors_enabled = _vertex_colors_enabled;
01634   _normals_enabled = true;
01635   _texturing_enabled = true;
01636   _vertex_colors_enabled = true;
01637 
01638 #ifdef DO_PSTATS
01639   // Count up the number of vertices we're about to render, by
01640   // checking the PStats vertex counters now, and at the end.  This is
01641   // kind of hacky, but this is debug code.
01642   float num_verts_before = 
01643     _vertices_tristrip_pcollector.get_level() +
01644     _vertices_trifan_pcollector.get_level() +
01645     _vertices_tri_pcollector.get_level() +
01646     _vertices_other_pcollector.get_level();
01647 #endif
01648 
01649   // Now define the display list.
01650   chromium.NewList(ggnc->_index, GL_COMPILE);
01651   for (i = 0; i < num_geoms; i++) {
01652     dDrawable *geom = node->get_geom(i);
01653     if (geom->is_dynamic()) {
01654       // Wait, this is a dynamic Geom.  We can't safely put it in the
01655       // display list, because it may change from one frame to the
01656       // next; instead, we'll keep it out.
01657       ggnc->_dynamic_geoms.push_back(geom);
01658     } else {
01659       // A static Geom becomes part of the display list.
01660       geom->draw(this);
01661     }
01662   }
01663   chromium.EndList();
01664 
01665 #ifdef DO_PSTATS
01666   float num_verts_after = 
01667     _vertices_tristrip_pcollector.get_level() +
01668     _vertices_trifan_pcollector.get_level() +
01669     _vertices_tri_pcollector.get_level() +
01670     _vertices_other_pcollector.get_level();
01671   float num_verts = num_verts_after - num_verts_before;
01672   ggnc->_num_verts = (int)(num_verts + 0.5);
01673 #endif
01674 
01675   _normals_enabled = old_normals_enabled;
01676   _texturing_enabled = old_texturing_enabled;
01677   _vertex_colors_enabled = old_vertex_colors_enabled;
01678 
01679   bool inserted = mark_prepared_geom_node(ggnc);
01680 
01681   // If this assertion fails, the same GeomNode was prepared twice,
01682   // which shouldn't be possible, since the GeomNode itself should
01683   // detect this.
01684   nassertr(inserted, NULL);
01685 
01686   return ggnc;
01687 #endif  // temporarily disabled until we bring to new scene graph
01688   return NULL;
01689 }
01690 
01691 ////////////////////////////////////////////////////////////////////
01692 //     Function: CRGraphicsStateGuardian::draw_geom_node
01693 //       Access: Public, Virtual
01694 //  Description: Draws a GeomNode previously indicated by a call to
01695 //               prepare_geom_node().
01696 ////////////////////////////////////////////////////////////////////
01697 void CRGraphicsStateGuardian::
01698 draw_geom_node(GeomNode *node, const RenderState *state,
01699                GeomNodeContext *gnc) {
01700 #if 0  // temporarily disabled until we bring to new scene graph
01701   if (gnc == (GeomNodeContext *)NULL) {
01702     // We don't have a saved context; just draw the GeomNode in
01703     // immediate mode.
01704     int num_geoms = node->get_num_geoms();
01705     for (int i = 0; i < num_geoms; i++) {
01706       node->get_geom(i)->draw(this);
01707     }
01708 
01709   } else {
01710     // We do have a saved context; use it.
01711     add_to_geom_node_record(gnc);
01712     CRGeomNodeContext *ggnc = DCAST(CRGeomNodeContext, gnc);
01713     chromium.CallList(ggnc->_index);
01714 
01715 #ifdef DO_PSTATS 
01716     PStatTimer timer(_draw_primitive_pcollector);
01717     _vertices_display_list_pcollector.add_level(ggnc->_num_verts);
01718 #endif
01719 
01720     // Also draw all the dynamic Geoms.
01721     int num_geoms = ggnc->_dynamic_geoms.size();
01722     for (int i = 0; i < num_geoms; i++) {
01723       ggnc->_dynamic_geoms[i]->draw(this);
01724     }
01725   }
01726 #endif  // temporarily disabled until we bring to new scene graph
01727 }
01728 
01729 ////////////////////////////////////////////////////////////////////
01730 //     Function: CRGraphicsStateGuardian::release_geom_node
01731 //       Access: Public, Virtual
01732 //  Description: Frees the resources previously allocated via a call
01733 //               to prepare_geom_node(), including deleting the
01734 //               GeomNodeContext itself, if necessary.
01735 ////////////////////////////////////////////////////////////////////
01736 void CRGraphicsStateGuardian::
01737 release_geom_node(GeomNodeContext *gnc) {
01738   if (gnc != (GeomNodeContext *)NULL) {
01739     CRGeomNodeContext *ggnc = DCAST(CRGeomNodeContext, gnc);
01740     chromium.DeleteLists(ggnc->_index, 1);
01741 
01742     bool erased = unmark_prepared_geom_node(ggnc);
01743 
01744     // If this assertion fails, a GeomNode was released that hadn't
01745     // been prepared (or a GeomNode was released twice).
01746     nassertv(erased);
01747     
01748     ggnc->_node->clear_gsg(this);
01749     delete ggnc;
01750   }
01751 }
01752 
01753 static int logs[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
01754                       4096, 0 };
01755 
01756 // This function returns the smallest power of two greater than or
01757 // equal to x.
01758 static int binary_log_cap(const int x) {
01759   int i = 0;
01760   for (; (x > logs[i]) && (logs[i] != 0); ++i);
01761   if (logs[i] == 0)
01762     return 4096;
01763   return logs[i];
01764 }
01765 
01766 ////////////////////////////////////////////////////////////////////
01767 //     Function: CRGraphicsStateGuardian::copy_texture
01768 //       Access: Public, Virtual
01769 //  Description: Copy the pixel region indicated by the display
01770 //               region from the framebuffer into texture memory
01771 ////////////////////////////////////////////////////////////////////
01772 void CRGraphicsStateGuardian::
01773 copy_texture(TextureContext *tc, const DisplayRegion *dr) {
01774   nassertv(tc != NULL && dr != NULL);
01775   //  activate();
01776 
01777   Texture *tex = tc->_texture;
01778 
01779   // Determine the size of the grab from the given display region
01780   // If the requested region is not a power of two, grab a region that is
01781   // a power of two that contains the requested region
01782   int xo, yo, req_w, req_h;
01783   dr->get_region_pixels(xo, yo, req_w, req_h);
01784   int w = binary_log_cap(req_w);
01785   int h = binary_log_cap(req_h);
01786   if (w != req_w || h != req_h) {
01787     tex->_requested_w = req_w;
01788     tex->_requested_h = req_h;
01789     tex->_has_requested_size = true;
01790   }
01791 
01792   PixelBuffer *pb = tex->_pbuffer;
01793 
01794   pb->set_xorg(xo);
01795   pb->set_yorg(yo);
01796   pb->set_xsize(w);
01797   pb->set_ysize(h);
01798 
01799   bind_texture(tc);
01800 
01801   chromium.CopyTexImage2D(GL_TEXTURE_2D, 0,
01802                    get_internal_image_format(pb->get_format()),
01803                    pb->get_xorg(), pb->get_yorg(),
01804                    pb->get_xsize(), pb->get_ysize(), pb->get_border());
01805   clear_attribute(TextureTransition::get_class_type());
01806 }
01807 
01808 ////////////////////////////////////////////////////////////////////
01809 //     Function: CRGraphicsStateGuardian::copy_texture
01810 //       Access: Public, Virtual
01811 //  Description:
01812 ////////////////////////////////////////////////////////////////////
01813 void CRGraphicsStateGuardian::
01814 copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb) {
01815   //  activate();
01816   set_read_buffer(rb);
01817   copy_texture(tc, dr);
01818 }
01819 
01820 ////////////////////////////////////////////////////////////////////
01821 //     Function: CRGraphicsStateGuardian::texture_to_pixel_buffer
01822 //       Access: Public, Virtual
01823 //  Description:
01824 ////////////////////////////////////////////////////////////////////
01825 void CRGraphicsStateGuardian::
01826 texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb) {
01827   nassertv(tc != NULL && pb != NULL);
01828   //  activate();
01829 
01830   Texture *tex = tc->_texture;
01831 
01832   int w = tex->_pbuffer->get_xsize();
01833   int h = tex->_pbuffer->get_ysize();
01834 
01835   PT(DisplayRegion) dr = _win->make_scratch_display_region(w, h);
01836 
01837   FrameBufferStack old_fb = push_frame_buffer
01838     (get_render_buffer(RenderBuffer::T_back | RenderBuffer::T_depth),
01839      dr);
01840 
01841   texture_to_pixel_buffer(tc, pb, dr);
01842 
01843   pop_frame_buffer(old_fb);
01844   report_errors();
01845 }
01846 
01847 ////////////////////////////////////////////////////////////////////
01848 //     Function: CRGraphicsStateGuardian::texture_to_pixel_buffer
01849 //       Access: Public, Virtual
01850 //  Description:
01851 ////////////////////////////////////////////////////////////////////
01852 void CRGraphicsStateGuardian::
01853 texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb,
01854                         const DisplayRegion *dr) {
01855   nassertv(tc != NULL && pb != NULL && dr != NULL);
01856   //  activate();
01857 
01858   Texture *tex = tc->_texture;
01859 
01860   // Do a deep copy to initialize the pixel buffer
01861   pb->copy(tex->_pbuffer);
01862 
01863   // If the image was empty, we need to render the texture into the frame
01864   // buffer and then copy the results into the pixel buffer's image
01865   if (pb->_image.empty()) {
01866     int w = pb->get_xsize();
01867     int h = pb->get_ysize();
01868     draw_texture(tc, dr);
01869     pb->_image = PTA_uchar::empty_array(w * h * pb->get_num_components());
01870     copy_pixel_buffer(pb, dr);
01871   }
01872   report_errors();
01873 }
01874 
01875 ////////////////////////////////////////////////////////////////////
01876 //     Function: CRGraphicsStateGuardian::copy_pixel_buffer
01877 //       Access: Public, Virtual
01878 //  Description:
01879 ////////////////////////////////////////////////////////////////////
01880 void CRGraphicsStateGuardian::
01881 copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
01882   nassertv(pb != NULL && dr != NULL);
01883   //  activate();
01884   set_pack_alignment(1);
01885 
01886   // Bug fix for RE, RE2, and VTX - need to disable texturing in order
01887   // for chromium.ReadPixels() to work
01888   // NOTE: reading the depth buffer is *much* slower than reading the
01889   // color buffer
01890   clear_attribute(TextureTransition::get_class_type());
01891 
01892   int xo, yo, w, h;
01893   dr->get_region_pixels(xo, yo, w, h);
01894 
01895 #ifdef GSG_VERBOSE
01896   crgsg_cat.debug()
01897     << "crReadPixels(" << pb->get_xorg() << ", " << pb->get_yorg()
01898     << ", " << pb->get_xsize() << ", " << pb->get_ysize()
01899     << ", ";
01900   switch (get_external_image_format(pb->get_format())) {
01901   case GL_DEPTH_COMPONENT:
01902     crgsg_cat.debug(false) << "GL_DEPTH_COMPONENT, ";
01903     break;
01904   case GL_RGB:
01905     crgsg_cat.debug(false) << "GL_RGB, ";
01906     break;
01907   case GL_RGBA:
01908     crgsg_cat.debug(false) << "GL_RGBA, ";
01909     break;
01910 #ifdef GL_BGR
01911   case GL_BGR:
01912     crgsg_cat.debug(false) << "GL_BGR, ";
01913     break;
01914   case GL_BGRA:
01915     crgsg_cat.debug(false) << "GL_BGRA, ";
01916     break;
01917 #endif  // GL_BGR
01918   default:
01919     crgsg_cat.debug(false) << "unknown, ";
01920     break;
01921   }
01922   switch (get_image_type(pb->get_image_type())) {
01923   case GL_UNSIGNED_BYTE:
01924     crgsg_cat.debug(false) << "GL_UNSIGNED_BYTE, ";
01925     break;
01926   case GL_FLOAT:
01927     crgsg_cat.debug(false) << "GL_FLOAT, ";
01928     break;
01929   default:
01930     crgsg_cat.debug(false) << "unknown, ";
01931     break;
01932   }
01933   crgsg_cat.debug(false)
01934     << (void *)pb->_image.p() << ")" << endl;
01935 #endif
01936 
01937   // pixelbuffer "origin" represents upper left screen point at which
01938   // pixelbuffer should be drawn using draw_pixel_buffer
01939   nassertv(!pb->_image.empty());
01940   chromium.ReadPixels(pb->get_xorg() + xo, pb->get_yorg() + yo,
01941                pb->get_xsize(), pb->get_ysize(),
01942                get_external_image_format(pb->get_format()),
01943                get_image_type(pb->get_image_type()),
01944                pb->_image.p());
01945 
01946   report_errors();
01947 }
01948 
01949 ////////////////////////////////////////////////////////////////////
01950 //     Function: CRGraphicsStateGuardian::copy_pixel_buffer
01951 //       Access: Public, Virtual
01952 //  Description:
01953 ////////////////////////////////////////////////////////////////////
01954 void CRGraphicsStateGuardian::
01955 copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
01956                   const RenderBuffer &rb) {
01957   //  activate();
01958   set_read_buffer(rb);
01959   copy_pixel_buffer(pb, dr);
01960 }
01961 
01962 ////////////////////////////////////////////////////////////////////
01963 //     Function: CRGraphicsStateGuardian::apply_material
01964 //       Access: Public, Virtual
01965 //  Description:
01966 ////////////////////////////////////////////////////////////////////
01967 void CRGraphicsStateGuardian::apply_material(const Material *material) {
01968   GLenum face = material->get_twoside() ? GL_FRONT_AND_BACK : GL_FRONT;
01969 
01970   chromium.Materialfv(face, GL_SPECULAR, material->get_specular().get_data());
01971   chromium.Materialfv(face, GL_EMISSION, material->get_emission().get_data());
01972   chromium.Materialf(face, GL_SHININESS, material->get_shininess());
01973 
01974   if (material->has_ambient() && material->has_diffuse()) {
01975     // The material has both an ambient and diffuse specified.  This
01976     // means we do not need chromium.MaterialColor().
01977     chromium.Disable(GL_COLOR_MATERIAL);
01978     chromium.Materialfv(face, GL_AMBIENT, material->get_ambient().get_data());
01979     chromium.Materialfv(face, GL_DIFFUSE, material->get_diffuse().get_data());
01980 
01981   } else if (material->has_ambient()) {
01982     // The material specifies an ambient, but not a diffuse component.
01983     // The diffuse component comes from the object's color.
01984     chromium.Materialfv(face, GL_AMBIENT, material->get_ambient().get_data());
01985     chromium.ColorMaterial(face, GL_DIFFUSE);
01986     chromium.Enable(GL_COLOR_MATERIAL);
01987 
01988   } else if (material->has_diffuse()) {
01989     // The material specifies a diffuse, but not an ambient component.
01990     // The ambient component comes from the object's color.
01991     chromium.Materialfv(face, GL_DIFFUSE, material->get_diffuse().get_data());
01992     chromium.ColorMaterial(face, GL_AMBIENT);
01993     chromium.Enable(GL_COLOR_MATERIAL);
01994 
01995   } else {
01996     // The material specifies neither a diffuse nor an ambient
01997     // component.  Both components come from the object's color.
01998     chromium.ColorMaterial(face, GL_AMBIENT_AND_DIFFUSE);
01999     chromium.Enable(GL_COLOR_MATERIAL);
02000   }
02001 
02002   call_glLightModelLocal(material->get_local());
02003   call_glLightModelTwoSide(material->get_twoside());
02004   report_errors();
02005 }
02006 
02007 ////////////////////////////////////////////////////////////////////
02008 //     Function: CRGraphicsStateGuardian::apply_fog
02009 //       Access: Public, Virtual
02010 //  Description:
02011 ////////////////////////////////////////////////////////////////////
02012 void CRGraphicsStateGuardian::
02013 apply_fog(Fog *fog) {
02014   Fog::Mode fmode = fog->get_mode();
02015   call_glFogMode(get_fog_mode_type((Fog::Mode)fmode));
02016 
02017   if (fmode == Fog::M_linear) {
02018     float onset, opaque;
02019     fog->get_linear_range(onset, opaque);
02020     call_glFogStart(onset);
02021     call_glFogEnd(opaque);
02022 
02023   } else {
02024     // Exponential fog is always camera-relative.
02025     call_glFogDensity(fog->get_exp_density());
02026   }
02027 
02028   call_glFogColor(fog->get_color());
02029   report_errors();
02030 }
02031 
02032 ////////////////////////////////////////////////////////////////////
02033 //     Function: CRGraphicsStateGuardian::issue_transform
02034 //       Access: Public, Virtual
02035 //  Description: Sends the indicated transform matrix to the graphics
02036 //               API to be applied to future vertices.
02037 ////////////////////////////////////////////////////////////////////
02038 void CRGraphicsStateGuardian::
02039 issue_transform(const TransformState *transform) {
02040 #ifdef GSG_VERBOSE
02041   crgsg_cat.debug()
02042     << "crLoadMatrix(GL_MODELVIEW): " << transform->get_mat() << endl;
02043 #endif
02044   chromium.MatrixMode(GL_MODELVIEW);
02045   chromium.LoadMatrixf(transform->get_mat().get_data());
02046 
02047   report_errors();
02048 }
02049 
02050 ////////////////////////////////////////////////////////////////////
02051 //     Function: CRGraphicsStateGuardian::issue_tex_matrix
02052 //       Access: Public, Virtual
02053 //  Description:
02054 ////////////////////////////////////////////////////////////////////
02055 void CRGraphicsStateGuardian::
02056 issue_tex_matrix(const TexMatrixAttrib *attrib) {
02057   chromium.MatrixMode(GL_TEXTURE);
02058   chromium.LoadMatrixf(attrib->get_mat().get_data());
02059   report_errors();
02060 }
02061 
02062 ////////////////////////////////////////////////////////////////////
02063 //     Function: CRGraphicsStateGuardian::issue_texture
02064 //       Access: Public, Virtual
02065 //  Description:
02066 ////////////////////////////////////////////////////////////////////
02067 void CRGraphicsStateGuardian::
02068 issue_texture(const TextureAttrib *attrib) {
02069   if (attrib->is_off()) {
02070     enable_texturing(false);
02071   } else {
02072     enable_texturing(true);
02073     Texture *tex = attrib->get_texture();
02074     nassertv(tex != (Texture *)NULL);
02075     tex->apply(this);
02076   }
02077   report_errors();
02078 }
02079 
02080 ////////////////////////////////////////////////////////////////////
02081 //     Function: CRGraphicsStateGuardian::issue_material
02082 //       Access: Public, Virtual
02083 //  Description:
02084 ////////////////////////////////////////////////////////////////////
02085 void CRGraphicsStateGuardian::
02086 issue_material(const MaterialAttrib *attrib) {
02087   const Material *material = attrib->get_material();
02088   if (material != (const Material *)NULL) {
02089     apply_material(material);
02090   } else {
02091     // Apply a default material when materials are turned off.
02092     Material empty;
02093     apply_material(&empty);
02094   }
02095   report_errors();
02096 }
02097 
02098 ////////////////////////////////////////////////////////////////////
02099 //     Function: CRGraphicsStateGuardian::issue_render_mode
02100 //       Access: Public, Virtual
02101 //  Description:
02102 ////////////////////////////////////////////////////////////////////
02103 void CRGraphicsStateGuardian::
02104 issue_render_mode(const RenderModeAttrib *attrib) {
02105   RenderModeAttrib::Mode mode = attrib->get_mode();
02106 
02107   switch (mode) {
02108   case RenderModeAttrib::M_filled:
02109     call_glPolygonMode(GL_FILL);
02110     break;
02111 
02112   case RenderModeAttrib::M_wireframe:
02113     call_glLineWidth(attrib->get_line_width());
02114     call_glPolygonMode(GL_LINE);
02115     break;
02116 
02117   default:
02118     crgsg_cat.error()
02119       << "Unknown render mode " << (int)mode << endl;
02120   }
02121   report_errors();
02122 }
02123 
02124 ////////////////////////////////////////////////////////////////////
02125 //     Function: CRGraphicsStateGuardian::issue_texture_apply
02126 //       Access: Public, Virtual
02127 //  Description:
02128 ////////////////////////////////////////////////////////////////////
02129 void CRGraphicsStateGuardian::
02130 issue_texture_apply(const TextureApplyAttrib *attrib) {
02131   GLint glmode = get_texture_apply_mode_type(attrib->get_mode());
02132   chromium.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glmode);
02133   report_errors();
02134 }
02135 
02136 ////////////////////////////////////////////////////////////////////
02137 //     Function: CRGraphicsStateGuardian::issue_color_write
02138 //       Access: Public, Virtual
02139 //  Description:
02140 ////////////////////////////////////////////////////////////////////
02141 void CRGraphicsStateGuardian::
02142 issue_color_write(const ColorWriteAttrib *attrib) {
02143   // If we did not override this function, the default implementation
02144   // would achieve turning off color writes by changing the blend mode
02145   // in set_blend_mode().  However, since GL does support an easy way
02146   // to disable writes to the color buffer, we can take advantage of
02147   // it here.
02148   ColorWriteAttrib::Mode mode = attrib->get_mode();
02149   if (mode == ColorWriteAttrib::M_off) {
02150     chromium.ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
02151   } else {
02152     chromium.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
02153   }
02154   report_errors();
02155 }
02156 
02157 ////////////////////////////////////////////////////////////////////
02158 //     Function: CRGraphicsStateGuardian::issue_depth_test
02159 //       Access: Public, Virtual
02160 //  Description:
02161 ////////////////////////////////////////////////////////////////////
02162 void CRGraphicsStateGuardian::
02163 issue_depth_test(const DepthTestAttrib *attrib) {
02164   DepthTestAttrib::Mode mode = attrib->get_mode();
02165   if (mode == DepthTestAttrib::M_none) {
02166     enable_depth_test(false);
02167   } else {
02168     enable_depth_test(true);
02169     chromium.DepthFunc(get_depth_func_type(mode));
02170   }
02171   report_errors();
02172 }
02173 
02174 ////////////////////////////////////////////////////////////////////
02175 //     Function: CRGraphicsStateGuardian::issue_depth_write
02176 //       Access: Public, Virtual
02177 //  Description:
02178 ////////////////////////////////////////////////////////////////////
02179 void CRGraphicsStateGuardian::
02180 issue_depth_write(const DepthWriteAttrib *attrib) {
02181   DepthWriteAttrib::Mode mode = attrib->get_mode();
02182   if (mode == DepthWriteAttrib::M_off) {
02183     chromium.DepthMask(GL_FALSE);
02184   } else {
02185     chromium.DepthMask(GL_TRUE);
02186   }
02187   report_errors();
02188 }
02189 
02190 ////////////////////////////////////////////////////////////////////
02191 //     Function: CRGraphicsStateGuardian::issue_cull_face
02192 //       Access: Public, Virtual
02193 //  Description:
02194 ////////////////////////////////////////////////////////////////////
02195 void CRGraphicsStateGuardian::
02196 issue_cull_face(const CullFaceAttrib *attrib) {
02197   CullFaceAttrib::Mode mode = attrib->get_mode();
02198 
02199   switch (mode) {
02200   case CullFaceAttrib::M_cull_none:
02201     chromium.Disable(GL_CULL_FACE);
02202     break;
02203   case CullFaceAttrib::M_cull_clockwise:
02204     chromium.Enable(GL_CULL_FACE);
02205     chromium.CullFace(GL_BACK);
02206     break;
02207   case CullFaceAttrib::M_cull_counter_clockwise:
02208     chromium.Enable(GL_CULL_FACE);
02209     chromium.CullFace(GL_FRONT);
02210     break;
02211   default:
02212     crgsg_cat.error()
02213       << "invalid cull face mode " << (int)mode << endl;
02214     break;
02215   }
02216   report_errors();
02217 }
02218 
02219 ////////////////////////////////////////////////////////////////////
02220 //     Function: CRGraphicsStateGuardian::issue_fog
02221 //       Access: Public, Virtual
02222 //  Description:
02223 ////////////////////////////////////////////////////////////////////
02224 void CRGraphicsStateGuardian::
02225 issue_fog(const FogAttrib *attrib) {
02226   if (!attrib->is_off()) {
02227     enable_fog(true);
02228     Fog *fog = attrib->get_fog();
02229     nassertv(fog != (Fog *)NULL);
02230     apply_fog(fog);
02231   } else {
02232     enable_fog(false);
02233   }
02234   report_errors();
02235 }
02236 
02237 ////////////////////////////////////////////////////////////////////
02238 //     Function: CRGraphicsStateGuardian::issue_depth_offset
02239 //       Access: Public, Virtual
02240 //  Description:
02241 ////////////////////////////////////////////////////////////////////
02242 void CRGraphicsStateGuardian::
02243 issue_depth_offset(const DepthOffsetAttrib *attrib) {
02244   int offset = attrib->get_offset();
02245 
02246   if (offset != 0) {
02247     // The relationship between these two parameters is a little
02248     // unclear and poorly explained in the GL man pages.
02249     chromium.PolygonOffset((GLfloat) -offset, (GLfloat) -offset);
02250     enable_polygon_offset(true);
02251 
02252   } else {
02253     enable_polygon_offset(false);
02254   }
02255 
02256   report_errors();
02257 }
02258 
02259 ////////////////////////////////////////////////////////////////////
02260 //     Function: CRGraphicsStateGuardian::bind_light
02261 //       Access: Public, Virtual
02262 //  Description: Called the first time a particular light has been
02263 //               bound to a given id within a frame, this should set
02264 //               up the associated hardware light with the light's
02265 //               properties.
02266 ////////////////////////////////////////////////////////////////////
02267 void CRGraphicsStateGuardian::
02268 bind_light(PointLight *light, int light_id) {
02269   GLenum id = get_light_id(light_id);
02270   static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
02271   chromium.Lightfv(id, GL_AMBIENT, black.get_data());
02272   chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data());
02273   chromium.Lightfv(id, GL_SPECULAR, light->get_specular_color().get_data());
02274 
02275   // Position needs to specify x, y, z, and w
02276   // w == 1 implies non-infinite position
02277   NodePath light_np(light);
02278   const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
02279   LPoint3f pos = light->get_point() * light_mat;
02280 
02281   LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f);
02282   chromium.Lightfv(id, GL_POSITION, fpos.get_data());
02283 
02284   // GL_SPOT_DIRECTION is not significant when cutoff == 180
02285 
02286   // Exponent == 0 implies uniform light distribution
02287   chromium.Lightf(id, GL_SPOT_EXPONENT, 0.0f);
02288 
02289   // Cutoff == 180 means uniform point light source
02290   chromium.Lightf(id, GL_SPOT_CUTOFF, 180.0f);
02291 
02292   const LVecBase3f &att = light->get_attenuation();
02293   chromium.Lightf(id, GL_CONSTANT_ATTENUATION, att[0]);
02294   chromium.Lightf(id, GL_LINEAR_ATTENUATION, att[1]);
02295   chromium.Lightf(id, GL_QUADRATIC_ATTENUATION, att[2]);
02296 
02297   report_errors();
02298 }
02299 
02300 ////////////////////////////////////////////////////////////////////
02301 //     Function: CRGraphicsStateGuardian::bind_light
02302 //       Access: Public, Virtual
02303 //  Description: Called the first time a particular light has been
02304 //               bound to a given id within a frame, this should set
02305 //               up the associated hardware light with the light's
02306 //               properties.
02307 ////////////////////////////////////////////////////////////////////
02308 void CRGraphicsStateGuardian::
02309 bind_light(DirectionalLight *light, int light_id) {
02310   GLenum id = get_light_id( light_id );
02311   static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
02312   chromium.Lightfv(id, GL_AMBIENT, black.get_data());
02313   chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data());
02314   chromium.Lightfv(id, GL_SPECULAR, light->get_specular_color().get_data());
02315 
02316   // Position needs to specify x, y, z, and w.
02317   // w == 0 implies light is at infinity
02318   NodePath light_np(light);
02319   const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
02320   LVector3f dir = light->get_direction() * light_mat;
02321   LPoint4f fdir(-dir[0], -dir[1], -dir[2], 0);
02322   chromium.Lightfv(id, GL_POSITION, fdir.get_data());
02323 
02324   // GL_SPOT_DIRECTION is not significant when cutoff == 180
02325   // In this case, position x, y, z specifies direction
02326 
02327   // Exponent == 0 implies uniform light distribution
02328   chromium.Lightf(id, GL_SPOT_EXPONENT, 0.0f);
02329 
02330   // Cutoff == 180 means uniform point light source
02331   chromium.Lightf(id, GL_SPOT_CUTOFF, 180.0f);
02332 
02333   // Default attenuation values (only spotlight and point light can
02334   // modify these)
02335   chromium.Lightf(id, GL_CONSTANT_ATTENUATION, 1.0f);
02336   chromium.Lightf(id, GL_LINEAR_ATTENUATION, 0.0f);
02337   chromium.Lightf(id, GL_QUADRATIC_ATTENUATION, 0.0f);
02338 
02339   report_errors();
02340 }
02341 
02342 ////////////////////////////////////////////////////////////////////
02343 //     Function: CRGraphicsStateGuardian::bind_light
02344 //       Access: Public, Virtual
02345 //  Description: Called the first time a particular light has been
02346 //               bound to a given id within a frame, this should set
02347 //               up the associated hardware light with the light's
02348 //               properties.
02349 ////////////////////////////////////////////////////////////////////
02350 void CRGraphicsStateGuardian::
02351 bind_light(Spotlight *light, int light_id) {
02352   Lens *lens = light->get_lens();
02353   nassertv(lens != (Lens *)NULL);
02354 
02355   GLenum id = get_light_id(light_id);
02356   static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
02357   chromium.Lightfv(id, GL_AMBIENT, black.get_data());
02358   chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data());
02359   chromium.Lightfv(id, GL_SPECULAR, light->get_specular_color().get_data());
02360 
02361   // Position needs to specify x, y, z, and w
02362   // w == 1 implies non-infinite position
02363   NodePath light_np(light);
02364   const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root());
02365   LPoint3f pos = lens->get_nodal_point() * light_mat;
02366   LVector3f dir = lens->get_view_vector() * light_mat;
02367 
02368   LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f);
02369   chromium.Lightfv(id, GL_POSITION, fpos.get_data());
02370   chromium.Lightfv(id, GL_SPOT_DIRECTION, dir.get_data());
02371 
02372   chromium.Lightf(id, GL_SPOT_EXPONENT, light->get_exponent());
02373   chromium.Lightf(id, GL_SPOT_CUTOFF, lens->get_hfov());
02374 
02375   const LVecBase3f &att = light->get_attenuation();
02376   chromium.Lightf(id, GL_CONSTANT_ATTENUATION, att[0]);
02377   chromium.Lightf(id, GL_LINEAR_ATTENUATION, att[1]);
02378   chromium.Lightf(id, GL_QUADRATIC_ATTENUATION, att[2]);
02379 
02380   report_errors();
02381 }
02382 
02383 ////////////////////////////////////////////////////////////////////
02384 //     Function: CRGraphicsStateGuardian::wants_normals
02385 //       Access: Public, Virtual
02386 //  Description:
02387 ////////////////////////////////////////////////////////////////////
02388 bool CRGraphicsStateGuardian::
02389 wants_normals() const {
02390   return (_lighting_enabled || _normals_enabled);
02391 }
02392 
02393 ////////////////////////////////////////////////////////////////////
02394 //     Function: CRGraphicsStateGuardian::wants_texcoords
02395 //       Access: Public, Virtual
02396 //  Description:
02397 ////////////////////////////////////////////////////////////////////
02398 bool CRGraphicsStateGuardian::
02399 wants_texcoords() const {
02400   return _texturing_enabled;
02401 }
02402 
02403 ////////////////////////////////////////////////////////////////////
02404 //     Function: CRGraphicsStateGuardian::depth_offset_decals
02405 //       Access: Public, Virtual
02406 //  Description: Returns true if this GSG can implement decals using a
02407 //               DepthOffsetAttrib, or false if that is unreliable
02408 //               and the three-step rendering process should be used
02409 //               instead.
02410 ////////////////////////////////////////////////////////////////////
02411 bool CRGraphicsStateGuardian::
02412 depth_offset_decals() {
02413   return cr_depth_offset_decals;
02414 }
02415 
02416 ////////////////////////////////////////////////////////////////////
02417 //     Function: CRGraphicsStateGuardian::get_internal_coordinate_system
02418 //       Access: Public, Virtual
02419 //  Description: Should be overridden by derived classes to return the
02420 //               coordinate system used internally by the GSG, if any
02421 //               one particular coordinate system is used.  The
02422 //               default, CS_default, indicates that the GSG can use
02423 //               any coordinate system.
02424 //
02425 //               If this returns other than CS_default, the
02426 //               GraphicsEngine will automatically convert all
02427 //               transforms into the indicated coordinate system.
02428 ////////////////////////////////////////////////////////////////////
02429 CoordinateSystem CRGraphicsStateGuardian::
02430 get_internal_coordinate_system() const {
02431   return CS_yup_right;
02432 }
02433 
02434 ////////////////////////////////////////////////////////////////////
02435 //     Function: CRGraphicsStateGuardian::compute_distance_to
02436 //       Access: Public, Virtual
02437 //  Description: This function may only be called during a render
02438 //               traversal; it will compute the distance to the
02439 //               indicated point, assumed to be in modelview
02440 //               coordinates, from the camera plane.
02441 ////////////////////////////////////////////////////////////////////
02442 float CRGraphicsStateGuardian::
02443 compute_distance_to(const LPoint3f &point) const {
02444   // In the case of a CRGraphicsStateGuardian, we know that the
02445   // modelview matrix already includes the relative transform from the
02446   // camera, as well as a to-y-up conversion.  Thus, the distance to
02447   // the camera plane is simply the -z distance.
02448 
02449   return -point[2];
02450 }
02451 
02452 ////////////////////////////////////////////////////////////////////
02453 //     Function: report_errors_loop
02454 //       Access: Protected
02455 //  Description: The internal implementation of report_errors().
02456 //               Don't call this function; use report_errors()
02457 //               instead.
02458 ////////////////////////////////////////////////////////////////////
02459 
02460 void report_errors_loop(GLenum error_code) {
02461 #ifndef NDEBUG
02462 #define MAXGLERRORSREPORTED 20
02463   int cnt=0;
02464   while ((cnt<MAXGLERRORSREPORTED) && (error_code != GL_NO_ERROR)) {
02465     const GLubyte *error_string = gluErrorString(error_code);
02466     if (error_string != (const GLubyte *)NULL) {
02467       crgsg_cat.error() << error_string << "\n";
02468     } else {
02469       crgsg_cat.error()
02470         << "Error number " << (int)error_code << "; no string available.\n";
02471     }
02472     error_code = chromium.GetError();
02473     cnt++;
02474   }
02475 #endif
02476 }
02477 
02478 ////////////////////////////////////////////////////////////////////
02479 //     Function: CRGraphicsStateGuardian::set_draw_buffer
02480 //       Access: Protected
02481 //  Description: Sets up the chromium.DrawBuffer to render into the buffer
02482 //               indicated by the RenderBuffer object.  This only sets
02483 //               up the color bits; it does not affect the depth,
02484 //               stencil, accum layers.
02485 ////////////////////////////////////////////////////////////////////
02486 void CRGraphicsStateGuardian::
02487 set_draw_buffer(const RenderBuffer &rb) {
02488   switch (rb._buffer_type & RenderBuffer::T_color) {
02489   case RenderBuffer::T_front:
02490     call_glDrawBuffer(GL_FRONT);
02491     break;
02492 
02493   case RenderBuffer::T_back:
02494     call_glDrawBuffer(GL_BACK);
02495     break;
02496 
02497   case RenderBuffer::T_right:
02498     call_glDrawBuffer(GL_RIGHT);
02499     break;
02500 
02501   case RenderBuffer::T_left:
02502     call_glDrawBuffer(GL_LEFT);
02503     break;
02504 
02505   case RenderBuffer::T_front_right:
02506     call_glDrawBuffer(GL_FRONT_RIGHT);
02507     break;
02508 
02509   case RenderBuffer::T_front_left:
02510     call_glDrawBuffer(GL_FRONT_LEFT);
02511     break;
02512 
02513   case RenderBuffer::T_back_right:
02514     call_glDrawBuffer(GL_BACK_RIGHT);
02515     break;
02516 
02517   case RenderBuffer::T_back_left:
02518     call_glDrawBuffer(GL_BACK_LEFT);
02519     break;
02520 
02521   default:
02522     call_glDrawBuffer(GL_FRONT_AND_BACK);
02523   }
02524   report_errors();
02525 }
02526 
02527 ////////////////////////////////////////////////////////////////////
02528 //     Function: CRGraphicsStateGuardian::set_read_buffer
02529 //       Access: Protected
02530 //  Description: Sets up the chromium.ReadBuffer to render into the buffer
02531 //               indicated by the RenderBuffer object.  This only sets
02532 //               up the color bits; it does not affect the depth,
02533 //               stencil, accum layers.
02534 ////////////////////////////////////////////////////////////////////
02535 void CRGraphicsStateGuardian::
02536 set_read_buffer(const RenderBuffer &rb) {
02537   switch (rb._buffer_type & RenderBuffer::T_color) {
02538   case RenderBuffer::T_front:
02539     call_glReadBuffer(GL_FRONT);
02540     break;
02541 
02542   case RenderBuffer::T_back:
02543     call_glReadBuffer(GL_BACK);
02544     break;
02545 
02546   case RenderBuffer::T_right:
02547     call_glReadBuffer(GL_RIGHT);
02548     break;
02549 
02550   case RenderBuffer::T_left:
02551     call_glReadBuffer(GL_LEFT);
02552     break;
02553 
02554   case RenderBuffer::T_front_right:
02555     call_glReadBuffer(GL_FRONT_RIGHT);
02556     break;
02557 
02558   case RenderBuffer::T_front_left:
02559     call_glReadBuffer(GL_FRONT_LEFT);
02560     break;
02561 
02562   case RenderBuffer::T_back_right:
02563     call_glReadBuffer(GL_BACK_RIGHT);
02564     break;
02565 
02566   case RenderBuffer::T_back_left:
02567     call_glReadBuffer(GL_BACK_LEFT);
02568     break;
02569 
02570   default:
02571     call_glReadBuffer(GL_FRONT_AND_BACK);
02572   }
02573   report_errors();
02574 }
02575 
02576 
02577 ////////////////////////////////////////////////////////////////////
02578 //     Function: CRGraphicsStateGuardian::bind_texture
02579 //       Access: Protected
02580 //  Description:
02581 ////////////////////////////////////////////////////////////////////
02582 void CRGraphicsStateGuardian::
02583 bind_texture(TextureContext *tc) {
02584   //  activate();
02585   CRTextureContext *gtc = DCAST(CRTextureContext, tc);
02586 
02587 #ifdef GSG_VERBOSE
02588   Texture *tex = tc->_texture;
02589   crgsg_cat.debug()
02590     << "crBindTexture(): " << tex->get_name() << "(" << (int)gtc->_index
02591     << ")" << endl;
02592 #endif
02593   chromium.BindTexture(GL_TEXTURE_2D, gtc->_index);
02594   report_errors();
02595 }
02596 
02597 ////////////////////////////////////////////////////////////////////
02598 //     Function: CRGraphicsStateGuardian::specify_texture
02599 //       Access: Protected
02600 //  Description:
02601 ////////////////////////////////////////////////////////////////////
02602 void CRGraphicsStateGuardian::
02603 specify_texture(Texture *tex) {
02604   chromium.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
02605                   get_texture_wrap_mode(tex->get_wrapu()));
02606   chromium.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
02607                   get_texture_wrap_mode(tex->get_wrapv()));
02608 
02609   if (cr_force_mipmaps) {
02610     chromium.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
02611                     GL_LINEAR_MIPMAP_LINEAR);
02612     chromium.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02613 
02614   } else {
02615     chromium.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
02616                     get_texture_filter_type(tex->get_minfilter()));
02617     chromium.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
02618                     get_texture_filter_type(tex->get_magfilter()));
02619   }
02620   report_errors();
02621 }
02622 
02623 #ifndef NDEBUG
02624 ////////////////////////////////////////////////////////////////////
02625 //     Function: compute_cr_image_size
02626 //  Description: Calculates how many bytes GL will expect to read for
02627 //               a texture image, based on the number of pixels and
02628 //               the GL format and type.  This is only used for
02629 //               debugging.
02630 ////////////////////////////////////////////////////////////////////
02631 static int
02632 compute_cr_image_size(int xsize, int ysize, int external_format, int type) {
02633   int num_components = 0;
02634   switch (external_format) {
02635   case GL_COLOR_INDEX:
02636   case GL_STENCIL_INDEX:
02637   case GL_DEPTH_COMPONENT:
02638   case GL_RED:
02639   case GL_GREEN:
02640   case GL_BLUE:
02641   case GL_ALPHA:
02642   case GL_LUMINANCE:
02643     num_components = 1;
02644     break;
02645 
02646   case GL_LUMINANCE_ALPHA:
02647     num_components = 2;
02648     break;
02649 
02650 #ifdef GL_BGR
02651   case GL_BGR:
02652 #endif
02653   case GL_RGB:
02654     num_components = 3;
02655     break;
02656 
02657 #ifdef GL_BGR
02658   case GL_BGRA:
02659 #endif
02660   case GL_RGBA:
02661     num_components = 4;
02662     break;
02663   }
02664 
02665   int pixel_width = 0;
02666   switch (type) {
02667   case GL_UNSIGNED_BYTE:
02668     pixel_width = 1 * num_components;
02669     break;
02670 
02671   case GL_UNSIGNED_SHORT:
02672     pixel_width = 2 * num_components;
02673     break;
02674 
02675 #ifdef GL_UNSIGNED_BYTE_3_3_2_EXT
02676   case GL_UNSIGNED_BYTE_3_3_2_EXT:
02677     nassertr(num_components == 3, 0);
02678     pixel_width = 1;
02679     break;
02680 #endif
02681 
02682   case GL_FLOAT:
02683     pixel_width = 4 * num_components;
02684     break;
02685   }
02686 
02687   return xsize * ysize * pixel_width;
02688 }
02689 #endif  // NDEBUG
02690 
02691 ////////////////////////////////////////////////////////////////////
02692 //     Function: CRGraphicsStateGuardian::uchar_bgr_to_rgb
02693 //  Description: Recopies the given array of pixels, converting from
02694 //               BGR to RGB arrangement.
02695 ////////////////////////////////////////////////////////////////////
02696 static void
02697 uchar_bgr_to_rgb(unsigned char *dest, const unsigned char *source, 
02698                  int num_pixels) {
02699   for (int i = 0; i < num_pixels; i++) {
02700     dest[0] = source[2];
02701     dest[1] = source[1];
02702     dest[2] = source[0];
02703     dest += 3;
02704     source += 3;
02705   }
02706 }
02707 
02708 ////////////////////////////////////////////////////////////////////
02709 //     Function: CRGraphicsStateGuardian::uchar_bgra_to_rgba
02710 //  Description: Recopies the given array of pixels, converting from
02711 //               BGRA to RGBA arrangement.
02712 ////////////////////////////////////////////////////////////////////
02713 static void
02714 uchar_bgra_to_rgba(unsigned char *dest, const unsigned char *source, 
02715                    int num_pixels) {
02716   for (int i = 0; i < num_pixels; i++) {
02717     dest[0] = source[2];
02718     dest[1] = source[1];
02719     dest[2] = source[0];
02720     dest[3] = source[3];
02721     dest += 4;
02722     source += 4;
02723   }
02724 }
02725 
02726 ////////////////////////////////////////////////////////////////////
02727 //     Function: CRGraphicsStateGuardian::apply_texture_immediate
02728 //       Access: Protected
02729 //  Description: Sends the texture image to GL.  This can be used to
02730 //               render a texture in immediate mode, or as part of the
02731 //               process of creating a GL texture object.
02732 //
02733 //               The return value is true if successful, or false if
02734 //               the texture has no image.
02735 ////////////////////////////////////////////////////////////////////
02736 bool CRGraphicsStateGuardian::
02737 apply_texture_immediate(Texture *tex) {
02738   PixelBuffer *pb = tex->get_ram_image();
02739   if (pb == (PixelBuffer *)NULL) {
02740     return false;
02741   }
02742 
02743   int xsize = pb->get_xsize();
02744   int ysize = pb->get_ysize();
02745   int num_pixels = xsize * ysize;
02746 
02747   GLenum internal_format = get_internal_image_format(pb->get_format());
02748   GLenum external_format = get_external_image_format(pb->get_format());
02749   GLenum type = get_image_type(pb->get_image_type());
02750 
02751   uchar *image = pb->_image;
02752   uchar *locally_allocated_image = (uchar *)NULL;
02753   if (!cr_supports_bgr) {
02754     // If the GL doesn't claim to support BGR, we may have to reverse
02755     // the byte ordering of the image.
02756     if (external_format == GL_RGB && pb->get_image_type() == PixelBuffer::T_unsigned_byte) {
02757       locally_allocated_image = new uchar[num_pixels * 3];
02758       image = locally_allocated_image;
02759       uchar_bgr_to_rgb(image, pb->_image, num_pixels);
02760     } else if (external_format == GL_RGBA && pb->get_image_type() == PixelBuffer::T_unsigned_byte) {
02761       locally_allocated_image = new uchar[num_pixels * 4];
02762       image = locally_allocated_image;
02763       uchar_bgra_to_rgba(image, pb->_image, num_pixels);
02764     }
02765   }
02766 
02767 #ifndef NDEBUG
02768   int wanted_size = 
02769     compute_cr_image_size(xsize, ysize,
02770                           external_format, type);
02771   nassertr(wanted_size == (int)pb->_image.size(), false);
02772 #endif  // NDEBUG
02773 
02774   set_unpack_alignment(1);
02775 
02776 #ifdef GSG_VERBOSE
02777   crgsg_cat.debug()
02778     << "crTexImage2D(GL_TEXTURE_2D, "
02779     << (int)internal_format << ", "
02780     << xsize << ", " << ysize << ", "
02781     << pb->get_border() << ", " << (int)external_format << ", "
02782     << (int)type << ", " << tex->get_name() << ")\n";
02783 #endif
02784 
02785   if (!cr_ignore_mipmaps || cr_force_mipmaps) {
02786     if (tex->uses_mipmaps() || cr_force_mipmaps) {
02787 #ifndef NDEBUG
02788       if (cr_show_mipmaps) {
02789         build_phony_mipmaps(tex);
02790       } else 
02791 #endif
02792         {
02793           gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format,
02794                             xsize, ysize,
02795                             external_format, type, image);
02796 #ifndef NDEBUG
02797           if (cr_save_mipmaps) {
02798             save_mipmap_images(tex);
02799           }
02800 #endif
02801         }
02802       report_errors();
02803 
02804       if (locally_allocated_image != (uchar *)NULL) {
02805         delete[] locally_allocated_image;
02806       }
02807       return true;
02808     }
02809   }
02810 
02811   nassertr(!pb->_image.empty(), false);
02812   chromium.TexImage2D(GL_TEXTURE_2D, 0, internal_format,
02813                xsize, ysize, pb->get_border(),
02814                external_format, type, image);
02815   report_errors();
02816 
02817   if (locally_allocated_image != (uchar *)NULL) {
02818     delete[] locally_allocated_image;
02819   }
02820   return true;
02821 }
02822 
02823 ////////////////////////////////////////////////////////////////////
02824 //     Function: CRGraphicsStateGuardian::get_texture_wrap_mode
02825 //       Access: Protected
02826 //  Description: Maps from the Texture's internal wrap mode symbols to
02827 //               GL's.
02828 ////////////////////////////////////////////////////////////////////
02829 GLenum CRGraphicsStateGuardian::
02830 get_texture_wrap_mode(Texture::WrapMode wm) {
02831   switch (wm) {
02832   case Texture::WM_clamp:
02833     return GL_CLAMP;
02834   case Texture::WM_repeat:
02835     return GL_REPEAT;
02836 
02837   case Texture::WM_mirror:
02838   case Texture::WM_mirror_once:
02839   case Texture::WM_border_color:
02840     // These are unsupported for now.
02841     return GL_REPEAT;
02842 
02843   case Texture::WM_invalid:
02844     break;
02845   }
02846   crgsg_cat.error() << "Invalid Texture::WrapMode value!\n";
02847   return GL_CLAMP;
02848 }
02849 
02850 ////////////////////////////////////////////////////////////////////
02851 //     Function: CRGraphicsStateGuardian::get_texture_filter_type
02852 //       Access: Protected
02853 //  Description: Maps from the Texture's internal filter type symbols
02854 //               to GL's.
02855 ////////////////////////////////////////////////////////////////////
02856 GLenum CRGraphicsStateGuardian::
02857 get_texture_filter_type(Texture::FilterType ft) {
02858   if (cr_ignore_mipmaps) {
02859     switch (ft) {
02860     case Texture::FT_nearest_mipmap_nearest:
02861     case Texture::FT_nearest:
02862       return GL_NEAREST;
02863     case Texture::FT_linear:
02864     case Texture::FT_linear_mipmap_nearest:
02865     case Texture::FT_nearest_mipmap_linear:
02866     case Texture::FT_linear_mipmap_linear:
02867       return GL_LINEAR;
02868     case Texture::FT_invalid:
02869       break;
02870     }
02871   } else {
02872     switch (ft) {
02873     case Texture::FT_nearest:
02874       return GL_NEAREST;
02875     case Texture::FT_linear:
02876       return GL_LINEAR;
02877     case Texture::FT_nearest_mipmap_nearest:
02878       return GL_NEAREST_MIPMAP_NEAREST;
02879     case Texture::FT_linear_mipmap_nearest:
02880       return GL_LINEAR_MIPMAP_NEAREST;
02881     case Texture::FT_nearest_mipmap_linear:
02882       return GL_NEAREST_MIPMAP_LINEAR;
02883     case Texture::FT_linear_mipmap_linear:
02884       return GL_LINEAR_MIPMAP_LINEAR;
02885     case Texture::FT_invalid:
02886       break;
02887     }
02888   }
02889   crgsg_cat.error() << "Invalid Texture::FilterType value!\n";
02890   return GL_NEAREST;
02891 }
02892 
02893 ////////////////////////////////////////////////////////////////////
02894 //     Function: CRGraphicsStateGuardian::get_image_type
02895 //       Access: Protected
02896 //  Description: Maps from the PixelBuffer's internal Type symbols
02897 //               to GL's.
02898 ////////////////////////////////////////////////////////////////////
02899 GLenum CRGraphicsStateGuardian::
02900 get_image_type(PixelBuffer::Type type) {
02901   switch (type) {
02902   case PixelBuffer::T_unsigned_byte:
02903     return GL_UNSIGNED_BYTE;
02904   case PixelBuffer::T_unsigned_short:
02905     return GL_UNSIGNED_SHORT;
02906 #ifdef GL_UNSIGNED_BYTE_3_3_2_EXT
02907   case PixelBuffer::T_unsigned_byte_332:
02908     return GL_UNSIGNED_BYTE_3_3_2_EXT;
02909 #endif
02910   case PixelBuffer::T_float:
02911     return GL_FLOAT;
02912 
02913   default:
02914     crgsg_cat.error() << "Invalid PixelBuffer::Type value!\n";
02915     return GL_UNSIGNED_BYTE;
02916   }
02917 }
02918 
02919 ////////////////////////////////////////////////////////////////////
02920 //     Function: CRGraphicsStateGuardian::get_external_image_format
02921 //       Access: Protected
02922 //  Description: Maps from the PixelBuffer's Format symbols
02923 //               to GL's.
02924 ////////////////////////////////////////////////////////////////////
02925 GLenum CRGraphicsStateGuardian::
02926 get_external_image_format(PixelBuffer::Format format) {
02927   switch (format) {
02928   case PixelBuffer::F_color_index:
02929     return GL_COLOR_INDEX;
02930   case PixelBuffer::F_stencil_index:
02931     return GL_STENCIL_INDEX;
02932   case PixelBuffer::F_depth_component:
02933     return GL_DEPTH_COMPONENT;
02934   case PixelBuffer::F_red:
02935     return GL_RED;
02936   case PixelBuffer::F_green:
02937     return GL_GREEN;
02938   case PixelBuffer::F_blue:
02939     return GL_BLUE;
02940   case PixelBuffer::F_alpha:
02941     return GL_ALPHA;
02942   case PixelBuffer::F_rgb:
02943   case PixelBuffer::F_rgb5:
02944   case PixelBuffer::F_rgb8:
02945   case PixelBuffer::F_rgb12:
02946   case PixelBuffer::F_rgb332:
02947 #ifdef GL_BGR
02948     return cr_supports_bgr ? GL_BGR : GL_RGB;
02949 #else
02950     return GL_RGB;
02951 #endif  // GL_BGR
02952   case PixelBuffer::F_rgba:
02953   case PixelBuffer::F_rgbm:
02954   case PixelBuffer::F_rgba4:
02955   case PixelBuffer::F_rgba5:
02956   case PixelBuffer::F_rgba8:
02957   case PixelBuffer::F_rgba12:
02958 #ifdef GL_BGR
02959     return cr_supports_bgr ? GL_BGRA : GL_RGBA;
02960 #else
02961     return GL_RGBA;
02962 #endif  // GL_BGR
02963   case PixelBuffer::F_luminance:
02964     return GL_LUMINANCE;
02965   case PixelBuffer::F_luminance_alphamask:
02966   case PixelBuffer::F_luminance_alpha:
02967     return GL_LUMINANCE_ALPHA;
02968   }
02969   crgsg_cat.error()
02970     << "Invalid PixelBuffer::Format value in get_external_image_format(): "
02971     << (int)format << "\n";
02972   return GL_RGB;
02973 }
02974 
02975 ////////////////////////////////////////////////////////////////////
02976 //     Function: CRGraphicsStateGuardian::get_internal_image_format
02977 //       Access: Protected
02978 //  Description: Maps from the PixelBuffer's Format symbols to a
02979 //               suitable internal format for GL textures.
02980 ////////////////////////////////////////////////////////////////////
02981 GLenum CRGraphicsStateGuardian::
02982 get_internal_image_format(PixelBuffer::Format format) {
02983   switch (format) {
02984   case PixelBuffer::F_rgba:
02985   case PixelBuffer::F_rgbm:
02986     return GL_RGBA;
02987   case PixelBuffer::F_rgba4:
02988     return GL_RGBA4;
02989   case PixelBuffer::F_rgba8:
02990     return GL_RGBA8;
02991   case PixelBuffer::F_rgba12:
02992     return GL_RGBA12;
02993 
02994   case PixelBuffer::F_rgb:
02995     return GL_RGB;
02996   case PixelBuffer::F_rgb5:
02997     return GL_RGB5;
02998   case PixelBuffer::F_rgba5:
02999     return GL_RGB5_A1;
03000   case PixelBuffer::F_rgb8:
03001     return GL_RGB8;
03002   case PixelBuffer::F_rgb12:
03003     return GL_RGB12;
03004   case PixelBuffer::F_rgb332:
03005     return GL_R3_G3_B2;
03006 
03007   case PixelBuffer::F_alpha:
03008     return GL_ALPHA;
03009 
03010   case PixelBuffer::F_red:
03011   case PixelBuffer::F_green:
03012   case PixelBuffer::F_blue:
03013   case PixelBuffer::F_luminance:
03014     return GL_LUMINANCE;
03015   case PixelBuffer::F_luminance_alpha:
03016   case PixelBuffer::F_luminance_alphamask:
03017     return GL_LUMINANCE_ALPHA;
03018 
03019   default:
03020     crgsg_cat.error()
03021       << "Invalid image format in get_internal_image_format(): "
03022       << (int)format << "\n";
03023     return GL_RGB;
03024   }
03025 }
03026 
03027 ////////////////////////////////////////////////////////////////////
03028 //     Function: CRGraphicsStateGuardian::get_texture_apply_mode_type
03029 //       Access: Protected
03030 //  Description: Maps from the texture environment's mode types
03031 //       to the corresponding OpenGL ids
03032 ////////////////////////////////////////////////////////////////////
03033 GLint CRGraphicsStateGuardian::
03034 get_texture_apply_mode_type(TextureApplyAttrib::Mode am) const {
03035   switch (am) {
03036   case TextureApplyAttrib::M_modulate: return GL_MODULATE;
03037   case TextureApplyAttrib::M_decal: return GL_DECAL;
03038   case TextureApplyAttrib::M_blend: return GL_BLEND;
03039   case TextureApplyAttrib::M_replace: return GL_REPLACE;
03040   case TextureApplyAttrib::M_add: return GL_ADD;
03041   }
03042   crgsg_cat.error()
03043     << "Invalid TextureApplyAttrib::Mode value" << endl;
03044   return GL_MODULATE;
03045 }
03046 
03047 ////////////////////////////////////////////////////////////////////
03048 //     Function: CRGraphicsStateGuardian::get_depth_func_type
03049 //       Access: Protected
03050 //  Description: Maps from the depth func modes to gl version
03051 ////////////////////////////////////////////////////////////////////
03052 GLenum CRGraphicsStateGuardian::
03053 get_depth_func_type(DepthTestAttrib::Mode m) const
03054 {
03055   switch(m) {
03056   case DepthTestAttrib::M_never: return GL_NEVER;
03057   case DepthTestAttrib::M_less: return GL_LESS;
03058   case DepthTestAttrib::M_equal: return GL_EQUAL;
03059   case DepthTestAttrib::M_less_equal: return GL_LEQUAL;
03060   case DepthTestAttrib::M_greater: return GL_GREATER;
03061   case DepthTestAttrib::M_not_equal: return GL_NOTEQUAL;
03062   case DepthTestAttrib::M_greater_equal: return GL_GEQUAL;
03063   case DepthTestAttrib::M_always: return GL_ALWAYS;
03064 
03065   default:
03066     crgsg_cat.error()
03067       << "Invalid DepthTestAttrib::Mode value" << endl;
03068     return GL_LESS;
03069   }
03070 }
03071 
03072 ////////////////////////////////////////////////////////////////////
03073 //     Function: CRGraphicsStateGuardian::print_gfx_visual
03074 //       Access: Public
03075 //  Description: Prints a description of the current visual selected.
03076 ////////////////////////////////////////////////////////////////////
03077 void CRGraphicsStateGuardian::
03078 print_gfx_visual() {
03079   GLint i;
03080   GLboolean j;
03081   //  activate();
03082 
03083   cout << "Graphics Visual Info (# bits of each):" << endl;
03084 
03085   cout << "RGBA: ";
03086   chromium.GetIntegerv( GL_RED_BITS, &i ); cout << i << " ";
03087   chromium.GetIntegerv( GL_GREEN_BITS, &i ); cout << i << " ";
03088   chromium.GetIntegerv( GL_BLUE_BITS, &i ); cout << i << " ";
03089   chromium.GetIntegerv( GL_ALPHA_BITS, &i ); cout << i << endl;
03090 
03091   cout << "Accum RGBA: ";
03092   chromium.GetIntegerv( GL_ACCUM_RED_BITS, &i ); cout << i << " ";
03093   chromium.GetIntegerv( GL_ACCUM_GREEN_BITS, &i ); cout << i << " ";
03094   chromium.GetIntegerv( GL_ACCUM_BLUE_BITS, &i ); cout << i << " ";
03095   chromium.GetIntegerv( GL_ACCUM_ALPHA_BITS, &i ); cout << i << endl;
03096 
03097   chromium.GetIntegerv( GL_INDEX_BITS, &i ); cout << "Color Index: " << i << endl;
03098 
03099   chromium.GetIntegerv( GL_DEPTH_BITS, &i ); cout << "Depth: " << i << endl;
03100   chromium.GetIntegerv( GL_ALPHA_BITS, &i ); cout << "Alpha: " << i << endl;
03101   chromium.GetIntegerv( GL_STENCIL_BITS, &i ); cout << "Stencil: " << i << endl;
03102 
03103   chromium.GetBooleanv( GL_DOUBLEBUFFER, &j ); cout << "DoubleBuffer? "
03104                                              << (int)j << endl;
03105 
03106   chromium.GetBooleanv( GL_STEREO, &j ); cout << "Stereo? " << (int)j << endl;
03107 
03108 #ifdef GL_MULTISAMPLE_SGIS
03109   chromium.GetBooleanv( GL_MULTISAMPLE_SGIS, &j ); cout << "Multisample? "
03110                                                  << (int)j << endl;
03111 #endif
03112 #ifdef GL_SAMPLES_SGIS
03113   chromium.GetIntegerv( GL_SAMPLES_SGIS, &i ); cout << "Samples: " << i << endl;
03114 #endif
03115 
03116   chromium.GetBooleanv( GL_BLEND, &j ); cout << "Blend? " << (int)j << endl;
03117   chromium.GetBooleanv( GL_POINT_SMOOTH, &j ); cout << "Point Smooth? "
03118                                              << (int)j << endl;
03119   chromium.GetBooleanv( GL_LINE_SMOOTH, &j ); cout << "Line Smooth? "
03120                                             << (int)j << endl;
03121 
03122   chromium.GetIntegerv( GL_AUX_BUFFERS, &i ); cout << "Aux Buffers: " << i << endl;
03123 }
03124 
03125 ////////////////////////////////////////////////////////////////////
03126 //     Function: CRGraphicsStateGuardian::issue_transformed_color
03127 //       Access: Public
03128 //  Description: Transform the color by the current color matrix, and
03129 //               calls the appropriate chromium.Color function.
03130 ////////////////////////////////////////////////////////////////////
03131 void CRGraphicsStateGuardian::
03132 issue_transformed_color(const Colorf &color) const {
03133   // To be truly general, we really need a 5x5 matrix to transform a
03134   // 4-component color.  Rather than messing with that, we instead
03135   // treat the color as a 3-component RGB, which can be transformed by
03136   // the ordinary 4x4 matrix, and a separate alpha value, which can be
03137   // scaled and offsetted.
03138   LPoint3f temp(color[0], color[1], color[2]);
03139   temp = temp * get_current_color_mat();
03140   float alpha = (color[3] * get_current_alpha_scale()) +
03141     get_current_alpha_offset();
03142 
03143   Colorf transformed(temp[0], temp[1], temp[2], alpha);
03144 
03145   //   crgsg_cat.debug() << "Issuing color " << transformed << "\n";
03146   //   crgsg_cat.debug() << "\tTransformed by " << get_current_color_mat() << "\n";
03147   //   crgsg_cat.debug() << "\tAlpha Transformed by " << get_current_alpha_offset() << " "
03148   //                     << get_current_alpha_scale() << "\n";
03149   chromium.Color4fv(transformed.get_data());
03150 }
03151 
03152 ////////////////////////////////////////////////////////////////////
03153 //     Function: CRGraphicsStateGuardian::enable_lighting
03154 //       Access: Protected, Virtual
03155 //  Description: Intended to be overridden by a derived class to
03156 //               enable or disable the use of lighting overall.  This
03157 //               is called by issue_light() according to whether any
03158 //               lights are in use or not.
03159 ////////////////////////////////////////////////////////////////////
03160 void CRGraphicsStateGuardian::
03161 enable_lighting(bool enable) {
03162   if (enable) {
03163     chromium.Enable(GL_LIGHTING);
03164   } else {
03165     chromium.Disable(GL_LIGHTING);
03166   }
03167 }
03168 
03169 ////////////////////////////////////////////////////////////////////
03170 //     Function: CRGraphicsStateGuardian::set_ambient_light
03171 //       Access: Protected, Virtual
03172 //  Description: Intended to be overridden by a derived class to
03173 //               indicate the color of the ambient light that should
03174 //               be in effect.  This is called by issue_light() after
03175 //               all other lights have been enabled or disabled.
03176 ////////////////////////////////////////////////////////////////////
03177 void CRGraphicsStateGuardian::
03178 set_ambient_light(const Colorf &color) {
03179   chromium.LightModelfv(GL_LIGHT_MODEL_AMBIENT, color.get_data());
03180 }
03181 
03182 ////////////////////////////////////////////////////////////////////
03183 //     Function: CRGraphicsStateGuardian::enable_light
03184 //       Access: Protected, Virtual
03185 //  Description: Intended to be overridden by a derived class to
03186 //               enable the indicated light id.  A specific Light will
03187 //               already have been bound to this id via bind_light().
03188 ////////////////////////////////////////////////////////////////////
03189 void CRGraphicsStateGuardian::
03190 enable_light(int light_id, bool enable) {
03191   if (enable) {
03192     chromium.Enable(get_light_id(light_id));
03193   } else {
03194     chromium.Disable(get_light_id(light_id));
03195   }
03196 }
03197 
03198 ////////////////////////////////////////////////////////////////////
03199 //     Function: CRGraphicsStateGuardian::begin_bind_lights
03200 //       Access: Protected, Virtual
03201 //  Description: Called immediately before bind_light() is called,
03202 //               this is intended to provide the derived class a hook
03203 //               in which to set up some state (like transform) that
03204 //               might apply to several lights.
03205 //
03206 //               The sequence is: begin_bind_lights() will be called,
03207 //               then one or more bind_light() calls, then
03208 //               end_bind_lights().
03209 ////////////////////////////////////////////////////////////////////
03210 void CRGraphicsStateGuardian::
03211 begin_bind_lights() {
03212   // We need to temporarily load a new matrix so we can define the
03213   // light in a known coordinate system.  We pick the transform of the
03214   // root.  (Alternatively, we could leave the current transform where
03215   // it is and compute the light position relative to that transform
03216   // instead of relative to the root, by composing with the matrix
03217   // computed by _transform->invert_compose(render_transform).  But I
03218   // think loading a completely new matrix is simpler.)
03219   chromium.MatrixMode(GL_MODELVIEW);
03220   chromium.PushMatrix();
03221   chromium.LoadMatrixf(_scene_setup->get_render_transform()->get_mat().get_data());
03222 }
03223 
03224 ////////////////////////////////////////////////////////////////////
03225 //     Function: CRGraphicsStateGuardian::end_bind_lights
03226 //       Access: Protected, Virtual
03227 //  Description: Called after before bind_light() has been called one
03228 //               or more times (but before any geometry is issued or
03229 //               additional state is changed), this is intended to
03230 //               clean up any temporary changes to the state that may
03231 //               have been made by begin_bind_lights().
03232 ////////////////////////////////////////////////////////////////////
03233 void CRGraphicsStateGuardian::
03234 end_bind_lights() {
03235   chromium.MatrixMode(GL_MODELVIEW);
03236   chromium.PopMatrix();
03237 }
03238 
03239 ////////////////////////////////////////////////////////////////////
03240 //     Function: CRGraphicsStateGuardian::set_blend_mode
03241 //       Access: Protected, Virtual
03242 //  Description: Called after any of these three blending states have
03243 //               changed; this function is responsible for setting the
03244 //               appropriate color blending mode based on the given
03245 //               properties.
03246 ////////////////////////////////////////////////////////////////////
03247 void CRGraphicsStateGuardian::
03248 set_blend_mode(ColorWriteAttrib::Mode color_write_mode,
03249                ColorBlendAttrib::Mode color_blend_mode,
03250                TransparencyAttrib::Mode transparency_mode) {
03251   // If color_write_mode is off, we disable writing to the color using
03252   // blending.  This case is only used if we can't use chromium.ColorMask to
03253   // disable the color writing for some reason (usually a driver
03254   // problem).
03255   if (color_write_mode == ColorWriteAttrib::M_off) {
03256     enable_multisample_alpha_one(false);
03257     enable_multisample_alpha_mask(false);
03258     enable_blend(true);
03259     enable_alpha_test(false);
03260     call_glBlendFunc(GL_ZERO, GL_ONE);
03261     return;
03262   }
03263 
03264   // Is there a color blend set?
03265   switch (color_blend_mode) {
03266   case ColorBlendAttrib::M_none:
03267     break;
03268 
03269   case ColorBlendAttrib::M_multiply:
03270     enable_multisample_alpha_one(false);
03271     enable_multisample_alpha_mask(false);
03272     enable_blend(true);
03273     enable_alpha_test(false);
03274     call_glBlendFunc(GL_DST_COLOR, GL_ZERO);
03275     return;
03276 
03277   case ColorBlendAttrib::M_add:
03278     enable_multisample_alpha_one(false);
03279     enable_multisample_alpha_mask(false);
03280     enable_blend(true);
03281     enable_alpha_test(false);
03282     call_glBlendFunc(GL_ONE, GL_ONE);
03283     return;
03284 
03285   case ColorBlendAttrib::M_multiply_add:
03286     enable_multisample_alpha_one(false);
03287     enable_multisample_alpha_mask(false);
03288     enable_blend(true);
03289     enable_alpha_test(false);
03290     call_glBlendFunc(GL_DST_COLOR, GL_ONE);
03291     return;
03292 
03293   default:
03294     crgsg_cat.error()
03295       << "Unknown color blend mode " << (int)color_blend_mode << endl;
03296     break;
03297   }
03298 
03299   // No color blend; is there a transparency set?
03300   switch (transparency_mode) {
03301   case TransparencyAttrib::M_none:
03302     break;
03303 
03304   case TransparencyAttrib::M_alpha:
03305   case TransparencyAttrib::M_alpha_sorted:
03306     // Should we really have an "alpha" and an "alpha_sorted" mode,
03307     // like Performer does?  (The difference is that "alpha" is with
03308     // the write to the depth buffer disabled.)  Or should we just use
03309     // the separate depth write transition to control this?  Doing it
03310     // implicitly requires a bit more logic here and in the state
03311     // management; for now we require the user to explicitly turn off
03312     // the depth write.
03313     enable_multisample_alpha_one(false);
03314     enable_multisample_alpha_mask(false);
03315     enable_blend(true);
03316     enable_alpha_test(false);
03317     call_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
03318     return;
03319 
03320   case TransparencyAttrib::M_multisample:
03321     enable_multisample_alpha_one(true);
03322     enable_multisample_alpha_mask(true);
03323     enable_blend(false);
03324     enable_alpha_test(false);
03325     return;
03326 
03327   case TransparencyAttrib::M_multisample_mask:
03328     enable_multisample_alpha_one(false);
03329     enable_multisample_alpha_mask(true);
03330     enable_blend(false);
03331     enable_alpha_test(false);
03332     return;
03333 
03334   case TransparencyAttrib::M_binary:
03335     enable_multisample_alpha_one(false);
03336     enable_multisample_alpha_mask(false);
03337     enable_blend(false);
03338     enable_alpha_test(true);
03339     call_glAlphaFunc(GL_EQUAL, 1);
03340     return;
03341 
03342   default:
03343     crgsg_cat.error()
03344       << "invalid transparency mode " << (int)transparency_mode << endl;
03345     break;
03346   }
03347 
03348   // Nothing's set, so disable blending.
03349   enable_multisample_alpha_one(false);
03350   enable_multisample_alpha_mask(false);
03351   enable_blend(false);
03352   enable_alpha_test(false);
03353 }
03354 
03355 ////////////////////////////////////////////////////////////////////
03356 //     Function: CRGraphicsStateGuardian::free_pointers
03357 //       Access: Protected
03358 //  Description: Frees some memory that was explicitly allocated
03359 //               within the crgsg.
03360 ////////////////////////////////////////////////////////////////////
03361 void CRGraphicsStateGuardian::
03362 free_pointers() {
03363   if (_clip_plane_enabled != (bool *)NULL) {
03364     delete[] _clip_plane_enabled;
03365     _clip_plane_enabled = (bool *)NULL;
03366   }
03367   if (_cur_clip_plane_enabled != (bool *)NULL) {
03368     delete[] _cur_clip_plane_enabled;
03369     _cur_clip_plane_enabled = (bool *)NULL;
03370   }
03371 }
03372 
03373 ////////////////////////////////////////////////////////////////////
03374 //     Function: CRGraphicsStateGuardian::save_frame_buffer
03375 //       Access: Public
03376 //  Description: Saves the indicated planes of the frame buffer
03377 //               (within the indicated display region) and returns it
03378 //               in some meaningful form that can be restored later
03379 //               via restore_frame_buffer().  This is a helper
03380 //               function for push_frame_buffer() and
03381 //               pop_frame_buffer().
03382 ////////////////////////////////////////////////////////////////////
03383 PT(SavedFrameBuffer) CRGraphicsStateGuardian::
03384 save_frame_buffer(const RenderBuffer &buffer,
03385                   CPT(DisplayRegion) dr) {
03386   CRSavedFrameBuffer *sfb = new CRSavedFrameBuffer(buffer, dr);
03387 
03388   if (buffer._buffer_type & RenderBuffer::T_depth) {
03389     // Save the depth buffer.
03390     sfb->_depth =
03391       new PixelBuffer(PixelBuffer::depth_buffer(dr->get_pixel_width(),
03392                                                 dr->get_pixel_height()));
03393     copy_pixel_buffer(sfb->_depth, dr, buffer);
03394   }
03395 
03396   if (buffer._buffer_type & RenderBuffer::T_back) {
03397     // Save the color buffer.
03398     sfb->_back_rgba = new Texture;
03399     copy_texture(sfb->_back_rgba->prepare(this), dr, buffer);
03400   }
03401 
03402   return sfb;
03403 }
03404 
03405 ////////////////////////////////////////////////////////////////////
03406 //     Function: CRGraphicsStateGuardian::restore_frame_buffer
03407 //       Access: Public
03408 //  Description: Restores the frame buffer that was previously saved.
03409 ////////////////////////////////////////////////////////////////////
03410 void CRGraphicsStateGuardian::
03411 restore_frame_buffer(SavedFrameBuffer *frame_buffer) {
03412   CRSavedFrameBuffer *sfb = DCAST(CRSavedFrameBuffer, frame_buffer);
03413 
03414   if (sfb->_back_rgba != (Texture *)NULL &&
03415       (sfb->_buffer._buffer_type & RenderBuffer::T_back) != 0) {
03416     // Restore the color buffer.
03417     draw_texture(sfb->_back_rgba->prepare(this),
03418                  sfb->_display_region, sfb->_buffer);
03419   }
03420 
03421   if (sfb->_depth != (PixelBuffer *)NULL &&
03422       (sfb->_buffer._buffer_type & RenderBuffer::T_depth) != 0) {
03423     // Restore the depth buffer.
03424     draw_pixel_buffer(sfb->_depth, sfb->_display_region, sfb->_buffer);
03425   }
03426 }
03427 
03428 #ifndef NDEBUG
03429 ////////////////////////////////////////////////////////////////////
03430 //     Function: CRGraphicsStateGuardian::build_phony_mipmaps
03431 //       Access: Protected
03432 //  Description: Generates a series of colored mipmap levels to aid in
03433 //               visualizing the mipmap levels as the hardware applies
03434 //               them.
03435 ////////////////////////////////////////////////////////////////////
03436 void CRGraphicsStateGuardian::
03437 build_phony_mipmaps(Texture *tex) {
03438   PixelBuffer *pb = tex->_pbuffer;
03439   int xsize = pb->get_xsize();
03440   int ysize = pb->get_ysize();
03441 
03442   crgsg_cat.info()
03443     << "Building phony mipmap levels for " << tex->get_name() << "\n";
03444   int level = 0;
03445   while (xsize > 0 && ysize > 0) {
03446     crgsg_cat.info(false)
03447       << "  level " << level << " is " << xsize << " by " << ysize << "\n";
03448     build_phony_mipmap_level(level, xsize, ysize);
03449 
03450     xsize >>= 1;
03451     ysize >>= 1;
03452     level++;
03453   }
03454 
03455   while (xsize > 0) {
03456     crgsg_cat.info(false)
03457       << "  level " << level << " is " << xsize << " by 1\n";
03458     build_phony_mipmap_level(level, xsize, 1);
03459 
03460     xsize >>= 1;
03461     level++;
03462   }
03463 
03464   while (ysize > 0) {
03465     crgsg_cat.info(false)
03466       << "  level " << level << " is 1 by " << ysize << "\n";
03467     build_phony_mipmap_level(level, 1, ysize);
03468 
03469     ysize >>= 1;
03470     level++;
03471   }
03472 }
03473 
03474 ////////////////////////////////////////////////////////////////////
03475 //     Function: CRGraphicsStateGuardian::build_phony_mipmap_level
03476 //       Access: Protected
03477 //  Description: Generates a single colored mipmap level.
03478 ////////////////////////////////////////////////////////////////////
03479 void CRGraphicsStateGuardian::
03480 build_phony_mipmap_level(int level, int xsize, int ysize) {
03481   static const int num_levels = 10;
03482   static const char *level_filenames[num_levels] = {
03483     "mipmap_level_0.rgb",
03484     "mipmap_level_1.rgb",
03485     "mipmap_level_2.rgb",
03486     "mipmap_level_3.rgb",
03487     "mipmap_level_4.rgb",
03488     "mipmap_level_5.rgb",
03489     "mipmap_level_6.rgb",
03490     "mipmap_level_7.rgb",
03491     "mipmap_level_8.rgb",
03492     "mipmap_level_9.rgb"
03493   };
03494   static const RGBColorf level_colors[num_levels] = {
03495     RGBColorf(1.0f, 1.0f, 1.0f),
03496     RGBColorf(1.0f, 0.0f, 0.0f),
03497     RGBColorf(0.0f, 1.0f, 0.0f),
03498     RGBColorf(0.0f, 0.0f, 1.0f),
03499     RGBColorf(1.0f, 1.0f, 0.0f),
03500     RGBColorf(0.0f, 1.0f, 1.0f),
03501     RGBColorf(1.0f, 0.0f, 1.0f),
03502     RGBColorf(1.0f, 0.5, 0.0f),
03503     RGBColorf(0.0f, 1.0f, 0.5),
03504     RGBColorf(0.83, 0.71, 1.0f)
03505   };
03506 
03507   level = level % num_levels;
03508   Filename filename(level_filenames[level]);
03509 
03510   PNMImage image_sized(xsize, ysize);
03511   PNMImage image_source;
03512   if (filename.resolve_filename(get_texture_path()) ||
03513       filename.resolve_filename(get_model_path())) {
03514     image_source.read(filename);
03515   }
03516 
03517   if (image_source.is_valid()) {
03518     image_sized.quick_filter_from(image_source);
03519 
03520   } else {
03521     crgsg_cat.info(false)
03522       << "    " << filename << " cannot be read, making solid color mipmap.\n";
03523     image_sized.fill(level_colors[level][0],
03524                      level_colors[level][1],
03525                      level_colors[level][2]);
03526   }
03527 
03528   PixelBuffer *pb = new PixelBuffer;
03529   pb->load(image_sized);
03530 
03531   GLenum internal_format = get_internal_image_format(pb->get_format());
03532   GLenum external_format = get_external_image_format(pb->get_format());
03533   GLenum type = get_image_type(pb->get_image_type());
03534 
03535   chromium.TexImage2D(GL_TEXTURE_2D, level, internal_format,
03536                pb->get_xsize(), pb->get_ysize(), pb->get_border(),
03537                external_format, type, pb->_image );
03538 
03539   delete pb;
03540 }
03541 
03542 ////////////////////////////////////////////////////////////////////
03543 //     Function: CRGraphicsStateGuardian::save_mipmap_images
03544 //       Access: Protected
03545 //  Description: Saves out each mipmap level of the indicated texture
03546 //               (which must also be the currently active texture in
03547 //               the GL state) as a separate image file to disk.
03548 ////////////////////////////////////////////////////////////////////
03549 void CRGraphicsStateGuardian::
03550 save_mipmap_images(Texture *tex) {
03551   Filename filename = tex->get_name();
03552   string name;
03553   if (filename.empty()) {
03554     static int index = 0;
03555     name = "texture" + format_string(index);
03556     index++;
03557   } else {
03558     name = filename.get_basename_wo_extension();
03559   }
03560 
03561   PixelBuffer *pb = tex->get_ram_image();
03562   nassertv(pb != (PixelBuffer *)NULL);
03563 
03564   GLenum external_format = get_external_image_format(pb->get_format());
03565   GLenum type = get_image_type(pb->get_image_type());
03566 
03567   int xsize = pb->get_xsize();
03568   int ysize = pb->get_ysize();
03569 
03570   // Specify byte-alignment for the pixels on output.
03571   set_pack_alignment(1);
03572 
03573   int mipmap_level = 0;
03574   do {
03575     xsize = max(xsize, 1);
03576     ysize = max(ysize, 1);
03577 
03578     PT(PixelBuffer) mpb = 
03579       new PixelBuffer(xsize, ysize, pb->get_num_components(),
03580                       pb->get_component_width(), pb->get_image_type(),
03581                       pb->get_format());
03582     chromium.GetTexImage(GL_TEXTURE_2D, mipmap_level, external_format, 
03583                   type, mpb->_image);
03584     Filename mipmap_filename = name + "_" + format_string(mipmap_level) + ".rgb";
03585     nout << "Writing mipmap level " << mipmap_level
03586          << " (" << xsize << " by " << ysize << ") " 
03587          << mipmap_filename << "\n";
03588     mpb->write(mipmap_filename);
03589 
03590     xsize >>= 1;
03591     ysize >>= 1;
03592     mipmap_level++;
03593   } while (xsize > 0 && ysize > 0);
03594 }
03595 #endif  // NDEBUG
03596 
03597 // factory and type stuff
03598 
03599 GraphicsStateGuardian *CRGraphicsStateGuardian::
03600 make_GlGraphicsStateGuardian(const FactoryParams &params) {
03601   GraphicsStateGuardian::GsgWindow *win_param;
03602   if (!get_param_into(win_param, params)) {
03603     crgsg_cat.error()
03604       << "No window specified for gsg creation!" << endl;
03605     return NULL;
03606   }
03607 
03608   GraphicsWindow *win = win_param->get_window();
03609   return new CRGraphicsStateGuardian(win);
03610 }
03611 
03612 TypeHandle CRGraphicsStateGuardian::get_type(void) const {
03613   return get_class_type();
03614 }
03615 
03616 TypeHandle CRGraphicsStateGuardian::get_class_type(void) {
03617   return _type_handle;
03618 }
03619 
03620 void CRGraphicsStateGuardian::init_type(void) {
03621   GraphicsStateGuardian::init_type();
03622   register_type(_type_handle, "CRGraphicsStateGuardian",
03623                 GraphicsStateGuardian::get_class_type());
03624 }
03625 
03626 
03627 #ifdef GSG_VERBOSE
03628 
03629 void CRGraphicsStateGuardian::
03630 dump_state(void)
03631 {
03632   if (crgsg_cat.is_debug())
03633     {
03634       int i;
03635       ostream &dump = crgsg_cat.debug(false);
03636       crgsg_cat.debug() << "Dumping GL State" << endl;
03637 
03638       dump << "\t\t" << "GL_LINE_SMOOTH " << _line_smooth_enabled << " " << (bool)chromium.IsEnabled(GL_LINE_SMOOTH) << "\n";
03639       dump << "\t\t" << "GL_POINT_SMOOTH " << _point_smooth_enabled << " " << (bool)chromium.IsEnabled(GL_POINT_SMOOTH) << "\n";
03640       dump << "\t\t" << "GL_LIGHTING " << _lighting_enabled << " " << (bool)chromium.IsEnabled(GL_LIGHTING) << "\n";
03641       dump << "\t\t" << "GL_SCISSOR_TEST " << _scissor_enabled << " " << (bool)chromium.IsEnabled(GL_SCISSOR_TEST) << "\n";
03642       dump << "\t\t" << "GL_TEXTURE_2D " << _texturing_enabled << " " << (bool)chromium.IsEnabled(GL_TEXTURE_2D) << "\n";
03643       dump << "\t\t" << "GL_DITHER " << _dither_enabled << " " << (bool)chromium.IsEnabled(GL_DITHER) << "\n";
03644       dump << "\t\t" << "GL_STENCIL_TEST " << " " << (bool)chromium.IsEnabled(GL_STENCIL_TEST) << "\n";
03645       for(i = 0; i < _max_clip_planes; i++)
03646         {
03647           dump << "\t\t\t\t" << "GL_CLIP_PLANE" << i << " " << _clip_plane_enabled[i] << " " << (bool)chromium.IsEnabled(GL_CLIP_PLANE0+i) << "\n";
03648         }
03649       dump << "\t\t" << "GL_BLEND " << _blend_enabled << " " << (bool)chromium.IsEnabled(GL_BLEND) << "\n";
03650       dump << "\t\t" << "GL_DEPTH_TEST " << _depth_test_enabled << " " << (bool)chromium.IsEnabled(GL_DEPTH_TEST) << "\n";
03651       dump << "\t\t" << "GL_FOG " << _fog_enabled << " " << (bool)chromium.IsEnabled(GL_FOG) << "\n";
03652       dump << "\t\t" << "GL_ALPHA_TEST " << _alpha_test_enabled << " " << (bool)chromium.IsEnabled(GL_ALPHA_TEST) << "\n";
03653       dump << "\t\t" << "GL_POLYGON_OFFSET_FILL " << _polygon_offset_enabled << " " << (bool)chromium.IsEnabled(GL_POLYGON_OFFSET_FILL) << "\n";
03654 
03655       dump << endl;
03656     }
03657 }
03658 
03659 #else  // GSG_VERBOSE
03660 
03661 // This function does nothing unless GSG_VERBOSE is compiled in.
03662 void CRGraphicsStateGuardian::
03663 dump_state(void)
03664 {
03665 }
03666 
03667 #endif  // GSG_VERBOSE
03668 
03669 
03670 #ifdef GSG_VERBOSE
03671 
03672 // This is a handy function to output a GLenum value as a string, for
03673 // debugging.
03674 ostream &output_cr_enum(ostream &out, GLenum v) {
03675   switch (v) {
03676   case GL_FALSE:
03677     return out << "GL_FALSE";
03678   case GL_TRUE:
03679     return out << "GL_TRUE";
03680 
03681     /* Data types */
03682   case GL_BYTE:
03683     return out << "GL_BYTE";
03684   case GL_UNSIGNED_BYTE:
03685     return out << "GL_UNSIGNED_BYTE";
03686   case GL_SHORT:
03687     return out << "GL_SHORT";
03688   case GL_UNSIGNED_SHORT:
03689     return out << "GL_UNSIGNED_SHORT";
03690   case GL_INT:
03691     return out << "GL_INT";
03692   case GL_UNSIGNED_INT:
03693     return out << "GL_UNSIGNED_INT";
03694   case GL_FLOAT:
03695     return out << "GL_FLOAT";
03696   case GL_DOUBLE:
03697     return out << "GL_DOUBLE";
03698   case GL_2_BYTES:
03699     return out << "GL_2_BYTES";
03700   case GL_3_BYTES:
03701     return out << "GL_3_BYTES";
03702   case GL_4_BYTES:
03703     return out << "GL_4_BYTES";
03704 
03705     /* Primitives */
03706     /*
03707       case GL_LINES:
03708       return out << "GL_LINES";
03709       case GL_POINTS:
03710       return out << "GL_POINTS";
03711     */
03712   case GL_LINE_STRIP:
03713     return out << "GL_LINE_STRIP";
03714   case GL_LINE_LOOP:
03715     return out << "GL_LINE_LOOP";
03716   case GL_TRIANGLES:
03717     return out << "GL_TRIANGLES";
03718   case GL_TRIANGLE_STRIP:
03719     return out << "GL_TRIANGLE_STRIP";
03720   case GL_TRIANGLE_FAN:
03721     return out << "GL_TRIANGLE_FAN";
03722   case GL_QUADS:
03723     return out << "GL_QUADS";
03724   case GL_QUAD_STRIP:
03725     return out << "GL_QUAD_STRIP";
03726   case GL_POLYGON:
03727     return out << "GL_POLYGON";
03728   case GL_EDGE_FLAG:
03729     return out << "GL_EDGE_FLAG";
03730 
03731     /* Vertex Arrays */
03732   case GL_VERTEX_ARRAY:
03733     return out << "GL_VERTEX_ARRAY";
03734   case GL_NORMAL_ARRAY:
03735     return out << "GL_NORMAL_ARRAY";
03736   case GL_COLOR_ARRAY:
03737     return out << "GL_COLOR_ARRAY";
03738   case GL_INDEX_ARRAY:
03739     return out << "GL_INDEX_ARRAY";
03740   case GL_TEXTURE_COORD_ARRAY:
03741     return out << "GL_TEXTURE_COORD_ARRAY";
03742   case GL_EDGE_FLAG_ARRAY:
03743     return out << "GL_EDGE_FLAG_ARRAY";
03744   case GL_VERTEX_ARRAY_SIZE:
03745     return out << "GL_VERTEX_ARRAY_SIZE";
03746   case GL_VERTEX_ARRAY_TYPE:
03747     return out << "GL_VERTEX_ARRAY_TYPE";
03748   case GL_VERTEX_ARRAY_STRIDE:
03749     return out << "GL_VERTEX_ARRAY_STRIDE";
03750   case GL_NORMAL_ARRAY_TYPE:
03751     return out << "GL_NORMAL_ARRAY_TYPE";
03752   case GL_NORMAL_ARRAY_STRIDE:
03753     return out << "GL_NORMAL_ARRAY_STRIDE";
03754   case GL_COLOR_ARRAY_SIZE:
03755     return out << "GL_COLOR_ARRAY_SIZE";
03756   case GL_COLOR_ARRAY_TYPE:
03757     return out << "GL_COLOR_ARRAY_TYPE";
03758   case GL_COLOR_ARRAY_STRIDE:
03759     return out << "GL_COLOR_ARRAY_STRIDE";
03760   case GL_INDEX_ARRAY_TYPE:
03761     return out << "GL_INDEX_ARRAY_TYPE";
03762   case GL_INDEX_ARRAY_STRIDE:
03763     return out << "GL_INDEX_ARRAY_STRIDE";
03764   case GL_TEXTURE_COORD_ARRAY_SIZE:
03765     return out << "GL_TEXTURE_COORD_ARRAY_SIZE";
03766   case GL_TEXTURE_COORD_ARRAY_TYPE:
03767     return out << "GL_TEXTURE_COORD_ARRAY_TYPE";
03768   case GL_TEXTURE_COORD_ARRAY_STRIDE:
03769     return out << "GL_TEXTURE_COORD_ARRAY_STRIDE";
03770   case GL_EDGE_FLAG_ARRAY_STRIDE:
03771     return out << "GL_EDGE_FLAG_ARRAY_STRIDE";
03772   case GL_VERTEX_ARRAY_POINTER:
03773     return out << "GL_VERTEX_ARRAY_POINTER";
03774   case GL_NORMAL_ARRAY_POINTER:
03775     return out << "GL_NORMAL_ARRAY_POINTER";
03776   case GL_COLOR_ARRAY_POINTER:
03777     return out << "GL_COLOR_ARRAY_POINTER";
03778   case GL_INDEX_ARRAY_POINTER:
03779     return out << "GL_INDEX_ARRAY_POINTER";
03780   case GL_TEXTURE_COORD_ARRAY_POINTER:
03781     return out << "GL_TEXTURE_COORD_ARRAY_POINTER";
03782   case GL_EDGE_FLAG_ARRAY_POINTER:
03783     return out << "GL_EDGE_FLAG_ARRAY_POINTER";
03784   case GL_V2F:
03785     return out << "GL_V2F";
03786   case GL_V3F:
03787     return out << "GL_V3F";
03788   case GL_C4UB_V2F:
03789     return out << "GL_C4UB_V2F";
03790   case GL_C4UB_V3F:
03791     return out << "GL_C4UB_V3F";
03792   case GL_C3F_V3F:
03793     return out << "GL_C3F_V3F";
03794   case GL_N3F_V3F:
03795     return out << "GL_N3F_V3F";
03796   case GL_C4F_N3F_V3F:
03797     return out << "GL_C4F_N3F_V3F";
03798   case GL_T2F_V3F:
03799     return out << "GL_T2F_V3F";
03800   case GL_T4F_V4F:
03801     return out << "GL_T4F_V4F";
03802   case GL_T2F_C4UB_V3F:
03803     return out << "GL_T2F_C4UB_V3F";
03804   case GL_T2F_C3F_V3F:
03805     return out << "GL_T2F_C3F_V3F";
03806   case GL_T2F_N3F_V3F:
03807     return out << "GL_T2F_N3F_V3F";
03808   case GL_T2F_C4F_N3F_V3F:
03809     return out << "GL_T2F_C4F_N3F_V3F";
03810   case GL_T4F_C4F_N3F_V4F:
03811     return out << "GL_T4F_C4F_N3F_V4F";
03812 
03813     /* Matrix Mode */
03814   case GL_MATRIX_MODE:
03815     return out << "GL_MATRIX_MODE";
03816   case GL_MODELVIEW:
03817     return out << "GL_MODELVIEW";
03818   case GL_PROJECTION:
03819     return out << "GL_PROJECTION";
03820   case GL_TEXTURE:
03821     return out << "GL_TEXTURE";
03822 
03823     /* Points */
03824   case GL_POINT_SMOOTH:
03825     return out << "GL_POINT_SMOOTH";
03826   case GL_POINT_SIZE:
03827     return out << "GL_POINT_SIZE";
03828   case GL_POINT_SIZE_GRANULARITY:
03829     return out << "GL_POINT_SIZE_GRANULARITY";
03830   case GL_POINT_SIZE_RANGE:
03831     return out << "GL_POINT_SIZE_RANGE";
03832 
03833     /* Lines */
03834   case GL_LINE_SMOOTH:
03835     return out << "GL_LINE_SMOOTH";
03836   case GL_LINE_STIPPLE:
03837     return out << "GL_LINE_STIPPLE";
03838   case GL_LINE_STIPPLE_PATTERN:
03839     return out << "GL_LINE_STIPPLE_PATTERN";
03840   case GL_LINE_STIPPLE_REPEAT:
03841     return out << "GL_LINE_STIPPLE_REPEAT";
03842   case GL_LINE_WIDTH:
03843     return out << "GL_LINE_WIDTH";
03844   case GL_LINE_WIDTH_GRANULARITY:
03845     return out << "GL_LINE_WIDTH_GRANULARITY";
03846   case GL_LINE_WIDTH_RANGE:
03847     return out << "GL_LINE_WIDTH_RANGE";
03848 
03849     /* Polygons */
03850   case GL_POINT:
03851     return out << "GL_POINT";
03852   case GL_LINE:
03853     return out << "GL_LINE";
03854   case GL_FILL:
03855     return out << "GL_FILL";
03856   case GL_CCW:
03857     return out << "GL_CCW";
03858   case GL_CW:
03859     return out << "GL_CW";
03860   case GL_FRONT:
03861     return out << "GL_FRONT";
03862   case GL_BACK:
03863     return out << "GL_BACK";
03864   case GL_CULL_FACE:
03865     return out << "GL_CULL_FACE";
03866   case GL_CULL_FACE_MODE:
03867     return out << "GL_CULL_FACE_MODE";
03868   case GL_POLYGON_SMOOTH:
03869     return out << "GL_POLYGON_SMOOTH";
03870   case GL_POLYGON_STIPPLE:
03871     return out << "GL_POLYGON_STIPPLE";
03872   case GL_FRONT_FACE:
03873     return out << "GL_FRONT_FACE";
03874   case GL_POLYGON_MODE:
03875     return out << "GL_POLYGON_MODE";
03876   case GL_POLYGON_OFFSET_FACTOR:
03877     return out << "GL_POLYGON_OFFSET_FACTOR";
03878   case GL_POLYGON_OFFSET_UNITS:
03879     return out << "GL_POLYGON_OFFSET_UNITS";
03880   case GL_POLYGON_OFFSET_POINT:
03881     return out << "GL_POLYGON_OFFSET_POINT";
03882   case GL_POLYGON_OFFSET_LINE:
03883     return out << "GL_POLYGON_OFFSET_LINE";
03884   case GL_POLYGON_OFFSET_FILL:
03885     return out << "GL_POLYGON_OFFSET_FILL";
03886 
03887     /* Display Lists */
03888   case GL_COMPILE:
03889     return out << "GL_COMPILE";
03890   case GL_COMPILE_AND_EXECUTE:
03891     return out << "GL_COMPILE_AND_EXECUTE";
03892   case GL_LIST_BASE:
03893     return out << "GL_LIST_BASE";
03894   case GL_LIST_INDEX:
03895     return out << "GL_LIST_INDEX";
03896   case GL_LIST_MODE:
03897     return out << "GL_LIST_MODE";
03898 
03899     /* Depth buffer */
03900   case GL_NEVER:
03901     return out << "GL_NEVER";
03902   case GL_LESS:
03903     return out << "GL_LESS";
03904   case GL_GEQUAL:
03905     return out << "GL_GEQUAL";
03906   case GL_LEQUAL:
03907     return out << "GL_LEQUAL";
03908   case GL_GREATER:
03909     return out << "GL_GREATER";
03910   case GL_NOTEQUAL:
03911     return out << "GL_NOTEQUAL";
03912   case GL_EQUAL:
03913     return out << "GL_EQUAL";
03914   case GL_ALWAYS:
03915     return out << "GL_ALWAYS";
03916   case GL_DEPTH_TEST:
03917     return out << "GL_DEPTH_TEST";
03918   case GL_DEPTH_BITS:
03919     return out << "GL_DEPTH_BITS";
03920   case GL_DEPTH_CLEAR_VALUE:
03921     return out << "GL_DEPTH_CLEAR_VALUE";
03922   case GL_DEPTH_FUNC:
03923     return out << "GL_DEPTH_FUNC";
03924   case GL_DEPTH_RANGE:
03925     return out << "GL_DEPTH_RANGE";
03926   case GL_DEPTH_WRITEMASK:
03927     return out << "GL_DEPTH_WRITEMASK";
03928   case GL_DEPTH_COMPONENT:
03929     return out << "GL_DEPTH_COMPONENT";
03930 
03931     /* Lighting */
03932   case GL_LIGHTING:
03933     return out << "GL_LIGHTING";
03934   case GL_LIGHT0:
03935     return out << "GL_LIGHT0";
03936   case GL_LIGHT1:
03937     return out << "GL_LIGHT1";
03938   case GL_LIGHT2:
03939     return out << "GL_LIGHT2";
03940   case GL_LIGHT3:
03941     return out << "GL_LIGHT3";
03942   case GL_LIGHT4:
03943     return out << "GL_LIGHT4";
03944   case GL_LIGHT5:
03945     return out << "GL_LIGHT5";
03946   case GL_LIGHT6:
03947     return out << "GL_LIGHT6";
03948   case GL_LIGHT7:
03949     return out << "GL_LIGHT7";
03950   case GL_SPOT_EXPONENT:
03951     return out << "GL_SPOT_EXPONENT";
03952   case GL_SPOT_CUTOFF:
03953     return out << "GL_SPOT_CUTOFF";
03954   case GL_CONSTANT_ATTENUATION:
03955     return out << "GL_CONSTANT_ATTENUATION";
03956   case GL_LINEAR_ATTENUATION:
03957     return out << "GL_LINEAR_ATTENUATION";
03958   case GL_QUADRATIC_ATTENUATION:
03959     return out << "GL_QUADRATIC_ATTENUATION";
03960   case GL_AMBIENT:
03961     return out << "GL_AMBIENT";
03962   case GL_DIFFUSE:
03963     return out << "GL_DIFFUSE";
03964   case GL_SPECULAR:
03965     return out << "GL_SPECULAR";
03966   case GL_SHININESS:
03967     return out << "GL_SHININESS";
03968   case GL_EMISSION:
03969     return out << "GL_EMISSION";
03970   case GL_POSITION:
03971     return out << "GL_POSITION";
03972   case GL_SPOT_DIRECTION:
03973     return out << "GL_SPOT_DIRECTION";
03974   case GL_AMBIENT_AND_DIFFUSE:
03975     return out << "GL_AMBIENT_AND_DIFFUSE";
03976   case GL_COLOR_INDEXES:
03977     return out << "GL_COLOR_INDEXES";
03978   case GL_LIGHT_MODEL_TWO_SIDE:
03979     return out << "GL_LIGHT_MODEL_TWO_SIDE";
03980   case GL_LIGHT_MODEL_LOCAL_VIEWER:
03981     return out << "GL_LIGHT_MODEL_LOCAL_VIEWER";
03982   case GL_LIGHT_MODEL_AMBIENT:
03983     return out << "GL_LIGHT_MODEL_AMBIENT";
03984   case GL_FRONT_AND_BACK:
03985     return out << "GL_FRONT_AND_BACK";
03986   case GL_SHADE_MODEL:
03987     return out << "GL_SHADE_MODEL";
03988   case GL_FLAT:
03989     return out << "GL_FLAT";
03990   case GL_SMOOTH:
03991     return out << "GL_SMOOTH";
03992   case GL_COLOR_MATERIAL:
03993     return out << "GL_COLOR_MATERIAL";
03994   case GL_COLOR_MATERIAL_FACE:
03995     return out << "GL_COLOR_MATERIAL_FACE";
03996   case GL_COLOR_MATERIAL_PARAMETER:
03997     return out << "GL_COLOR_MATERIAL_PARAMETER";
03998   case GL_NORMALIZE:
03999     return out << "GL_NORMALIZE";
04000 
04001     /* User clipping planes */
04002   case GL_CLIP_PLANE0:
04003     return out << "GL_CLIP_PLANE0";
04004   case GL_CLIP_PLANE1:
04005     return out << "GL_CLIP_PLANE1";
04006   case GL_CLIP_PLANE2:
04007     return out << "GL_CLIP_PLANE2";
04008   case GL_CLIP_PLANE3:
04009     return out << "GL_CLIP_PLANE3";
04010   case GL_CLIP_PLANE4:
04011     return out << "GL_CLIP_PLANE4";
04012   case GL_CLIP_PLANE5:
04013     return out << "GL_CLIP_PLANE5";
04014 
04015     /* Accumulation buffer */
04016   case GL_ACCUM_RED_BITS:
04017     return out << "GL_ACCUM_RED_BITS";
04018   case GL_ACCUM_GREEN_BITS:
04019     return out << "GL_ACCUM_GREEN_BITS";
04020   case GL_ACCUM_BLUE_BITS:
04021     return out << "GL_ACCUM_BLUE_BITS";
04022   case GL_ACCUM_ALPHA_BITS:
04023     return out << "GL_ACCUM_ALPHA_BITS";
04024   case GL_ACCUM_CLEAR_VALUE:
04025     return out << "GL_ACCUM_CLEAR_VALUE";
04026   case GL_ACCUM:
04027     return out << "GL_ACCUM";
04028   case GL_ADD:
04029     return out << "GL_ADD";
04030   case GL_LOAD:
04031     return out << "GL_LOAD";
04032   case GL_MULT:
04033     return out << "GL_MULT";
04034 
04035     /* Alpha testing */
04036   case GL_ALPHA_TEST:
04037     return out << "GL_ALPHA_TEST";
04038   case GL_ALPHA_TEST_REF:
04039     return out << "GL_ALPHA_TEST_REF";
04040   case GL_ALPHA_TEST_FUNC:
04041     return out << "GL_ALPHA_TEST_FUNC";
04042 
04043     /* Blending */
04044   case GL_BLEND:
04045     return out << "GL_BLEND";
04046   case GL_BLEND_SRC:
04047     return out << "GL_BLEND_SRC";
04048   case GL_BLEND_DST:
04049     return out << "GL_BLEND_DST";
04050     /*
04051       case GL_ZERO:
04052       return out << "GL_ZERO";
04053       case GL_ONE:
04054       return out << "GL_ONE";
04055     */
04056   case GL_SRC_COLOR:
04057     return out << "GL_SRC_COLOR";
04058   case GL_ONE_MINUS_SRC_COLOR:
04059     return out << "GL_ONE_MINUS_SRC_COLOR";
04060   case GL_DST_COLOR:
04061     return out << "GL_DST_COLOR";
04062   case GL_ONE_MINUS_DST_COLOR:
04063     return out << "GL_ONE_MINUS_DST_COLOR";
04064   case GL_SRC_ALPHA:
04065     return out << "GL_SRC_ALPHA";
04066   case GL_ONE_MINUS_SRC_ALPHA:
04067     return out << "GL_ONE_MINUS_SRC_ALPHA";
04068   case GL_DST_ALPHA:
04069     return out << "GL_DST_ALPHA";
04070   case GL_ONE_MINUS_DST_ALPHA:
04071     return out << "GL_ONE_MINUS_DST_ALPHA";
04072   case GL_SRC_ALPHA_SATURATE:
04073     return out << "GL_SRC_ALPHA_SATURATE";
04074   #ifdef USING_OPENGL_1_2 //[
04075   case GL_CONSTANT_COLOR:
04076     return out << "GL_CONSTANT_COLOR";
04077   case GL_ONE_MINUS_CONSTANT_COLOR:
04078     return out << "GL_ONE_MINUS_CONSTANT_COLOR";
04079   case GL_CONSTANT_ALPHA:
04080     return out << "GL_CONSTANT_ALPHA";
04081   case GL_ONE_MINUS_CONSTANT_ALPHA:
04082     return out << "GL_ONE_MINUS_CONSTANT_ALPHA";
04083   #endif //]
04084 
04085     /* Render Mode */
04086   case GL_FEEDBACK:
04087     return out << "GL_FEEDBACK";
04088   case GL_RENDER:
04089     return out << "GL_RENDER";
04090   case GL_SELECT:
04091     return out << "GL_SELECT";
04092 
04093     /* Feedback */
04094   case GL_2D:
04095     return out << "GL_2D";
04096   case GL_3D:
04097     return out << "GL_3D";
04098   case GL_3D_COLOR:
04099     return out << "GL_3D_COLOR";
04100   case GL_3D_COLOR_TEXTURE:
04101     return out << "GL_3D_COLOR_TEXTURE";
04102   case GL_4D_COLOR_TEXTURE:
04103     return out << "GL_4D_COLOR_TEXTURE";
04104   case GL_POINT_TOKEN:
04105     return out << "GL_POINT_TOKEN";
04106   case GL_LINE_TOKEN:
04107     return out << "GL_LINE_TOKEN";
04108   case GL_LINE_RESET_TOKEN:
04109     return out << "GL_LINE_RESET_TOKEN";
04110   case GL_POLYGON_TOKEN:
04111     return out << "GL_POLYGON_TOKEN";
04112   case GL_BITMAP_TOKEN:
04113     return out << "GL_BITMAP_TOKEN";
04114   case GL_DRAW_PIXEL_TOKEN:
04115     return out << "GL_DRAW_PIXEL_TOKEN";
04116   case GL_COPY_PIXEL_TOKEN:
04117     return out << "GL_COPY_PIXEL_TOKEN";
04118   case GL_PASS_THROUGH_TOKEN:
04119     return out << "GL_PASS_THROUGH_TOKEN";
04120   case GL_FEEDBACK_BUFFER_POINTER:
04121     return out << "GL_FEEDBACK_BUFFER_POINTER";
04122   case GL_FEEDBACK_BUFFER_SIZE:
04123     return out << "GL_FEEDBACK_BUFFER_SIZE";
04124   case GL_FEEDBACK_BUFFER_TYPE:
04125     return out << "GL_FEEDBACK_BUFFER_TYPE";
04126 
04127     /* Selection */
04128   case GL_SELECTION_BUFFER_POINTER:
04129     return out << "GL_SELECTION_BUFFER_POINTER";
04130   case GL_SELECTION_BUFFER_SIZE:
04131     return out << "GL_SELECTION_BUFFER_SIZE";
04132 
04133     /* Fog */
04134   case GL_FOG:
04135     return out << "GL_FOG";
04136   case GL_FOG_MODE:
04137     return out << "GL_FOG_MODE";
04138   case GL_FOG_DENSITY:
04139     return out << "GL_FOG_DENSITY";
04140   case GL_FOG_COLOR:
04141     return out << "GL_FOG_COLOR";
04142   case GL_FOG_INDEX:
04143     return out << "GL_FOG_INDEX";
04144   case GL_FOG_START:
04145     return out << "GL_FOG_START";
04146   case GL_FOG_END:
04147     return out << "GL_FOG_END";
04148   case GL_LINEAR:
04149     return out << "GL_LINEAR";
04150   case GL_EXP:
04151     return out << "GL_EXP";
04152   case GL_EXP2:
04153     return out << "GL_EXP2";
04154 
04155     /* Logic Ops */
04156   case GL_LOGIC_OP:
04157     return out << "GL_LOGIC_OP";
04158     /*
04159       case GL_INDEX_LOGIC_OP:
04160       return out << "GL_INDEX_LOGIC_OP";
04161     */
04162   case GL_COLOR_LOGIC_OP:
04163     return out << "GL_COLOR_LOGIC_OP";
04164   case GL_LOGIC_OP_MODE:
04165     return out << "GL_LOGIC_OP_MODE";
04166   case GL_CLEAR:
04167     return out << "GL_CLEAR";
04168   case GL_SET:
04169     return out << "GL_SET";
04170   case GL_COPY:
04171     return out << "GL_COPY";
04172   case GL_COPY_INVERTED:
04173     return out << "GL_COPY_INVERTED";
04174   case GL_NOOP:
04175     return out << "GL_NOOP";
04176   case GL_INVERT:
04177     return out << "GL_INVERT";
04178   case GL_AND:
04179     return out << "GL_AND";
04180   case GL_NAND:
04181     return out << "GL_NAND";
04182   case GL_OR:
04183     return out << "GL_OR";
04184   case GL_NOR:
04185     return out << "GL_NOR";
04186   case GL_XOR:
04187     return out << "GL_XOR";
04188   case GL_EQUIV:
04189     return out << "GL_EQUIV";
04190   case GL_AND_REVERSE:
04191     return out << "GL_AND_REVERSE";
04192   case GL_AND_INVERTED:
04193     return out << "GL_AND_INVERTED";
04194   case GL_OR_REVERSE:
04195     return out << "GL_OR_REVERSE";
04196   case GL_OR_INVERTED:
04197     return out << "GL_OR_INVERTED";
04198 
04199     /* Stencil */
04200   case GL_STENCIL_TEST:
04201     return out << "GL_STENCIL_TEST";
04202   case GL_STENCIL_WRITEMASK:
04203     return out << "GL_STENCIL_WRITEMASK";
04204   case GL_STENCIL_BITS:
04205     return out << "GL_STENCIL_BITS";
04206   case GL_STENCIL_FUNC:
04207     return out << "GL_STENCIL_FUNC";
04208   case GL_STENCIL_VALUE_MASK:
04209     return out << "GL_STENCIL_VALUE_MASK";
04210   case GL_STENCIL_REF:
04211     return out << "GL_STENCIL_REF";
04212   case GL_STENCIL_FAIL:
04213     return out << "GL_STENCIL_FAIL";
04214   case GL_STENCIL_PASS_DEPTH_PASS:
04215     return out << "GL_STENCIL_PASS_DEPTH_PASS";
04216   case GL_STENCIL_PASS_DEPTH_FAIL:
04217     return out << "GL_STENCIL_PASS_DEPTH_FAIL";
04218   case GL_STENCIL_CLEAR_VALUE:
04219     return out << "GL_STENCIL_CLEAR_VALUE";
04220   case GL_STENCIL_INDEX:
04221     return out << "GL_STENCIL_INDEX";
04222   case GL_KEEP:
04223     return out << "GL_KEEP";
04224   case GL_REPLACE:
04225     return out << "GL_REPLACE";
04226   case GL_INCR:
04227     return out << "GL_INCR";
04228   case GL_DECR:
04229     return out << "GL_DECR";
04230 
04231     /* Buffers, Pixel Drawing/Reading */
04232     /*
04233       case GL_NONE:
04234       return out << "GL_NONE";
04235     */
04236   case GL_LEFT:
04237     return out << "GL_LEFT";
04238   case GL_RIGHT:
04239     return out << "GL_RIGHT";
04240   case GL_FRONT_LEFT:
04241     return out << "GL_FRONT_LEFT";
04242   case GL_FRONT_RIGHT:
04243     return out << "GL_FRONT_RIGHT";
04244   case GL_BACK_LEFT:
04245     return out << "GL_BACK_LEFT";
04246   case GL_BACK_RIGHT:
04247     return out << "GL_BACK_RIGHT";
04248   case GL_AUX0:
04249     return out << "GL_AUX0";
04250   case GL_AUX1:
04251     return out << "GL_AUX1";
04252   case GL_AUX2:
04253     return out << "GL_AUX2";
04254   case GL_AUX3:
04255     return out << "GL_AUX3";
04256   case GL_COLOR_INDEX:
04257     return out << "GL_COLOR_INDEX";
04258   case GL_RED:
04259     return out << "GL_RED";
04260   case GL_GREEN:
04261     return out << "GL_GREEN";
04262   case GL_BLUE:
04263     return out << "GL_BLUE";
04264   case GL_ALPHA:
04265     return out << "GL_ALPHA";
04266   case GL_LUMINANCE:
04267     return out << "GL_LUMINANCE";
04268   case GL_LUMINANCE_ALPHA:
04269     return out << "GL_LUMINANCE_ALPHA";
04270   case GL_ALPHA_BITS:
04271     return out << "GL_ALPHA_BITS";
04272   case GL_RED_BITS:
04273     return out << "GL_RED_BITS";
04274   case GL_GREEN_BITS:
04275     return out << "GL_GREEN_BITS";
04276   case GL_BLUE_BITS:
04277     return out << "GL_BLUE_BITS";
04278   case GL_INDEX_BITS:
04279     return out << "GL_INDEX_BITS";
04280   case GL_SUBPIXEL_BITS:
04281     return out << "GL_SUBPIXEL_BITS";
04282   case GL_AUX_BUFFERS:
04283     return out << "GL_AUX_BUFFERS";
04284   case GL_READ_BUFFER:
04285     return out << "GL_READ_BUFFER";
04286   case GL_DRAW_BUFFER:
04287     return out << "GL_DRAW_BUFFER";
04288   case GL_DOUBLEBUFFER:
04289     return out << "GL_DOUBLEBUFFER";
04290   case GL_STEREO:
04291     return out << "GL_STEREO";
04292   case GL_BITMAP:
04293     return out << "GL_BITMAP";
04294   case GL_COLOR:
04295     return out << "GL_COLOR";
04296   case GL_DEPTH:
04297     return out << "GL_DEPTH";
04298   case GL_STENCIL:
04299     return out << "GL_STENCIL";
04300   case GL_DITHER:
04301     return out << "GL_DITHER";
04302   case GL_RGB:
04303     return out << "GL_RGB";
04304   case GL_RGBA:
04305     return out << "GL_RGBA";
04306 
04307     /* Implementation limits */
04308   case GL_MAX_LIST_NESTING:
04309     return out << "GL_MAX_LIST_NESTING";
04310   case GL_MAX_ATTRIB_STACK_DEPTH:
04311     return out << "GL_MAX_ATTRIB_STACK_DEPTH";
04312   case GL_MAX_MODELVIEW_STACK_DEPTH:
04313     return out << "GL_MAX_MODELVIEW_STACK_DEPTH";
04314   case GL_MAX_NAME_STACK_DEPTH:
04315     return out << "GL_MAX_NAME_STACK_DEPTH";
04316   case GL_MAX_PROJECTION_STACK_DEPTH:
04317     return out << "GL_MAX_PROJECTION_STACK_DEPTH";
04318   case GL_MAX_TEXTURE_STACK_DEPTH:
04319     return out << "GL_MAX_TEXTURE_STACK_DEPTH";
04320   case GL_MAX_EVAL_ORDER:
04321     return out << "GL_MAX_EVAL_ORDER";
04322   case GL_MAX_LIGHTS:
04323     return out << "GL_MAX_LIGHTS";
04324   case GL_MAX_CLIP_PLANES:
04325     return out << "GL_MAX_CLIP_PLANES";
04326   case GL_MAX_TEXTURE_SIZE:
04327     return out << "GL_MAX_TEXTURE_SIZE";
04328   case GL_MAX_PIXEL_MAP_TABLE:
04329     return out << "GL_MAX_PIXEL_MAP_TABLE";
04330   case GL_MAX_VIEWPORT_DIMS:
04331     return out << "GL_MAX_VIEWPORT_DIMS";
04332   case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
04333     return out << "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH";
04334 
04335     /* Gets */
04336   case GL_ATTRIB_STACK_DEPTH:
04337     return out << "GL_ATTRIB_STACK_DEPTH";
04338   case GL_CLIENT_ATTRIB_STACK_DEPTH:
04339     return out << "GL_CLIENT_ATTRIB_STACK_DEPTH";
04340   case GL_COLOR_CLEAR_VALUE:
04341     return out << "GL_COLOR_CLEAR_VALUE";
04342   case GL_COLOR_WRITEMASK:
04343     return out << "GL_COLOR_WRITEMASK";
04344   case GL_CURRENT_INDEX:
04345     return out << "GL_CURRENT_INDEX";
04346   case GL_CURRENT_COLOR:
04347     return out << "GL_CURRENT_COLOR";
04348   case GL_CURRENT_NORMAL:
04349     return out << "GL_CURRENT_NORMAL";
04350   case GL_CURRENT_RASTER_COLOR:
04351     return out << "GL_CURRENT_RASTER_COLOR";
04352   case GL_CURRENT_RASTER_DISTANCE:
04353     return out << "GL_CURRENT_RASTER_DISTANCE";
04354   case GL_CURRENT_RASTER_INDEX:
04355     return out << "GL_CURRENT_RASTER_INDEX";
04356   case GL_CURRENT_RASTER_POSITION:
04357     return out << "GL_CURRENT_RASTER_POSITION";
04358   case GL_CURRENT_RASTER_TEXTURE_COORDS:
04359     return out << "GL_CURRENT_RASTER_TEXTURE_COORDS";
04360   case GL_CURRENT_RASTER_POSITION_VALID:
04361     return out << "GL_CURRENT_RASTER_POSITION_VALID";
04362   case GL_CURRENT_TEXTURE_COORDS:
04363     return out << "GL_CURRENT_TEXTURE_COORDS";
04364   case GL_INDEX_CLEAR_VALUE:
04365     return out << "GL_INDEX_CLEAR_VALUE";
04366   case GL_INDEX_MODE:
04367     return out << "GL_INDEX_MODE";
04368   case GL_INDEX_WRITEMASK:
04369     return out << "GL_INDEX_WRITEMASK";
04370   case GL_MODELVIEW_MATRIX:
04371     return out << "GL_MODELVIEW_MATRIX";
04372   case GL_MODELVIEW_STACK_DEPTH:
04373     return out << "GL_MODELVIEW_STACK_DEPTH";
04374   case GL_NAME_STACK_DEPTH:
04375     return out << "GL_NAME_STACK_DEPTH";
04376   case GL_PROJECTION_MATRIX:
04377     return out << "GL_PROJECTION_MATRIX";
04378   case GL_PROJECTION_STACK_DEPTH:
04379     return out << "GL_PROJECTION_STACK_DEPTH";
04380   case GL_RENDER_MODE:
04381     return out << "GL_RENDER_MODE";
04382   case GL_RGBA_MODE:
04383     return out << "GL_RGBA_MODE";
04384   case GL_TEXTURE_MATRIX:
04385     return out << "GL_TEXTURE_MATRIX";
04386   case GL_TEXTURE_STACK_DEPTH:
04387     return out << "GL_TEXTURE_STACK_DEPTH";
04388   case GL_VIEWPORT:
04389     return out << "GL_VIEWPORT";
04390 
04391 
04392     /* Evaluators */
04393   case GL_AUTO_NORMAL:
04394     return out << "GL_AUTO_NORMAL";
04395   case GL_MAP1_COLOR_4:
04396     return out << "GL_MAP1_COLOR_4";
04397   case GL_MAP1_GRID_DOMAIN:
04398     return out << "GL_MAP1_GRID_DOMAIN";
04399   case GL_MAP1_GRID_SEGMENTS:
04400     return out << "GL_MAP1_GRID_SEGMENTS";
04401   case GL_MAP1_INDEX:
04402     return out << "GL_MAP1_INDEX";
04403   case GL_MAP1_NORMAL:
04404     return out << "GL_MAP1_NORMAL";
04405   case GL_MAP1_TEXTURE_COORD_1:
04406     return out << "GL_MAP1_TEXTURE_COORD_1";
04407   case GL_MAP1_TEXTURE_COORD_2:
04408     return out << "GL_MAP1_TEXTURE_COORD_2";
04409   case GL_MAP1_TEXTURE_COORD_3:
04410     return out << "GL_MAP1_TEXTURE_COORD_3";
04411   case GL_MAP1_TEXTURE_COORD_4:
04412     return out << "GL_MAP1_TEXTURE_COORD_4";
04413   case GL_MAP1_VERTEX_3:
04414     return out << "GL_MAP1_VERTEX_3";
04415   case GL_MAP1_VERTEX_4:
04416     return out << "GL_MAP1_VERTEX_4";
04417   case GL_MAP2_COLOR_4:
04418     return out << "GL_MAP2_COLOR_4";
04419   case GL_MAP2_GRID_DOMAIN:
04420     return out << "GL_MAP2_GRID_DOMAIN";
04421   case GL_MAP2_GRID_SEGMENTS:
04422     return out << "GL_MAP2_GRID_SEGMENTS";
04423   case GL_MAP2_INDEX:
04424     return out << "GL_MAP2_INDEX";
04425   case GL_MAP2_NORMAL:
04426     return out << "GL_MAP2_NORMAL";
04427   case GL_MAP2_TEXTURE_COORD_1:
04428     return out << "GL_MAP2_TEXTURE_COORD_1";
04429   case GL_MAP2_TEXTURE_COORD_2:
04430     return out << "GL_MAP2_TEXTURE_COORD_2";
04431   case GL_MAP2_TEXTURE_COORD_3:
04432     return out << "GL_MAP2_TEXTURE_COORD_3";
04433   case GL_MAP2_TEXTURE_COORD_4:
04434     return out << "GL_MAP2_TEXTURE_COORD_4";
04435   case GL_MAP2_VERTEX_3:
04436     return out << "GL_MAP2_VERTEX_3";
04437   case GL_MAP2_VERTEX_4:
04438     return out << "GL_MAP2_VERTEX_4";
04439   case GL_COEFF:
04440     return out << "GL_COEFF";
04441   case GL_DOMAIN:
04442     return out << "GL_DOMAIN";
04443   case GL_ORDER:
04444     return out << "GL_ORDER";
04445 
04446     /* Hints */
04447   case GL_FOG_HINT:
04448     return out << "GL_FOG_HINT";
04449   case GL_LINE_SMOOTH_HINT:
04450     return out << "GL_LINE_SMOOTH_HINT";
04451   case GL_PERSPECTIVE_CORRECTION_HINT:
04452     return out << "GL_PERSPECTIVE_CORRECTION_HINT";
04453   case GL_POINT_SMOOTH_HINT:
04454     return out << "GL_POINT_SMOOTH_HINT";
04455   case GL_POLYGON_SMOOTH_HINT:
04456     return out << "GL_POLYGON_SMOOTH_HINT";
04457   case GL_DONT_CARE:
04458     return out << "GL_DONT_CARE";
04459   case GL_FASTEST:
04460     return out << "GL_FASTEST";
04461   case GL_NICEST:
04462     return out << "GL_NICEST";
04463 
04464     /* Scissor box */
04465   case GL_SCISSOR_TEST:
04466     return out << "GL_SCISSOR_TEST";
04467   case GL_SCISSOR_BOX:
04468     return out << "GL_SCISSOR_BOX";
04469 
04470     /* Pixel Mode / Transfer */
04471   case GL_MAP_COLOR:
04472     return out << "GL_MAP_COLOR";
04473   case GL_MAP_STENCIL:
04474     return out << "GL_MAP_STENCIL";
04475   case GL_INDEX_SHIFT:
04476     return out << "GL_INDEX_SHIFT";
04477   case GL_INDEX_OFFSET:
04478     return out << "GL_INDEX_OFFSET";
04479   case GL_RED_SCALE:
04480     return out << "GL_RED_SCALE";
04481   case GL_RED_BIAS:
04482     return out << "GL_RED_BIAS";
04483   case GL_GREEN_SCALE:
04484     return out << "GL_GREEN_SCALE";
04485   case GL_GREEN_BIAS:
04486     return out << "GL_GREEN_BIAS";
04487   case GL_BLUE_SCALE:
04488     return out << "GL_BLUE_SCALE";
04489   case GL_BLUE_BIAS:
04490     return out << "GL_BLUE_BIAS";
04491   case GL_ALPHA_SCALE:
04492     return out << "GL_ALPHA_SCALE";
04493   case GL_ALPHA_BIAS:
04494     return out << "GL_ALPHA_BIAS";
04495   case GL_DEPTH_SCALE:
04496     return out << "GL_DEPTH_SCALE";
04497   case GL_DEPTH_BIAS:
04498     return out << "GL_DEPTH_BIAS";
04499   case GL_PIXEL_MAP_S_TO_S_SIZE:
04500     return out << "GL_PIXEL_MAP_S_TO_S_SIZE";
04501   case GL_PIXEL_MAP_I_TO_I_SIZE:
04502     return out << "GL_PIXEL_MAP_I_TO_I_SIZE";
04503   case GL_PIXEL_MAP_I_TO_R_SIZE:
04504     return out << "GL_PIXEL_MAP_I_TO_R_SIZE";
04505   case GL_PIXEL_MAP_I_TO_G_SIZE:
04506     return out << "GL_PIXEL_MAP_I_TO_G_SIZE";
04507   case GL_PIXEL_MAP_I_TO_B_SIZE:
04508     return out << "GL_PIXEL_MAP_I_TO_B_SIZE";
04509   case GL_PIXEL_MAP_I_TO_A_SIZE:
04510     return out << "GL_PIXEL_MAP_I_TO_A_SIZE";
04511   case GL_PIXEL_MAP_R_TO_R_SIZE:
04512     return out << "GL_PIXEL_MAP_R_TO_R_SIZE";
04513   case GL_PIXEL_MAP_G_TO_G_SIZE:
04514     return out << "GL_PIXEL_MAP_G_TO_G_SIZE";
04515   case GL_PIXEL_MAP_B_TO_B_SIZE:
04516     return out << "GL_PIXEL_MAP_B_TO_B_SIZE";
04517   case GL_PIXEL_MAP_A_TO_A_SIZE:
04518     return out << "GL_PIXEL_MAP_A_TO_A_SIZE";
04519   case GL_PIXEL_MAP_S_TO_S:
04520     return out << "GL_PIXEL_MAP_S_TO_S";
04521   case GL_PIXEL_MAP_I_TO_I:
04522     return out << "GL_PIXEL_MAP_I_TO_I";
04523   case GL_PIXEL_MAP_I_TO_R:
04524     return out << "GL_PIXEL_MAP_I_TO_R";
04525   case GL_PIXEL_MAP_I_TO_G:
04526     return out << "GL_PIXEL_MAP_I_TO_G";
04527   case GL_PIXEL_MAP_I_TO_B:
04528     return out << "GL_PIXEL_MAP_I_TO_B";
04529   case GL_PIXEL_MAP_I_TO_A:
04530     return out << "GL_PIXEL_MAP_I_TO_A";
04531   case GL_PIXEL_MAP_R_TO_R:
04532     return out << "GL_PIXEL_MAP_R_TO_R";
04533   case GL_PIXEL_MAP_G_TO_G:
04534     return out << "GL_PIXEL_MAP_G_TO_G";
04535   case GL_PIXEL_MAP_B_TO_B:
04536     return out << "GL_PIXEL_MAP_B_TO_B";
04537   case GL_PIXEL_MAP_A_TO_A:
04538     return out << "GL_PIXEL_MAP_A_TO_A";
04539   case GL_PACK_ALIGNMENT:
04540     return out << "GL_PACK_ALIGNMENT";
04541   case GL_PACK_LSB_FIRST:
04542     return out << "GL_PACK_LSB_FIRST";
04543   case GL_PACK_ROW_LENGTH:
04544     return out << "GL_PACK_ROW_LENGTH";
04545   case GL_PACK_SKIP_PIXELS:
04546     return out << "GL_PACK_SKIP_PIXELS";
04547   case GL_PACK_SKIP_ROWS:
04548     return out << "GL_PACK_SKIP_ROWS";
04549   case GL_PACK_SWAP_BYTES:
04550     return out << "GL_PACK_SWAP_BYTES";
04551   case GL_UNPACK_ALIGNMENT:
04552     return out << "GL_UNPACK_ALIGNMENT";
04553   case GL_UNPACK_LSB_FIRST:
04554     return out << "GL_UNPACK_LSB_FIRST";
04555   case GL_UNPACK_ROW_LENGTH:
04556     return out << "GL_UNPACK_ROW_LENGTH";
04557   case GL_UNPACK_SKIP_PIXELS:
04558     return out << "GL_UNPACK_SKIP_PIXELS";
04559   case GL_UNPACK_SKIP_ROWS:
04560     return out << "GL_UNPACK_SKIP_ROWS";
04561   case GL_UNPACK_SWAP_BYTES:
04562     return out << "GL_UNPACK_SWAP_BYTES";
04563   case GL_ZOOM_X:
04564     return out << "GL_ZOOM_X";
04565   case GL_ZOOM_Y:
04566     return out << "GL_ZOOM_Y";
04567 
04568     /* Texture mapping */
04569   case GL_TEXTURE_ENV:
04570     return out << "GL_TEXTURE_ENV";
04571   case GL_TEXTURE_ENV_MODE:
04572     return out << "GL_TEXTURE_ENV_MODE";
04573   case GL_TEXTURE_1D:
04574     return out << "GL_TEXTURE_1D";
04575   case GL_TEXTURE_2D:
04576     return out << "GL_TEXTURE_2D";
04577   case GL_TEXTURE_WRAP_S:
04578     return out << "GL_TEXTURE_WRAP_S";
04579   case GL_TEXTURE_WRAP_T:
04580     return out << "GL_TEXTURE_WRAP_T";
04581   case GL_TEXTURE_MAG_FILTER:
04582     return out << "GL_TEXTURE_MAG_FILTER";
04583   case GL_TEXTURE_MIN_FILTER:
04584     return out << "GL_TEXTURE_MIN_FILTER";
04585   case GL_TEXTURE_ENV_COLOR:
04586     return out << "GL_TEXTURE_ENV_COLOR";
04587   case GL_TEXTURE_GEN_S:
04588     return out << "GL_TEXTURE_GEN_S";
04589   case GL_TEXTURE_GEN_T:
04590     return out << "GL_TEXTURE_GEN_T";
04591   case GL_TEXTURE_GEN_MODE:
04592     return out << "GL_TEXTURE_GEN_MODE";
04593   case GL_TEXTURE_BORDER_COLOR:
04594     return out << "GL_TEXTURE_BORDER_COLOR";
04595   case GL_TEXTURE_WIDTH:
04596     return out << "GL_TEXTURE_WIDTH";
04597   case GL_TEXTURE_HEIGHT:
04598     return out << "GL_TEXTURE_HEIGHT";
04599   case GL_TEXTURE_BORDER:
04600     return out << "GL_TEXTURE_BORDER";
04601   case GL_TEXTURE_COMPONENTS:
04602     return out << "GL_TEXTURE_COMPONENTS";
04603   case GL_TEXTURE_RED_SIZE:
04604     return out << "GL_TEXTURE_RED_SIZE";
04605   case GL_TEXTURE_GREEN_SIZE:
04606     return out << "GL_TEXTURE_GREEN_SIZE";
04607   case GL_TEXTURE_BLUE_SIZE:
04608     return out << "GL_TEXTURE_BLUE_SIZE";
04609   case GL_TEXTURE_ALPHA_SIZE:
04610     return out << "GL_TEXTURE_ALPHA_SIZE";
04611   case GL_TEXTURE_LUMINANCE_SIZE:
04612     return out << "GL_TEXTURE_LUMINANCE_SIZE";
04613   case GL_TEXTURE_INTENSITY_SIZE:
04614     return out << "GL_TEXTURE_INTENSITY_SIZE";
04615   case GL_NEAREST_MIPMAP_NEAREST:
04616     return out << "GL_NEAREST_MIPMAP_NEAREST";
04617   case GL_NEAREST_MIPMAP_LINEAR:
04618     return out << "GL_NEAREST_MIPMAP_LINEAR";
04619   case GL_LINEAR_MIPMAP_NEAREST:
04620     return out << "GL_LINEAR_MIPMAP_NEAREST";
04621   case GL_LINEAR_MIPMAP_LINEAR:
04622     return out << "GL_LINEAR_MIPMAP_LINEAR";
04623   case GL_OBJECT_LINEAR:
04624     return out << "GL_OBJECT_LINEAR";
04625   case GL_OBJECT_PLANE:
04626     return out << "GL_OBJECT_PLANE";
04627   case GL_EYE_LINEAR:
04628     return out << "GL_EYE_LINEAR";
04629   case GL_EYE_PLANE:
04630     return out << "GL_EYE_PLANE";
04631   case GL_SPHERE_MAP:
04632     return out << "GL_SPHERE_MAP";
04633   case GL_DECAL:
04634     return out << "GL_DECAL";
04635   case GL_MODULATE:
04636     return out << "GL_MODULATE";
04637   case GL_NEAREST:
04638     return out << "GL_NEAREST";
04639   case GL_REPEAT:
04640     return out << "GL_REPEAT";
04641   case GL_CLAMP:
04642     return out << "GL_CLAMP";
04643   case GL_S:
04644     return out << "GL_S";
04645   case GL_T:
04646     return out << "GL_T";
04647   case GL_R:
04648     return out << "GL_R";
04649   case GL_Q:
04650     return out << "GL_Q";
04651   case GL_TEXTURE_GEN_R:
04652     return out << "GL_TEXTURE_GEN_R";
04653   case GL_TEXTURE_GEN_Q:
04654     return out << "GL_TEXTURE_GEN_Q";
04655 
04656     /* GL 1.1 texturing */
04657   case GL_PROXY_TEXTURE_1D:
04658     return out << "GL_PROXY_TEXTURE_1D";
04659   case GL_PROXY_TEXTURE_2D:
04660     return out << "GL_PROXY_TEXTURE_2D";
04661   case GL_TEXTURE_PRIORITY:
04662     return out << "GL_TEXTURE_PRIORITY";
04663   case GL_TEXTURE_RESIDENT:
04664     return out << "GL_TEXTURE_RESIDENT";
04665   case GL_TEXTURE_BINDING_1D:
04666     return out << "GL_TEXTURE_BINDING_1D";
04667   case GL_TEXTURE_BINDING_2D:
04668     return out << "GL_TEXTURE_BINDING_2D";
04669     /*
04670       case GL_TEXTURE_INTERNAL_FORMAT:
04671       return out << "GL_TEXTURE_INTERNAL_FORMAT";
04672     */
04673 
04674     /* GL 1.2 texturing */
04675   #ifdef USING_OPENGL_1_2 //[
04676   case GL_PACK_SKIP_IMAGES:
04677     return out << "GL_PACK_SKIP_IMAGES";
04678   case GL_PACK_IMAGE_HEIGHT:
04679     return out << "GL_PACK_IMAGE_HEIGHT";
04680   case GL_UNPACK_SKIP_IMAGES:
04681     return out << "GL_UNPACK_SKIP_IMAGES";
04682   case GL_UNPACK_IMAGE_HEIGHT:
04683     return out << "GL_UNPACK_IMAGE_HEIGHT";
04684   case GL_TEXTURE_3D:
04685     return out << "GL_TEXTURE_3D";
04686   case GL_PROXY_TEXTURE_3D:
04687     return out << "GL_PROXY_TEXTURE_3D";
04688   case GL_TEXTURE_DEPTH:
04689     return out << "GL_TEXTURE_DEPTH";
04690   case GL_TEXTURE_WRAP_R:
04691     return out << "GL_TEXTURE_WRAP_R";
04692   case GL_MAX_3D_TEXTURE_SIZE:
04693     return out << "GL_MAX_3D_TEXTURE_SIZE";
04694 #ifdef GL_TEXTURE_BINDING_3D
04695   case GL_TEXTURE_BINDING_3D:
04696     return out << "GL_TEXTURE_BINDING_3D";
04697 #endif
04698   #endif //]
04699 
04700     /* Internal texture formats (GL 1.1) */
04701   case GL_ALPHA4:
04702     return out << "GL_ALPHA4";
04703   case GL_ALPHA8:
04704     return out << "GL_ALPHA8";
04705   case GL_ALPHA12:
04706     return out << "GL_ALPHA12";
04707   case GL_ALPHA16:
04708     return out << "GL_ALPHA16";
04709   case GL_LUMINANCE4:
04710     return out << "GL_LUMINANCE4";
04711   case GL_LUMINANCE8:
04712     return out << "GL_LUMINANCE8";
04713   case GL_LUMINANCE12:
04714     return out << "GL_LUMINANCE12";
04715   case GL_LUMINANCE16:
04716     return out << "GL_LUMINANCE16";
04717   case GL_LUMINANCE4_ALPHA4:
04718     return out << "GL_LUMINANCE4_ALPHA4";
04719   case GL_LUMINANCE6_ALPHA2:
04720     return out << "GL_LUMINANCE6_ALPHA2";
04721   case GL_LUMINANCE8_ALPHA8:
04722     return out << "GL_LUMINANCE8_ALPHA8";
04723   case GL_LUMINANCE12_ALPHA4:
04724     return out << "GL_LUMINANCE12_ALPHA4";
04725   case GL_LUMINANCE12_ALPHA12:
04726     return out << "GL_LUMINANCE12_ALPHA12";
04727   case GL_LUMINANCE16_ALPHA16:
04728     return out << "GL_LUMINANCE16_ALPHA16";
04729   case GL_INTENSITY:
04730     return out << "GL_INTENSITY";
04731   case GL_INTENSITY4:
04732     return out << "GL_INTENSITY4";
04733   case GL_INTENSITY8:
04734     return out << "GL_INTENSITY8";
04735   case GL_INTENSITY12:
04736     return out << "GL_INTENSITY12";
04737   case GL_INTENSITY16:
04738     return out << "GL_INTENSITY16";
04739   case GL_R3_G3_B2:
04740     return out << "GL_R3_G3_B2";
04741   case GL_RGB4:
04742     return out << "GL_RGB4";
04743   case GL_RGB5:
04744     return out << "GL_RGB5";
04745   case GL_RGB8:
04746     return out << "GL_RGB8";
04747   case GL_RGB10:
04748     return out << "GL_RGB10";
04749   case GL_RGB12:
04750     return out << "GL_RGB12";
04751   case GL_RGB16:
04752     return out << "GL_RGB16";
04753   case GL_RGBA2:
04754     return out << "GL_RGBA2";
04755   case GL_RGBA4:
04756     return out << "GL_RGBA4";
04757   case GL_RGB5_A1:
04758     return out << "GL_RGB5_A1";
04759   case GL_RGBA8:
04760     return out << "GL_RGBA8";
04761   case GL_RGB10_A2:
04762     return out << "GL_RGB10_A2";
04763   case GL_RGBA12:
04764     return out << "GL_RGBA12";
04765   case GL_RGBA16:
04766     return out << "GL_RGBA16";
04767 
04768     /* Utility */
04769   case GL_VENDOR:
04770     return out << "GL_VENDOR";
04771   case GL_RENDERER:
04772     return out << "GL_RENDERER";
04773   case GL_VERSION:
04774     return out << "GL_VERSION";
04775   case GL_EXTENSIONS:
04776     return out << "GL_EXTENSIONS";
04777 
04778     /* Errors */
04779   case GL_INVALID_VALUE:
04780     return out << "GL_INVALID_VALUE";
04781   case GL_INVALID_ENUM:
04782     return out << "GL_INVALID_ENUM";
04783   case GL_INVALID_OPERATION:
04784     return out << "GL_INVALID_OPERATION";
04785   case GL_STACK_OVERFLOW:
04786     return out << "GL_STACK_OVERFLOW";
04787   case GL_STACK_UNDERFLOW:
04788     return out << "GL_STACK_UNDERFLOW";
04789   case GL_OUT_OF_MEMORY:
04790     return out << "GL_OUT_OF_MEMORY";
04791 
04792     /* OpenGL 1.2 */
04793   #ifdef USING_OPENGL_1_2 //[
04794   case GL_RESCALE_NORMAL:
04795     return out << "GL_RESCALE_NORMAL";
04796   case GL_CLAMP_TO_EDGE:
04797     return out << "GL_CLAMP_TO_EDGE";
04798   case GL_MAX_ELEMENTS_VERTICES:
04799     return out << "GL_MAX_ELEMENTS_VERTICES";
04800   case GL_MAX_ELEMENTS_INDICES:
04801     return out << "GL_MAX_ELEMENTS_INDICES";
04802   case GL_BGR:
04803     return out << "GL_BGR";
04804   case GL_BGRA:
04805     return out << "GL_BGRA";
04806   case GL_UNSIGNED_BYTE_3_3_2:
04807     return out << "GL_UNSIGNED_BYTE_3_3_2";
04808   case GL_UNSIGNED_BYTE_2_3_3_REV:
04809     return out << "GL_UNSIGNED_BYTE_2_3_3_REV";
04810   case GL_UNSIGNED_SHORT_5_6_5:
04811     return out << "GL_UNSIGNED_SHORT_5_6_5";
04812   case GL_UNSIGNED_SHORT_5_6_5_REV:
04813     return out << "GL_UNSIGNED_SHORT_5_6_5_REV";
04814   case GL_UNSIGNED_SHORT_4_4_4_4:
04815     return out << "GL_UNSIGNED_SHORT_4_4_4_4";
04816   case GL_UNSIGNED_SHORT_4_4_4_4_REV:
04817     return out << "GL_UNSIGNED_SHORT_4_4_4_4_REV";
04818   case GL_UNSIGNED_SHORT_5_5_5_1:
04819     return out << "GL_UNSIGNED_SHORT_5_5_5_1";
04820   case GL_UNSIGNED_SHORT_1_5_5_5_REV:
04821     return out << "GL_UNSIGNED_SHORT_1_5_5_5_REV";
04822   case GL_UNSIGNED_INT_8_8_8_8:
04823     return out << "GL_UNSIGNED_INT_8_8_8_8";
04824   case GL_UNSIGNED_INT_8_8_8_8_REV:
04825     return out << "GL_UNSIGNED_INT_8_8_8_8_REV";
04826   case GL_UNSIGNED_INT_10_10_10_2:
04827     return out << "GL_UNSIGNED_INT_10_10_10_2";
04828   case GL_UNSIGNED_INT_2_10_10_10_REV:
04829     return out << "GL_UNSIGNED_INT_2_10_10_10_REV";
04830   case GL_LIGHT_MODEL_COLOR_CONTROL:
04831     return out << "GL_LIGHT_MODEL_COLOR_CONTROL";
04832   case GL_SINGLE_COLOR:
04833     return out << "GL_SINGLE_COLOR";
04834   case GL_SEPARATE_SPECULAR_COLOR:
04835     return out << "GL_SEPARATE_SPECULAR_COLOR";
04836   case GL_TEXTURE_MIN_LOD:
04837     return out << "GL_TEXTURE_MIN_LOD";
04838   case GL_TEXTURE_MAX_LOD:
04839     return out << "GL_TEXTURE_MAX_LOD";
04840   case GL_TEXTURE_BASE_LEVEL:
04841     return out << "GL_TEXTURE_BASE_LEVEL";
04842   case GL_TEXTURE_MAX_LEVEL:
04843     return out << "GL_TEXTURE_MAX_LEVEL";
04844   #endif //]
04845   }
04846 
04847   return out << (int)v;
04848 }
04849 #endif

Generated on Fri May 2 00:36:02 2003 for Panda by doxygen1.3