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

panda/src/glgsg/glGraphicsStateGuardian.cxx

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

Generated on Fri May 2 00:39:07 2003 for Panda by doxygen1.3