Explorar el Código

move rotate and decompose operations into cull

David Rose hace 20 años
padre
commit
2434300804
Se han modificado 44 ficheros con 716 adiciones y 604 borrados
  1. 8 20
      panda/src/display/graphicsStateGuardian.cxx
  2. 2 2
      panda/src/display/graphicsStateGuardian.h
  3. 35 0
      panda/src/display/standardMunger.cxx
  4. 1 0
      panda/src/display/standardMunger.h
  5. 0 6
      panda/src/dxgsg7/config_dxgsg7.cxx
  6. 0 1
      panda/src/dxgsg7/config_dxgsg7.h
  7. 3 3
      panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx
  8. 0 6
      panda/src/dxgsg8/config_dxgsg8.cxx
  9. 0 1
      panda/src/dxgsg8/config_dxgsg8.h
  10. 93 40
      panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx
  11. 1 0
      panda/src/dxgsg8/dxGraphicsStateGuardian8.h
  12. 1 1
      panda/src/dxgsg8/dxIndexBufferContext8.cxx
  13. 8 5
      panda/src/dxgsg8/wdxGraphicsWindow8.cxx
  14. 0 6
      panda/src/dxgsg9/config_dxgsg9.cxx
  15. 0 1
      panda/src/dxgsg9/config_dxgsg9.h
  16. 8 5
      panda/src/dxgsg9/wdxGraphicsWindow9.cxx
  17. 125 110
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  18. 16 7
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  19. 58 15
      panda/src/gobj/qpgeom.I
  20. 130 40
      panda/src/gobj/qpgeom.cxx
  21. 12 4
      panda/src/gobj/qpgeom.h
  22. 39 19
      panda/src/gobj/qpgeomEnums.h
  23. 1 1
      panda/src/gobj/qpgeomLines.cxx
  24. 13 1
      panda/src/gobj/qpgeomLinestrips.cxx
  25. 1 1
      panda/src/gobj/qpgeomLinestrips.h
  26. 15 0
      panda/src/gobj/qpgeomPoints.cxx
  27. 1 0
      panda/src/gobj/qpgeomPoints.h
  28. 30 91
      panda/src/gobj/qpgeomPrimitive.I
  29. 47 160
      panda/src/gobj/qpgeomPrimitive.cxx
  30. 8 24
      panda/src/gobj/qpgeomPrimitive.h
  31. 14 2
      panda/src/gobj/qpgeomTrifans.cxx
  32. 1 0
      panda/src/gobj/qpgeomTrifans.h
  33. 13 1
      panda/src/gobj/qpgeomTristrips.cxx
  34. 1 0
      panda/src/gobj/qpgeomTristrips.h
  35. 0 1
      panda/src/gobj/qpgeomVertexData.cxx
  36. 1 1
      panda/src/gsgbase/graphicsStateGuardianBase.h
  37. 2 2
      panda/src/pgraph/cullableObject.cxx
  38. 9 9
      panda/src/pgraph/renderModeAttrib.I
  39. 1 1
      panda/src/pgraph/renderModeAttrib.h
  40. 7 7
      panda/src/pgraph/renderState.I
  41. 1 1
      panda/src/pgraph/renderState.h
  42. 7 7
      panda/src/pgraph/texGenAttrib.I
  43. 1 1
      panda/src/pgraph/texGenAttrib.h
  44. 2 1
      panda/src/pstatclient/pStatProperties.cxx

+ 8 - 20
panda/src/display/graphicsStateGuardian.cxx

@@ -122,7 +122,7 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
   _supports_generate_mipmap = false;
   _supports_render_texture = false;
 
-  _supported_point_rendering = 0;
+  _supported_geom_rendering = 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -153,20 +153,20 @@ get_supports_multisample() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::get_supported_point_rendering
+//     Function: GraphicsStateGuardian::get_supported_geom_rendering
 //       Access: Published, Virtual
-//  Description: Returns the union of Geom::PointRendering values that
-//               this particular GSG can support directly.  If a point
+//  Description: Returns the union of Geom::GeomRendering values that
+//               this particular GSG can support directly.  If a Geom
 //               needs to be rendered that requires some additional
-//               properties, the StandardMunger will convert it into
-//               quads instead.
+//               properties, the StandardMunger and/or the
+//               CullableObject will convert it as needed.
 //
 //               This method is declared virtual solely so that it can
 //               be queried from cullableObject.cxx.
 ////////////////////////////////////////////////////////////////////
 int GraphicsStateGuardian::
-get_supported_point_rendering() const {
-  return _supported_point_rendering;
+get_supported_geom_rendering() const {
+  return _supported_geom_rendering;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -723,10 +723,6 @@ draw_triangles(const qpGeomTriangles *) {
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 draw_tristrips(const qpGeomTristrips *primitive) {
-  CPT(qpGeomPrimitive) new_prim = primitive->decompose();
-  if (!new_prim->is_of_type(qpGeomTristrips::get_class_type())) {
-    new_prim->draw(this);
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -736,10 +732,6 @@ draw_tristrips(const qpGeomTristrips *primitive) {
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 draw_trifans(const qpGeomTrifans *primitive) {
-  CPT(qpGeomPrimitive) new_prim = primitive->decompose();
-  if (!new_prim->is_of_type(qpGeomTrifans::get_class_type())) {
-    new_prim->draw(this);
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -758,10 +750,6 @@ draw_lines(const qpGeomLines *) {
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 draw_linestrips(const qpGeomLinestrips *primitive) {
-  CPT(qpGeomPrimitive) new_prim = primitive->decompose();
-  if (!new_prim->is_of_type(qpGeomLinestrips::get_class_type())) {
-    new_prim->draw(this);
-  }
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/display/graphicsStateGuardian.h

@@ -96,7 +96,7 @@ PUBLISHED:
   INLINE bool get_supports_generate_mipmap() const;
   INLINE bool get_supports_render_texture() const;
 
-  virtual int get_supported_point_rendering() const;
+  virtual int get_supported_geom_rendering() const;
 
 public:
   INLINE bool set_scene(SceneSetup *scene_setup);
@@ -326,7 +326,7 @@ protected:
   bool _supports_multisample;
   bool _supports_generate_mipmap;
   bool _supports_render_texture;
-  int _supported_point_rendering;
+  int _supported_geom_rendering;
 
 public:
   // Statistics

+ 35 - 0
panda/src/display/standardMunger.cxx

@@ -133,6 +133,41 @@ munge_data_impl(const qpGeomVertexData *data) {
   return new_data->convert_to(new_format);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: StandardMunger::munge_geom_impl
+//       Access: Protected, Virtual
+//  Description: Converts a Geom and/or its data as necessary.
+////////////////////////////////////////////////////////////////////
+bool StandardMunger::
+munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &vertex_data) {
+  int geom_rendering = geom->get_geom_rendering();
+  int supported_geom_rendering = _gsg->get_supported_geom_rendering();
+
+  int unsupported_bits = geom_rendering & ~supported_geom_rendering;
+
+  if (unsupported_bits != 0) {
+    // Even beyond munging the vertex format, we have to convert the
+    // Geom itself into a new primitive type the GSG can render
+    // directly.
+    if ((unsupported_bits & qpGeom::GR_composite_bits) != 0) {
+      // This decomposes everything in the primitive, so that if (for
+      // instance) the primitive contained both strips and fans, but
+      // the GSG didn't support fans, it would decompose the strips
+      // too.  To handle this correctly, we'd need a separate
+      // decompose_fans() and decompose_strips() call; but for now,
+      // we'll just say it's good enough.  In practice, we don't have
+      // any GSG's that can support strips without also supporting
+      // fans.
+      geom = geom->decompose();
+    }
+    if ((unsupported_bits & qpGeom::GR_shade_model_bits) != 0) {
+      geom = geom->rotate();
+    }
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: StandardMunger::compare_to_impl
 //       Access: Protected, Virtual

+ 1 - 0
panda/src/display/standardMunger.h

@@ -46,6 +46,7 @@ public:
 protected:
   virtual CPT(qpGeomVertexData) munge_data_impl(const qpGeomVertexData *data);
   virtual int compare_to_impl(const qpGeomMunger *other) const;
+  virtual bool munge_geom_impl(CPT(qpGeom) &geom, CPT(qpGeomVertexData) &data);
   virtual int geom_compare_to_impl(const qpGeomMunger *other) const;
 
 private:

+ 0 - 6
panda/src/dxgsg7/config_dxgsg7.cxx

@@ -35,12 +35,6 @@ NotifyCategoryDef(wdxdisplay7, "windisplay");
 ConfigVariableBool dx_full_screen
 ("dx-full-screen", false);
 
-//  Configure this true to force the rendering to sync to the video
-//  refresh, or false to let your frame rate go as high as it can,
-//  irrespective of the video refresh.
-ConfigVariableBool dx_sync_video
-("sync-video", true);
-
 // enable this to turn on full-screen anti-aliasing, if the HW supports it
 // this var is also used in wdxGraphicsWindows.cxx
 ConfigVariableBool dx_full_screen_antialiasing

+ 0 - 1
panda/src/dxgsg7/config_dxgsg7.h

@@ -29,7 +29,6 @@ NotifyCategoryDecl(dxgsg7, EXPCL_PANDADX, EXPTP_PANDADX);
 NotifyCategoryDecl(wdxdisplay7, EXPCL_PANDADX, EXPTP_PANDADX);
 
 extern ConfigVariableBool dx_full_screen;
-extern ConfigVariableBool dx_sync_video;
 extern ConfigVariableBool dx_no_vertex_fog;
 extern ConfigVariableBool dx_full_screen_antialiasing;
 extern ConfigVariableBool dx_use_rangebased_fog;

+ 3 - 3
panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx

@@ -4968,7 +4968,7 @@ void DXGraphicsStateGuardian7::show_full_screen_frame(void) {
     // Normally, we can just do the fast flip operation.
     DWORD dwFlipFlags = DDFLIP_WAIT;
 
-    if (!dx_sync_video) {
+    if (!sync_video) {
       // If the user indicated via Config that we shouldn't wait for
       // video sync, then don't wait (if the hardware supports this).
       // This will introduce visible artifacts like tearing, and may
@@ -5008,7 +5008,7 @@ void DXGraphicsStateGuardian7::show_windowed_frame(void) {
 
   DX_DECLARE_CLEAN(DDBLTFX, bltfx);
 
-  if (dx_sync_video) {
+  if (sync_video) {
     // Wait for the video refresh *before* we blt the rendered image
     // onto the window.  This will (a) prevent the "tearing" of the
     // image that would occur if only part of the image happened to be
@@ -5029,7 +5029,7 @@ void DXGraphicsStateGuardian7::show_windowed_frame(void) {
 
   hr = _pScrn->pddsPrimary->Blt( &_pScrn->view_rect, _pScrn->pddsBack,  NULL, DDBLT_DDFX | DDBLT_WAIT, &bltfx );
 
-  if (dx_sync_video) {
+  if (sync_video) {
     HRESULT hr = _pScrn->pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL);
     if(hr != DD_OK) {
       dxgsg7_cat.error() << "WaitForVerticalBlank() failed : " << ConvD3DErrorToString(hr) << endl;

+ 0 - 6
panda/src/dxgsg8/config_dxgsg8.cxx

@@ -40,12 +40,6 @@ NotifyCategoryDef(wdxdisplay8, "windisplay");
 ConfigVariableBool dx_show_transforms
 ("dx-show-transforms", false);
 
-//  Configure this true to force the rendering to sync to the video
-//  refresh, or false to let your frame rate go as high as it can,
-//  irrespective of the video refresh.
-ConfigVariableBool dx_sync_video
-("sync-video", true);
-
 // Set Level of MultiSampling to be used, if HW supports it.  Valid values are 2-16.
 ConfigVariableInt dx_multisample_antialiasing_level
 ("dx-multisample-antialiasing-level", 0);

+ 0 - 1
panda/src/dxgsg8/config_dxgsg8.h

@@ -29,7 +29,6 @@
 NotifyCategoryDecl(dxgsg8, EXPCL_PANDADX, EXPTP_PANDADX);
 NotifyCategoryDecl(wdxdisplay8, EXPCL_PANDADX, EXPTP_PANDADX);
 
-extern ConfigVariableBool dx_sync_video;
 extern ConfigVariableBool dx_no_vertex_fog;
 extern ConfigVariableBool dx_show_cursor_watermark;
 extern ConfigVariableBool dx_full_screen_antialiasing;

+ 93 - 40
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -190,38 +190,41 @@ DXGraphicsStateGuardian8::
 DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
   GraphicsStateGuardian(properties, CS_yup_left)
 {
+  reset_panda_gsg();
+  
+  _pScrn = NULL;
+  _pD3DDevice = NULL;
+  
+  _bDXisReady = false;
+  _transform_stale = false;
+  _vertex_blending_enabled = false;
+  _overlay_windows_supported = false;
+  
+  _pFvfBufBasePtr = NULL;
+  _index_buf=NULL;
+  
+  _vbuffer_active = false;
+  _ibuffer_active = false;
+  
+  //    _max_light_range = __D3DLIGHT_RANGE_MAX;
+  
+  // non-dx obj values inited here should not change if resize is
+  // called and dx objects need to be recreated (otherwise they
+  // belong in dx_init, with other renderstate
+  
+  ZeroMemory(&matIdentity,sizeof(D3DMATRIX));
+  matIdentity._11 = matIdentity._22 = matIdentity._33 = matIdentity._44 = 1.0f;
+  
+  _cur_read_pixel_buffer=RenderBuffer::T_front;
+  set_color_clear_value(_color_clear_value);
+  
+  // DirectX drivers seem to consistently invert the texture when
+  // they copy framebuffer-to-texture.  Ok.
+  _copy_texture_inverted = true;
 
-    reset_panda_gsg();
-
-    _pScrn = NULL;
-    _pD3DDevice = NULL;
-    
-    _bDXisReady = false;
-    _transform_stale = false;
-    _vertex_blending_enabled = false;
-    _overlay_windows_supported = false;
-
-    _pFvfBufBasePtr = NULL;
-    _index_buf=NULL;
-
-    _vbuffer_active = false;
-    _ibuffer_active = false;
-
-    //    _max_light_range = __D3DLIGHT_RANGE_MAX;
-
-    // non-dx obj values inited here should not change if resize is
-    // called and dx objects need to be recreated (otherwise they
-    // belong in dx_init, with other renderstate
-
-    ZeroMemory(&matIdentity,sizeof(D3DMATRIX));
-    matIdentity._11 = matIdentity._22 = matIdentity._33 = matIdentity._44 = 1.0f;
-
-    _cur_read_pixel_buffer=RenderBuffer::T_front;
-    set_color_clear_value(_color_clear_value);
-
-    // DirectX drivers seem to consistently invert the texture when
-    // they copy framebuffer-to-texture.  Ok.
-    _copy_texture_inverted = true;
+  _supported_geom_rendering = 
+    qpGeom::GR_triangle_strip | qpGeom::GR_triangle_fan |
+    qpGeom::GR_flat_first_vertex;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2749,7 +2752,7 @@ draw_triangles(const qpGeomTriangles *primitive) {
        primitive->get_min_vertex(),
        primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
        primitive->get_num_primitives(), 
-       primitive->get_flat_first_vertices(),
+       primitive->get_vertices(),
        D3DFMT_INDEX16,
        _vertex_data->get_array(0)->get_data(),
        _vertex_data->get_format()->get_array(0)->get_stride());
@@ -2765,8 +2768,6 @@ void DXGraphicsStateGuardian8::
 draw_tristrips(const qpGeomTristrips *primitive) {
   int min_vertex = primitive->get_min_vertex();
   int max_vertex = primitive->get_max_vertex();
-  //  CPTA_ushort vertices = primitive->get_flat_first_vertices();
-  CPTA_ushort vertices = primitive->get_vertices();
 
   if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
     // One long triangle strip, connected by the degenerate vertices
@@ -2779,17 +2780,15 @@ draw_tristrips(const qpGeomTristrips *primitive) {
 
       _pD3DDevice->DrawIndexedPrimitive
         (D3DPT_TRIANGLESTRIP,
-         primitive->get_min_vertex(),
-         primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
+         min_vertex, max_vertex - min_vertex + 1,
          0, primitive->get_num_vertices() - 2);
       
     } else {
       _pD3DDevice->DrawIndexedPrimitiveUP
         (D3DPT_TRIANGLESTRIP, 
-         primitive->get_min_vertex(),
-         primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
+         min_vertex, max_vertex - min_vertex + 1,
          primitive->get_num_vertices() - 2, 
-         vertices, D3DFMT_INDEX16,
+         primitive->get_vertices(), D3DFMT_INDEX16,
          _vertex_data->get_array(0)->get_data(),
          _vertex_data->get_format()->get_array(0)->get_stride());
     }
@@ -2821,6 +2820,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
     } else {
       CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
       int stride = _vertex_data->get_format()->get_array(0)->get_stride();
+      CPTA_ushort vertices = primitive->get_vertices();
       
       unsigned int start = 0;
       for (size_t i = 0; i < ends.size(); i++) {
@@ -2838,6 +2838,59 @@ draw_tristrips(const qpGeomTristrips *primitive) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DXGraphicsStateGuardian8::draw_trifans
+//       Access: Public, Virtual
+//  Description: Draws a series of triangle fans.
+////////////////////////////////////////////////////////////////////
+void DXGraphicsStateGuardian8::
+draw_trifans(const qpGeomTrifans *primitive) {
+  int min_vertex = primitive->get_min_vertex();
+  int max_vertex = primitive->get_max_vertex();
+
+  // Send the individual triangle fans.  There's no connecting fans
+  // with degenerate vertices, so no worries about that.
+  CPTA_int ends = primitive->get_ends();
+  CPTA_ushort mins = primitive->get_mins();
+  CPTA_ushort maxs = primitive->get_maxs();
+  nassertv(mins.size() == ends.size() && maxs.size() == ends.size());
+  
+  if (_vbuffer_active) {
+    IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
+    nassertv(ibc != (IndexBufferContext *)NULL);
+    apply_index_buffer(ibc);
+    
+    unsigned int start = 0;
+    for (size_t i = 0; i < ends.size(); i++) {
+      _vertices_trifan_pcollector.add_level(ends[i] - start);
+      _pD3DDevice->DrawIndexedPrimitive
+        (D3DPT_TRIANGLEFAN,
+         mins[i], maxs[i] - mins[i] + 1, 
+         start, ends[i] - start - 2);
+      
+      start = ends[i] + 2;
+    }
+    
+  } else {
+    CPTA_uchar array_data = _vertex_data->get_array(0)->get_data();
+    int stride = _vertex_data->get_format()->get_array(0)->get_stride();
+    CPTA_ushort vertices = primitive->get_vertices();
+    
+    unsigned int start = 0;
+    for (size_t i = 0; i < ends.size(); i++) {
+      _vertices_trifan_pcollector.add_level(ends[i] - start);
+      _pD3DDevice->DrawIndexedPrimitiveUP
+        (D3DPT_TRIANGLEFAN, 
+         mins[i], maxs[i] - mins[i] + 1, 
+         ends[i] - start - 2,
+         vertices + start, D3DFMT_INDEX16,
+         array_data, stride);
+      
+      start = ends[i] + 2;
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXGraphicsStateGuardian8::draw_lines
 //       Access: Public, Virtual
@@ -2863,7 +2916,7 @@ draw_lines(const qpGeomLines *primitive) {
        primitive->get_min_vertex(),
        primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
        primitive->get_num_primitives(), 
-       primitive->get_flat_first_vertices(),
+       primitive->get_vertices(),
        D3DFMT_INDEX16,
        _vertex_data->get_array(0)->get_data(),
        _vertex_data->get_format()->get_array(0)->get_stride());

+ 1 - 0
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -95,6 +95,7 @@ public:
                                      const qpGeomVertexData *vertex_data);
   virtual void draw_triangles(const qpGeomTriangles *primitive);
   virtual void draw_tristrips(const qpGeomTristrips *primitive);
+  virtual void draw_trifans(const qpGeomTrifans *primitive);
   virtual void draw_lines(const qpGeomLines *primitive);
   virtual void end_draw_primitives();
 

+ 1 - 1
panda/src/dxgsg8/dxIndexBufferContext8.cxx

@@ -104,7 +104,7 @@ upload_data() {
     return;
   }
 
-  memcpy(local_pointer, get_data()->get_flat_first_vertices(), data_size);
+  memcpy(local_pointer, get_data()->get_vertices(), data_size);
 
   _ibuffer->Unlock();
 }

+ 8 - 5
panda/src/dxgsg8/wdxGraphicsWindow8.cxx

@@ -683,9 +683,12 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
 
   pPresParams->BackBufferFormat = Display.DisplayMode.Format;  // dont need dest alpha, so just use adapter format
 
-  if (dx_sync_video && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
-    wdxdisplay8_cat.info() << "HW doesnt support syncing to vertical refresh, ignoring dx_sync_video\n";
-    dx_sync_video=false;
+  bool do_sync = sync_video;
+
+  if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
+    wdxdisplay8_cat.info() 
+      << "HW doesnt support syncing to vertical refresh, ignoring sync-video\n";
+    do_sync = false;
   }
 
   // verify the rendertarget fmt one last time
@@ -779,7 +782,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
 
   if (is_fullscreen()) {
     pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD;  // we dont care about preserving contents of old frame
-    pPresParams->FullScreen_PresentationInterval = (dx_sync_video ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
+    pPresParams->FullScreen_PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
     pPresParams->FullScreen_RefreshRateInHz = Display.DisplayMode.RefreshRate;
 
 #ifdef _DEBUG
@@ -831,7 +834,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
     pPresParams->FullScreen_PresentationInterval = 0;
 
     if (dx_multisample_antialiasing_level<2) {
-      if (dx_sync_video) {
+      if (do_sync) {
         pPresParams->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
       } else {
         pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD;  //D3DSWAPEFFECT_COPY;  does this make any difference?

+ 0 - 6
panda/src/dxgsg9/config_dxgsg9.cxx

@@ -37,12 +37,6 @@ NotifyCategoryDef(wdxdisplay9, "windisplay");
 ConfigVariableBool dx_show_transforms
 ("dx-show-transforms", false);
 
-//  Configure this true to force the rendering to sync to the video
-//  refresh, or false to let your frame rate go as high as it can,
-//  irrespective of the video refresh.
-ConfigVariableBool dx_sync_video
-("sync-video", true);
-
 // Set Level of MultiSampling to be used, if HW supports it.  Valid values are 2-16.
 ConfigVariableInt dx_multisample_antialiasing_level
 ("dx-multisample-antialiasing-level", 0);

+ 0 - 1
panda/src/dxgsg9/config_dxgsg9.h

@@ -29,7 +29,6 @@
 NotifyCategoryDecl(dxgsg9, EXPCL_PANDADX, EXPTP_PANDADX);
 NotifyCategoryDecl(wdxdisplay9, EXPCL_PANDADX, EXPTP_PANDADX);
 
-extern ConfigVariableBool dx_sync_video;
 extern ConfigVariableBool dx_no_vertex_fog;
 extern ConfigVariableBool dx_show_cursor_watermark;
 extern ConfigVariableBool dx_full_screen_antialiasing;

+ 8 - 5
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -670,9 +670,12 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
 
   pPresParams->BackBufferFormat = Display.DisplayMode.Format;  // dont need dest alpha, so just use adapter format
 
-  if (dx_sync_video && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
-    wdxdisplay9_cat.info() << "HW doesnt support syncing to vertical refresh, ignoring dx_sync_video\n";
-    dx_sync_video=false;
+  bool do_sync = sync_video;
+
+  if (do_sync && !(pD3DCaps->Caps & D3DCAPS_READ_SCANLINE)) {
+    wdxdisplay9_cat.info()
+      << "HW doesnt support syncing to vertical refresh, ignoring sync-video\n";
+    do_sync = false;
   }
 
   // verify the rendertarget fmt one last time
@@ -766,7 +769,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
 
   if (is_fullscreen()) {
     pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD;  // we dont care about preserving contents of old frame
-    pPresParams->PresentationInterval = (dx_sync_video ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
+    pPresParams->PresentationInterval = (do_sync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE);
     pPresParams->FullScreen_RefreshRateInHz = Display.DisplayMode.RefreshRate;
 
 #ifdef _DEBUG
@@ -818,7 +821,7 @@ create_screen_buffers_and_device(DXScreenData &Display, bool force_16bpp_zbuffer
     pPresParams->PresentationInterval = 0;
 
     if (dx_multisample_antialiasing_level<2) {
-      if (dx_sync_video) {
+      if (do_sync) {
         pPresParams->SwapEffect = D3DSWAPEFFECT_COPY;
       } else {
         pPresParams->SwapEffect = D3DSWAPEFFECT_DISCARD;  //D3DSWAPEFFECT_COPY;  does this make any difference?

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 125 - 110
panda/src/glstuff/glGraphicsStateGuardian_src.cxx


+ 16 - 7
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -100,6 +100,7 @@ public:
   virtual void draw_triangles(const qpGeomTriangles *primitive);
   virtual void draw_tristrips(const qpGeomTristrips *primitive);
   virtual void draw_lines(const qpGeomLines *primitive);
+  virtual void draw_linestrips(const qpGeomLinestrips *primitive);
   virtual void draw_points(const qpGeomPoints *primitive);
   virtual void end_draw_primitives();
 
@@ -390,16 +391,24 @@ public:
   typedef pvector<GLuint> DeletedDisplayLists;
   DeletedDisplayLists _deleted_display_lists;
 
-public:
-  static GraphicsStateGuardian *
-  make_GlGraphicsStateGuardian(const FactoryParams &params);
+  static PStatCollector _vertices_display_list_pcollector;
 
-  static TypeHandle get_class_type(void);
-  static void init_type(void);
-  virtual TypeHandle get_type(void) const;
+public:
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
 
-  static PStatCollector _vertices_display_list_pcollector;
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+
+public:
+  static void init_type() {
+    GraphicsStateGuardian::init_type();
+    register_type(_type_handle, CLASSPREFIX_QUOTED "GraphicsStateGuardian",
+                  GraphicsStateGuardian::get_class_type());
+  }
 
 private:
   static TypeHandle _type_handle;

+ 58 - 15
panda/src/gobj/qpgeom.I

@@ -31,6 +31,32 @@ get_primitive_type() const {
   return cdata->_primitive_type;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeom::get_shade_model
+//       Access: Published
+//  Description: Returns the shade model common to all of the
+//               individual GeomPrimitives that have been added to the
+//               geom.
+////////////////////////////////////////////////////////////////////
+INLINE qpGeom::ShadeModel qpGeom::
+get_shade_model() const {
+  CDReader cdata(_cycler);
+  return cdata->_shade_model;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeom::get_geom_rendering
+//       Access: Published
+//  Description: Returns the set of GeomRendering bits that represent
+//               the rendering properties required to properly render
+//               this Geom.
+////////////////////////////////////////////////////////////////////
+INLINE int qpGeom::
+get_geom_rendering() const {
+  CDReader cdata(_cycler);
+  return cdata->_geom_rendering;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeom::get_usage_hint
 //       Access: Published
@@ -48,19 +74,6 @@ get_usage_hint() const {
   return cdata->_usage_hint;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeom::get_point_rendering
-//       Access: Published
-//  Description: Returns the set of PointRendering bits that represent
-//               the rendering properties required to properly render
-//               the points (if any) represented within this Geom.
-////////////////////////////////////////////////////////////////////
-INLINE int qpGeom::
-get_point_rendering() const {
-  CDReader cdata(_cycler);
-  return cdata->_point_rendering;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeom::get_vertex_data
 //       Access: Published
@@ -123,6 +136,34 @@ modify_primitive(int i) {
   return cdata->_primitives[i];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeom::decompose
+//       Access: Published
+//  Description: Decomposes all of the primitives within this Geom,
+//               returning the result.  See
+//               GeomPrimitive::decompose().
+////////////////////////////////////////////////////////////////////
+INLINE CPT(qpGeom) qpGeom::
+decompose() const {
+  PT(qpGeom) new_geom = new qpGeom(*this);
+  new_geom->decompose_in_place();
+  return new_geom;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeom::rotate
+//       Access: Published
+//  Description: Rotates all of the primitives within this Geom,
+//               returning the result.  See
+//               GeomPrimitive::rotate().
+////////////////////////////////////////////////////////////////////
+INLINE CPT(qpGeom) qpGeom::
+rotate() const {
+  PT(qpGeom) new_geom = new qpGeom(*this);
+  new_geom->rotate_in_place();
+  return new_geom;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeom::get_modified
 //       Access: Published
@@ -179,7 +220,8 @@ operator < (const CacheEntry &other) const {
 INLINE qpGeom::CData::
 CData() :
   _primitive_type(PT_none),
-  _point_rendering(0),
+  _shade_model(SM_uniform),
+  _geom_rendering(0),
   _usage_hint(UH_unspecified),
   _got_usage_hint(false)
 {
@@ -195,7 +237,8 @@ CData(const qpGeom::CData &copy) :
   _data(copy._data),
   _primitives(copy._primitives),
   _primitive_type(copy._primitive_type),
-  _point_rendering(copy._point_rendering),
+  _shade_model(copy._shade_model),
+  _geom_rendering(copy._geom_rendering),
   _usage_hint(copy._usage_hint),
   _got_usage_hint(copy._got_usage_hint),
   _modified(copy._modified)

+ 130 - 40
panda/src/gobj/qpgeom.cxx

@@ -162,7 +162,7 @@ set_vertex_data(const qpGeomVertexData *data) {
   CDWriter cdata(_cycler);
   cdata->_data = (qpGeomVertexData *)data;
   mark_bound_stale();
-  reset_point_rendering(cdata);
+  reset_geom_rendering(cdata);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -199,10 +199,9 @@ offset_vertices(const qpGeomVertexData *data, int offset) {
 #endif
   }
 
-  cdata->_got_usage_hint = false;
   cdata->_modified = qpGeom::get_next_modified();
   mark_bound_stale();
-  reset_point_rendering(cdata);
+  reset_geom_rendering(cdata);
 
   nassertv(all_is_valid);
 }
@@ -225,25 +224,25 @@ set_primitive(int i, const qpGeomPrimitive *primitive) {
   nassertv(cdata->_primitive_type == PT_none ||
            cdata->_primitive_type == primitive->get_primitive_type());
 
-  if (cdata->_got_usage_hint &&
-      cdata->_primitives[i]->get_usage_hint() != primitive->get_usage_hint()) {
-    if (cdata->_primitives[i]->get_usage_hint() < primitive->get_usage_hint()) {
-      // If we're reducing the usage hint, we might also be reducing
-      // the minimum usage hit.
-      cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint());
-    } else { // (cdata->_primitives[i]->get_usage_hint() > primitive->get_usage_hint())
-      // If we're increasing it, we might have to rederive the minimum.
-      if (cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) {
-        cdata->_got_usage_hint = false;
-      }
-    }
-  }
+  // They also should have the same fundamental shade model, but
+  // SM_uniform is compatible with anything.
+  nassertv(cdata->_shade_model == SM_uniform ||
+           primitive->get_shade_model() == SM_uniform ||
+           cdata->_shade_model == primitive->get_shade_model());
+
   cdata->_primitives[i] = (qpGeomPrimitive *)primitive;
   PrimitiveType new_primitive_type = primitive->get_primitive_type();
   if (new_primitive_type != cdata->_primitive_type) {
     cdata->_primitive_type = new_primitive_type;
-    reset_point_rendering(cdata);
   }
+  ShadeModel new_shade_model = primitive->get_shade_model();
+  if (new_shade_model != cdata->_shade_model &&
+      new_shade_model != SM_uniform) {
+    cdata->_shade_model = new_shade_model;
+  }
+
+  reset_geom_rendering(cdata);
+  cdata->_got_usage_hint = false;
   cdata->_modified = qpGeom::get_next_modified();
 }
 
@@ -267,16 +266,25 @@ add_primitive(const qpGeomPrimitive *primitive) {
   nassertv(cdata->_primitive_type == PT_none ||
            cdata->_primitive_type == primitive->get_primitive_type());
 
+  // They also should have the same fundamental shade model, but
+  // SM_uniform is compatible with anything.
+  nassertv(cdata->_shade_model == SM_uniform ||
+           primitive->get_shade_model() == SM_uniform ||
+           cdata->_shade_model == primitive->get_shade_model());
+
   cdata->_primitives.push_back((qpGeomPrimitive *)primitive);
   PrimitiveType new_primitive_type = primitive->get_primitive_type();
   if (new_primitive_type != cdata->_primitive_type) {
     cdata->_primitive_type = new_primitive_type;
-    reset_point_rendering(cdata);
   }
-
-  if (cdata->_got_usage_hint) {
-    cdata->_usage_hint = min(cdata->_usage_hint, primitive->get_usage_hint());
+  ShadeModel new_shade_model = primitive->get_shade_model();
+  if (new_shade_model != cdata->_shade_model &&
+      new_shade_model != SM_uniform) {
+    cdata->_shade_model = new_shade_model;
   }
+
+  reset_geom_rendering(cdata);
+  cdata->_got_usage_hint = false;
   cdata->_modified = qpGeom::get_next_modified();
 }
 
@@ -290,17 +298,13 @@ remove_primitive(int i) {
   clear_cache();
   CDWriter cdata(_cycler);
   nassertv(i >= 0 && i < (int)cdata->_primitives.size());
-  if (cdata->_got_usage_hint &&
-      cdata->_usage_hint == cdata->_primitives[i]->get_usage_hint()) {
-    // Maybe we're raising the minimum usage_hint; we have to rederive
-    // the usage_hint later.
-    cdata->_got_usage_hint = false;
-  }
   cdata->_primitives.erase(cdata->_primitives.begin() + i);
   if (cdata->_primitives.empty()) {
     cdata->_primitive_type = PT_none;
-    reset_point_rendering(cdata);
+    cdata->_shade_model = SM_uniform;
   }
+  reset_geom_rendering(cdata);
+  cdata->_got_usage_hint = false;
   cdata->_modified = qpGeom::get_next_modified();
 }
 
@@ -318,7 +322,73 @@ clear_primitives() {
   CDWriter cdata(_cycler);
   cdata->_primitives.clear();
   cdata->_primitive_type = PT_none;
-  reset_point_rendering(cdata);
+  cdata->_shade_model = SM_uniform;
+  reset_geom_rendering(cdata);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeom::decompose_in_place
+//       Access: Published
+//  Description: Decomposes all of the primitives within this Geom,
+//               leaving the results in place.  See
+//               GeomPrimitive::decompose().
+////////////////////////////////////////////////////////////////////
+void qpGeom::
+decompose_in_place() {
+  clear_cache();
+  CDWriter cdata(_cycler);
+
+#ifndef NDEBUG
+  bool all_is_valid = true;
+#endif
+  Primitives::iterator pi;
+  for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
+    CPT(qpGeomPrimitive) new_prim = (*pi)->decompose();
+    (*pi) = (qpGeomPrimitive *)new_prim.p();
+
+#ifndef NDEBUG
+    if (!(*pi)->check_valid(cdata->_data)) {
+      all_is_valid = false;
+    }
+#endif
+  }
+
+  cdata->_modified = qpGeom::get_next_modified();
+  reset_geom_rendering(cdata);
+
+  nassertv(all_is_valid);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeom::rotate_in_place
+//       Access: Published
+//  Description: Rotates all of the primitives within this Geom,
+//               leaving the results in place.  See
+//               GeomPrimitive::rotate().
+////////////////////////////////////////////////////////////////////
+void qpGeom::
+rotate_in_place() {
+  clear_cache();
+  CDWriter cdata(_cycler);
+
+#ifndef NDEBUG
+  bool all_is_valid = true;
+#endif
+  Primitives::iterator pi;
+  for (pi = cdata->_primitives.begin(); pi != cdata->_primitives.end(); ++pi) {
+    CPT(qpGeomPrimitive) new_prim = (*pi)->rotate();
+    (*pi) = (qpGeomPrimitive *)new_prim.p();
+
+#ifndef NDEBUG
+    if (!(*pi)->check_valid(cdata->_data)) {
+      all_is_valid = false;
+    }
+#endif
+  }
+
+  cdata->_modified = qpGeom::get_next_modified();
+
+  nassertv(all_is_valid);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -712,26 +782,44 @@ reset_usage_hint(qpGeom::CDWriter &cdata) {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: qpGeom::reset_point_rendering
+//     Function: qpGeom::reset_geom_rendering
 //       Access: Private
-//  Description: Rederives the _point_rendering member.
+//  Description: Rederives the _geom_rendering member.
 ////////////////////////////////////////////////////////////////////
 void qpGeom::
-reset_point_rendering(qpGeom::CDWriter &cdata) {
-  cdata->_point_rendering = 0;
-  if (cdata->_primitive_type == PT_points) {
-    cdata->_point_rendering |= PR_point;
+reset_geom_rendering(qpGeom::CDWriter &cdata) {
+  cdata->_geom_rendering = 0;
+  Primitives::const_iterator pi;
+  for (pi = cdata->_primitives.begin(); 
+       pi != cdata->_primitives.end();
+       ++pi) {
+    cdata->_geom_rendering |= (*pi)->get_geom_rendering();
+  }
 
+  if ((cdata->_geom_rendering & GR_point) != 0) {
     if (cdata->_data->has_column(InternalName::get_size())) {
-      cdata->_point_rendering |= PR_per_point_size;
+      cdata->_geom_rendering |= GR_per_point_size;
     }
     if (cdata->_data->has_column(InternalName::get_aspect_ratio())) {
-      cdata->_point_rendering |= PR_aspect_ratio;
+      cdata->_geom_rendering |= GR_point_aspect_ratio;
     }
     if (cdata->_data->has_column(InternalName::get_rotate())) {
-      cdata->_point_rendering |= PR_rotate;
+      cdata->_geom_rendering |= GR_point_rotate;
     }
   }
+
+  switch (get_shade_model()) {
+  case SM_flat_first_vertex:
+    cdata->_geom_rendering |= GR_flat_first_vertex;
+    break;
+
+  case SM_flat_last_vertex:
+    cdata->_geom_rendering |= GR_flat_last_vertex;
+    break;
+
+  default:
+    break;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -862,7 +950,8 @@ write_datagram(BamWriter *manager, Datagram &dg) const {
   }
 
   dg.add_uint8(_primitive_type);
-  dg.add_uint16(_point_rendering);
+  dg.add_uint8(_shade_model);
+  dg.add_uint16(_geom_rendering);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -905,7 +994,8 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   }
 
   _primitive_type = (PrimitiveType)scan.get_uint8();
-  _point_rendering = scan.get_uint16();
+  _shade_model = (ShadeModel)scan.get_uint16();
+  _geom_rendering = scan.get_uint16();
   _got_usage_hint = false;
   _modified = qpGeom::get_next_modified();
 }

+ 12 - 4
panda/src/gobj/qpgeom.h

@@ -68,11 +68,12 @@ PUBLISHED:
   virtual Geom *make_copy() const;
 
   INLINE PrimitiveType get_primitive_type() const;
+  INLINE ShadeModel get_shade_model() const;
+  INLINE int get_geom_rendering() const;
+
   INLINE UsageHint get_usage_hint() const;
   void set_usage_hint(UsageHint usage_hint);
 
-  INLINE int get_point_rendering() const;
-
   INLINE CPT(qpGeomVertexData) get_vertex_data() const;
   PT(qpGeomVertexData) modify_vertex_data();
   void set_vertex_data(const qpGeomVertexData *data);
@@ -86,6 +87,12 @@ PUBLISHED:
   void remove_primitive(int i);
   void clear_primitives();
 
+  INLINE CPT(qpGeom) decompose() const;
+  INLINE CPT(qpGeom) rotate() const;
+
+  void decompose_in_place();
+  void rotate_in_place();
+
   int get_num_bytes() const;
   INLINE UpdateSeq get_modified() const;
 
@@ -160,7 +167,8 @@ private:
     PT(qpGeomVertexData) _data;
     Primitives _primitives;
     PrimitiveType _primitive_type;
-    int _point_rendering;
+    ShadeModel _shade_model;
+    int _geom_rendering;
     UsageHint _usage_hint;
     bool _got_usage_hint;
     UpdateSeq _modified;
@@ -172,7 +180,7 @@ private:
   typedef CycleDataWriter<CData> CDWriter;
 
   void reset_usage_hint(CDWriter &cdata);
-  void reset_point_rendering(CDWriter &cdata);
+  void reset_geom_rendering(CDWriter &cdata);
 
   static UpdateSeq _next_modified;
 

+ 39 - 19
panda/src/gobj/qpgeomEnums.h

@@ -82,48 +82,68 @@ PUBLISHED:
     UH_unspecified,
   };
 
-  // This type specifies a number of bits that are used to
-  // representing the rendering capabilities and/or requirements for
-  // fancy points.
-  enum PointRendering {
+  // This type specifies a number of bits that are used to represent
+  // the rendering requirements of a particular Geom, as well as the
+  // rendering capabilities of the GSG.  The difference between the
+  // two indicates whether the Geom needs to be munged for the GSG.
+  enum GeomRendering {
     // If there are any points at all.
-    PR_point          = 0x0001,
+    GR_point                = 0x0001,
 
     // If the points are all the same size, other than 1 pixel.
-    PR_uniform_size   = 0x0002,
+    GR_point_uniform_size   = 0x0002,
 
     // If the points have a per-vertex size designation.
-    PR_per_point_size = 0x0004,
+    GR_per_point_size       = 0x0004,
 
     // If the points' size is specified in camera units rather than
     // screen pixels.
-    PR_perspective    = 0x0008,
+    GR_point_perspective    = 0x0008,
 
     // If the points have a non-square aspect ratio.
-    PR_aspect_ratio   = 0x0010,
+    GR_point_aspect_ratio   = 0x0010,
 
     // If the points are rotated off the orthonormal axis.
-    PR_rotate         = 0x0020,
+    GR_point_rotate         = 0x0020,
 
     // If the points require texture coordinates interpolated across
     // their face, to render textures as sprites.
-    PR_sprite         = 0x0040,
+    GR_point_sprite         = 0x0040,
+
+    // The union of all the above point attributes.
+    GR_point_bits           = 0x007f,
+
+    // If there are any of these composite types.
+    GR_triangle_strip       = 0x0080,
+    GR_triangle_fan         = 0x0100,
+    GR_line_strip           = 0x0200,
+
+    // The union of all of the above composite types.
+    GR_composite_bits       = 0x0380,
+
+    // If the shade model requires a particular vertex for flat shading.
+    GR_flat_first_vertex    = 0x0400,
+    GR_flat_last_vertex     = 0x0800,
+
+    // The union of the above shade model types.
+    GR_shade_model_bits     = 0x0c00,
   };
 
-  // The shade model controls whether colors and/or lighting effects
-  // are smoothly interpolated across the face of a triangle, or
-  // uniform for the entire triangle.
+  // The shade model specifies whether the per-vertex colors and
+  // normals indexed by a given primitive truly represent per-vertex
+  // colors and normals, or whether they actually represent
+  // per-triangle flat-shaded colors and normals.
   enum ShadeModel {
-    // SM_smooth: vertices within a single face have different
-    // colors/normals that should be smoothed across the face.  This
-    // primitive should be rendered with SmoothModelAttrib::M_smooth.
-    SM_smooth,  
-
     // SM_uniform: all vertices across all faces have the same colors
     // and normals.  It doesn't really matter which ShadeModelAttrib
     // mode is used to render this primitive.
     SM_uniform, 
 
+    // SM_smooth: vertices within a single face have different
+    // colors/normals that should be smoothed across the face.  This
+    // primitive should be rendered with SmoothModelAttrib::M_smooth.
+    SM_smooth,  
+
     // SM_flat_(first,last)_vertex: each face within the primitive
     // might have a different color/normal than the other faces, but
     // across a particular face there is only one color/normal.  Each

+ 1 - 1
panda/src/gobj/qpgeomLines.cxx

@@ -134,7 +134,7 @@ rotate_impl() const {
     new_vertices.push_back(vertices[begin]);
   }
   
-  nassertr(new_vertices.size() == vertices.size(), vertices);
+  nassertr(new_vertices.size() == vertices.size(), CPTA_ushort());
   return new_vertices;
 }
 

+ 13 - 1
panda/src/gobj/qpgeomLinestrips.cxx

@@ -79,6 +79,18 @@ get_primitive_type() const {
   return PT_lines;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomLinestrips::get_geom_rendering
+//       Access: Published, Virtual
+//  Description: Returns the set of GeomRendering bits that represent
+//               the rendering properties required to properly render
+//               this primitive.
+////////////////////////////////////////////////////////////////////
+int qpGeomLinestrips::
+get_geom_rendering() const {
+  return GR_line_strip;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomLinestrips::get_min_num_vertices_per_primitive
 //       Access: Public, Virtual
@@ -167,7 +179,7 @@ rotate_impl() const {
     }
     begin = end;
   }
-  nassertr(new_vertices.size() == vertices.size(), vertices);
+  nassertr(new_vertices.size() == vertices.size(), CPTA_ushort());
 
   return new_vertices;
 }

+ 1 - 1
panda/src/gobj/qpgeomLinestrips.h

@@ -37,7 +37,7 @@ PUBLISHED:
 public:
   virtual PT(qpGeomPrimitive) make_copy() const;
   virtual PrimitiveType get_primitive_type() const;
-
+  virtual int get_geom_rendering() const;
   virtual int get_min_num_vertices_per_primitive() const;
 
 public:

+ 15 - 0
panda/src/gobj/qpgeomPoints.cxx

@@ -78,6 +78,21 @@ get_primitive_type() const {
   return PT_points;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomPoints::get_geom_rendering
+//       Access: Published, Virtual
+//  Description: Returns the set of GeomRendering bits that represent
+//               the rendering properties required to properly render
+//               this primitive.
+////////////////////////////////////////////////////////////////////
+int qpGeomPoints::
+get_geom_rendering() const {
+  // Fancy point attributes, if any, are based on whether the
+  // appropriate columns are defined in the associated GeomVertexData;
+  // these bits will be added by Geom::get_geom_rendering().
+  return GR_point;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPoints::get_num_vertices_per_primitive
 //       Access: Public, Virtual

+ 1 - 0
panda/src/gobj/qpgeomPoints.h

@@ -37,6 +37,7 @@ PUBLISHED:
 public:
   virtual PT(qpGeomPrimitive) make_copy() const;
   virtual PrimitiveType get_primitive_type() const;
+  virtual int get_geom_rendering() const;
 
   virtual int get_num_vertices_per_primitive() const;
   virtual int get_min_num_vertices_per_primitive() const;

+ 30 - 91
panda/src/gobj/qpgeomPrimitive.I

@@ -17,6 +17,36 @@
 ////////////////////////////////////////////////////////////////////
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomPrimitive::get_shade_model
+//       Access: Published
+//  Description: Returns the ShadeModel hint for this primitive.
+//               This is intended as a hint to the renderer to tell it
+//               how the per-vertex colors and normals are applied.
+////////////////////////////////////////////////////////////////////
+INLINE qpGeomPrimitive::ShadeModel qpGeomPrimitive::
+get_shade_model() const {
+  CDReader cdata(_cycler);
+  return cdata->_shade_model;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomPrimitive::set_shade_model
+//       Access: Published
+//  Description: Changes the ShadeModel hint for this primitive.
+//               This is different from the ShadeModelAttrib that
+//               might also be applied from the scene graph.  This
+//               does not affect the shade model that is in effect
+//               when rendering, but rather serves as a hint to the
+//               renderer to tell it how the per-vertex colors and
+//               normals on this primitive are applied.
+////////////////////////////////////////////////////////////////////
+INLINE void qpGeomPrimitive::
+set_shade_model(qpGeomPrimitive::ShadeModel shade_model) {
+  CDWriter cdata(_cycler);
+  cdata->_shade_model = shade_model;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::get_usage_hint
 //       Access: Published
@@ -47,42 +77,10 @@ get_usage_hint() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void qpGeomPrimitive::
 set_usage_hint(qpGeomPrimitive::UsageHint usage_hint) {
-  clear_cache();
   CDWriter cdata(_cycler);
   cdata->_usage_hint = usage_hint;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::get_shade_model
-//       Access: Published
-//  Description: Returns the ShadeModel hint for this primitive.
-//               This is intended as a hint to the renderer to tell it
-//               how the per-vertex colors and normals are applied.
-////////////////////////////////////////////////////////////////////
-INLINE qpGeomPrimitive::ShadeModel qpGeomPrimitive::
-get_shade_model() const {
-  CDReader cdata(_cycler);
-  return cdata->_shade_model;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::set_shade_model
-//       Access: Published
-//  Description: Changes the ShadeModel hint for this primitive.
-//               This is different from the ShadeModelAttrib that
-//               might also be applied from the scene graph.  This
-//               does not affect the shade model that is in effect
-//               when rendering, but rather serves as a hint to the
-//               renderer to tell it how the per-vertex colors and
-//               normals on this primitive are applied.
-////////////////////////////////////////////////////////////////////
-INLINE void qpGeomPrimitive::
-set_shade_model(qpGeomPrimitive::ShadeModel shade_model) {
-  CDWriter cdata(_cycler);
-  cdata->_shade_model = shade_model;
-  cdata->_rotated_vertices.clear();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::get_num_vertices
 //       Access: Published
@@ -246,64 +244,6 @@ get_vertices() const {
   return cdata->_vertices;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::get_flat_first_vertices
-//       Access: Public
-//  Description: Returns a const pointer to the vertex index array,
-//               suitable for traversing for a renderer that expects
-//               the key vertex of each triangle in a flat-shaded
-//               model to be the triangle's first vertex (as DirectX
-//               does).
-//
-//               The result of this is dependent on the value
-//               specified to set_shade_model().  If the shade model
-//               indicates flat_last_vertex, this will return the
-//               vertices rotated to bring them into first_vertex
-//               compliance; otherwise, it will be the unmodified
-//               result from get_vertices().
-////////////////////////////////////////////////////////////////////
-INLINE CPTA_ushort qpGeomPrimitive::
-get_flat_first_vertices() const {
-  CDReader cdata(_cycler);
-  if (cdata->_shade_model == SM_flat_last_vertex) {
-    if (cdata->_rotated_vertices == (const ushort *)NULL) {
-      return ((qpGeomPrimitive *)this)->do_rotate(cdata);
-    }
-    return cdata->_rotated_vertices;
-  } else {
-    return cdata->_vertices;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::get_flat_last_vertices
-//       Access: Public
-//  Description: Returns a const pointer to the vertex index array,
-//               suitable for traversing for a renderer that expects
-//               the key vertex of each triangle in a flat-shaded
-//               model to be the triangle's last vertex (as OpenGL
-//               does).
-//
-//               The result of this is dependent on the value
-//               specified to set_shade_model().  If the shade model
-//               indicates flat_first_vertex, this will return the
-//               vertices rotated to bring them into last_vertex
-//               compliance; otherwise, it will be the unmodified
-//               result from get_vertices().
-////////////////////////////////////////////////////////////////////
-INLINE CPTA_ushort qpGeomPrimitive::
-get_flat_last_vertices() const {
-  CDReader cdata(_cycler);
-  if (cdata->_shade_model == SM_flat_first_vertex) {
-    if (cdata->_rotated_vertices == (const ushort *)NULL) {
-      return ((qpGeomPrimitive *)this)->do_rotate(cdata);
-    }
-    return cdata->_rotated_vertices;
-  } else {
-    return cdata->_vertices;
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::get_ends
 //       Access: Public
@@ -391,7 +331,6 @@ CData(const qpGeomPrimitive::CData &copy) :
   _usage_hint(copy._usage_hint),
   _shade_model(copy._shade_model),
   _vertices(copy._vertices),
-  _rotated_vertices(copy._rotated_vertices),
   _ends(copy._ends),
   _mins(copy._mins),
   _maxs(copy._maxs),

+ 47 - 160
panda/src/gobj/qpgeomPrimitive.cxx

@@ -30,7 +30,8 @@
 
 TypeHandle qpGeomPrimitive::_type_handle;
 
-PStatCollector qpGeomPrimitive::_rotate_pcollector("Draw:Rotate");
+PStatCollector qpGeomPrimitive::_decompose_pcollector("Cull:Munge:Decompose");
+PStatCollector qpGeomPrimitive::_rotate_pcollector("Cull:Munge:Rotate");
 
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::Constructor
@@ -61,24 +62,22 @@ qpGeomPrimitive(const qpGeomPrimitive &copy) :
 ////////////////////////////////////////////////////////////////////
 qpGeomPrimitive::
 ~qpGeomPrimitive() {
-  // When we destruct, we should ensure that all of our cached
-  // entries, across all pipeline stages, are properly removed from
-  // the cache manager.
-  int num_stages = _cycler.get_num_stages();
-  for (int i = 0; i < num_stages; i++) {
-    if (_cycler.is_stage_unique(i)) {
-      CData *cdata = _cycler.write_stage(i);
-      if (cdata->_cache != (CacheEntry *)NULL) {
-        cdata->_cache->erase();
-        cdata->_cache = NULL;
-      }
-      _cycler.release_write_stage(i, cdata);
-    }
-  }
-
   release_all();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomPrimitive::get_geom_rendering
+//       Access: Published, Virtual
+//  Description: Returns the set of GeomRendering bits that represent
+//               the rendering properties required to properly render
+//               this primitive.
+////////////////////////////////////////////////////////////////////
+int qpGeomPrimitive::
+get_geom_rendering() const {
+  // The default is nothing fancy.
+  return 0;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::add_vertex
 //       Access: Published
@@ -94,7 +93,6 @@ add_vertex(int vertex) {
   unsigned short short_vertex = vertex;
   nassertv((int)short_vertex == vertex);
 
-  clear_cache();
   CDWriter cdata(_cycler);
 
   int num_primitives = get_num_primitives();
@@ -106,7 +104,6 @@ add_vertex(int vertex) {
   }
 
   cdata->_vertices.push_back(short_vertex);
-  cdata->_rotated_vertices.clear();
 
   if (cdata->_got_minmax) {
     cdata->_min_vertex = min(cdata->_min_vertex, short_vertex);
@@ -139,7 +136,6 @@ add_consecutive_vertices(int start, int num_vertices) {
   if (num_vertices == 0) {
     return;
   }
-  clear_cache();
   int end = (start + num_vertices) - 1;
   unsigned short short_start = start;
   unsigned short short_end = end;
@@ -158,7 +154,6 @@ add_consecutive_vertices(int start, int num_vertices) {
   for (unsigned short v = short_start; v <= short_end; ++v) {
     cdata->_vertices.push_back(v);
   }
-  cdata->_rotated_vertices.clear();
 
   if (cdata->_got_minmax) {
     cdata->_min_vertex = min(cdata->_min_vertex, short_start);
@@ -210,7 +205,6 @@ add_next_vertices(int num_vertices) {
 ////////////////////////////////////////////////////////////////////
 bool qpGeomPrimitive::
 close_primitive() {
-  clear_cache();
   int num_vertices_per_primitive = get_num_vertices_per_primitive();
 
   CDWriter cdata(_cycler);
@@ -262,10 +256,8 @@ close_primitive() {
 ////////////////////////////////////////////////////////////////////
 void qpGeomPrimitive::
 clear_vertices() {
-  clear_cache();
   CDWriter cdata(_cycler);
   cdata->_vertices.clear();
-  cdata->_rotated_vertices.clear();
   cdata->_ends.clear();
   cdata->_mins.clear();
   cdata->_maxs.clear();
@@ -280,10 +272,8 @@ clear_vertices() {
 ////////////////////////////////////////////////////////////////////
 void qpGeomPrimitive::
 offset_vertices(int offset) {
-  clear_cache();
   CDWriter cdata(_cycler);
 
-  cdata->_rotated_vertices.clear();
   cdata->_mins.clear();
   cdata->_maxs.clear();
   cdata->_got_minmax = false;
@@ -427,49 +417,44 @@ get_primitive_num_vertices(int n) const {
 ////////////////////////////////////////////////////////////////////
 CPT(qpGeomPrimitive) qpGeomPrimitive::
 decompose() const {
-  CPT(qpGeomPrimitive) result;
-  {
-    // Use read() and release_read() instead of CDReader, because the
-    // call to record_primitive() might recursively call back into
-    // this object, and require a write.
-    const CData *cdata = _cycler.read();
-    if (cdata->_cache != (CacheEntry *)NULL) {
-      result = cdata->_cache->_decomposed;
-      _cycler.release_read(cdata);
-      // Record a cache hit, so this element will stay in the cache a
-      // while longer.
-      cdata->_cache->refresh();
-
-      return result;
-    }
-    _cycler.release_read(cdata);
+  if (gobj_cat.is_debug()) {
+    gobj_cat.debug()
+      << "Decomposing " << get_type() << ": " << (void *)this << "\n";
   }
 
-  result = decompose_impl();
-  if (result.p() == this || result.p() == NULL) {
-    // decomposing this primitive has no effect or cannot be done.
-    return this;
-  }
+  PStatTimer timer(_decompose_pcollector);
+  return decompose_impl();
+}
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomPrimitive::rotate
+//       Access: Published
+//  Description: Returns a new primitive with the shade_model reversed
+//               (if it is flat shaded).
+//
+//               If the current shade_model indicates
+//               flat_vertex_last, this should bring the last vertex
+//               to the first position; if it indicates
+//               flat_vertex_first, this should bring the first vertex
+//               to the last position.
+////////////////////////////////////////////////////////////////////
+CPT(qpGeomPrimitive) qpGeomPrimitive::
+rotate() const {
   if (gobj_cat.is_debug()) {
     gobj_cat.debug()
-      << "Decomposing " << get_type() << ": " << (void *)this << "\n";
+      << "Rotating " << get_type() << ": " << (void *)this << "\n";
   }
 
-  // Record the result for the future.
-  CacheEntry *entry;
-  {
-    CDWriter cdata(((qpGeomPrimitive *)this)->_cycler);
-    entry = new CacheEntry;
-    entry->_source = (qpGeomPrimitive *)this;
-    entry->_decomposed = result;
-    cdata->_cache = entry;
-  }
+  PStatTimer timer(_rotate_pcollector);
+  CPTA_ushort rotated_vertices = rotate_impl();
 
-  // And add *this* object to the cache manager.
-  entry->record();
+  if (rotated_vertices.is_null()) {
+    return this;
+  }
 
-  return result;
+  PT(qpGeomPrimitive) new_prim = make_copy();
+  new_prim->set_vertices(rotated_vertices);
+  return new_prim;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -554,9 +539,7 @@ write(ostream &out, int indent_level) const {
 ////////////////////////////////////////////////////////////////////
 PTA_ushort qpGeomPrimitive::
 modify_vertices() {
-  clear_cache();
   CDWriter cdata(_cycler);
-  cdata->_rotated_vertices.clear();
   cdata->_got_minmax = false;
   return cdata->_vertices;
 }
@@ -570,10 +553,8 @@ modify_vertices() {
 ////////////////////////////////////////////////////////////////////
 void qpGeomPrimitive::
 set_vertices(CPTA_ushort vertices) {
-  clear_cache();
   CDWriter cdata(_cycler);
   cdata->_vertices = (PTA_ushort &)vertices;
-  cdata->_rotated_vertices.clear();
   cdata->_got_minmax = false;
 }
 
@@ -591,9 +572,7 @@ set_vertices(CPTA_ushort vertices) {
 ////////////////////////////////////////////////////////////////////
 PTA_int qpGeomPrimitive::
 modify_ends() {
-  clear_cache();
   CDWriter cdata(_cycler);
-  cdata->_rotated_vertices.clear();
   cdata->_got_minmax = false;
   return cdata->_ends;
 }
@@ -612,10 +591,8 @@ modify_ends() {
 ////////////////////////////////////////////////////////////////////
 void qpGeomPrimitive::
 set_ends(CPTA_int ends) {
-  clear_cache();
   CDWriter cdata(_cycler);
   cdata->_ends = (PTA_int &)ends;
-  cdata->_rotated_vertices.clear();
   cdata->_got_minmax = false;
 }
 
@@ -660,28 +637,6 @@ get_num_unused_vertices_per_primitive() const {
   return 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::clear_cache
-//       Access: Public
-//  Description: Removes all of the previously-cached results of
-//               decompose().
-////////////////////////////////////////////////////////////////////
-void qpGeomPrimitive::
-clear_cache() {
-  // Probably we shouldn't do anything at all here unless we are
-  // running in pipeline stage 0.
-  CData *cdata = CDWriter(_cycler);
-  if (cdata->_cache != (CacheEntry *)NULL) {
-    cdata->_cache->erase();
-    cdata->_cache = NULL;
-  }
-
-  // This, on the other hand, should be applied to the current
-  // pipeline stage.
-  cdata->_modified = qpGeom::get_next_modified();
-}
-
-
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::prepare
 //       Access: Public
@@ -892,13 +847,13 @@ decompose_impl() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::rotate_impl
 //       Access: Protected, Virtual
-//  Description: The virtual implementation of do_rotate().
+//  Description: The virtual implementation of rotate().
 ////////////////////////////////////////////////////////////////////
 CPTA_ushort qpGeomPrimitive::
 rotate_impl() const {
   // The default implementation doesn't even try to do anything.
-  nassertr(false, get_vertices());
-  return get_vertices();
+  nassertr(false, CPTA_ushort());
+  return CPTA_ushort();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -914,34 +869,6 @@ void qpGeomPrimitive::
 append_unused_vertices(PTA_ushort &, int) {
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::do_rotate
-//       Access: Private
-//  Description: Fills _rotated_vertices by rotating the individual
-//               primitives to bring each flat-colored vertex to the
-//               opposite position.  If the current shade_model
-//               indicates flat_vertex_last, this should bring the
-//               last vertex to the first position; if it indicates
-//               flat_vertex_first, this should bring the first vertex
-//               to the last position.  This is used internally to
-//               implement get_flat_first_vertices() and
-//               get_flat_last_vertices().
-////////////////////////////////////////////////////////////////////
-CPTA_ushort qpGeomPrimitive::
-do_rotate(qpGeomPrimitive::CDReader &cdata) {
-  if (gobj_cat.is_debug()) {
-    gobj_cat.debug()
-      << "Rotating " << get_type() << ": " << (void *)this << "\n";
-  }
-
-  PStatTimer timer(_rotate_pcollector);
-  CPTA_ushort rotated_vertices = rotate_impl();
-
-  CDWriter cdataw(_cycler, cdata);
-  cdataw->_rotated_vertices = rotated_vertices;
-  return rotated_vertices;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::recompute_minmax
 //       Access: Private
@@ -1041,46 +968,6 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   manager->read_cdata(scan, _cycler);
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::CacheEntry::evict_callback
-//       Access: Public, Virtual
-//  Description: Called when the entry is evicted from the cache, this
-//               should clean up the owning object appropriately.
-////////////////////////////////////////////////////////////////////
-void qpGeomPrimitive::CacheEntry::
-evict_callback() {
-  // We have to operate on stage 0 of the pipeline, since that's where
-  // the cache really counts.  Because of the multistage pipeline, we
-  // might not actually have a cache entry there (it might have been
-  // added to stage 1 instead).  No big deal if we don't.
-  CData *cdata = _source->_cycler.write_stage(0);
-  if (cdata->_cache.p() == this) {
-    cdata->_cache = NULL;
-  }
-  _source->_cycler.release_write_stage(0, cdata);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::CacheEntry::get_result_size
-//       Access: Public, Virtual
-//  Description: Returns the approximate number of bytes represented
-//               by the computed result.
-////////////////////////////////////////////////////////////////////
-int qpGeomPrimitive::CacheEntry::
-get_result_size() const {
-  return _decomposed->get_num_bytes();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: qpGeomPrimitive::CacheEntry::output
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void qpGeomPrimitive::CacheEntry::
-output(ostream &out) const {
-  out << "primitive " << (void *)_source;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomPrimitive::CData::make_copy
 //       Access: Public, Virtual

+ 8 - 24
panda/src/gobj/qpgeomPrimitive.h

@@ -21,7 +21,6 @@
 
 #include "pandabase.h"
 #include "qpgeomEnums.h"
-#include "qpgeomCacheEntry.h"
 #include "typedWritableReferenceCount.h"
 #include "luse.h"
 #include "updateSeq.h"
@@ -72,13 +71,14 @@ PUBLISHED:
   virtual PT(qpGeomPrimitive) make_copy() const=0;
 
   virtual PrimitiveType get_primitive_type() const=0;
-
-  INLINE UsageHint get_usage_hint() const;
-  INLINE void set_usage_hint(UsageHint usage_hint);
+  virtual int get_geom_rendering() const;
 
   INLINE ShadeModel get_shade_model() const;
   INLINE void set_shade_model(ShadeModel shade_model);
 
+  INLINE UsageHint get_usage_hint() const;
+  INLINE void set_usage_hint(UsageHint usage_hint);
+
   // The following published methods are provided for safe, high-level
   // iteration through the vertices and sub-primitives within the
   // GeomPrimitive class.  These work correctly regardless of the
@@ -109,6 +109,7 @@ PUBLISHED:
   INLINE int get_primitive_max_vertex(int n) const;
 
   CPT(qpGeomPrimitive) decompose() const;
+  CPT(qpGeomPrimitive) rotate() const;
 
   int get_num_bytes() const;
   INLINE int get_data_size_bytes() const;
@@ -131,8 +132,6 @@ public:
   // instead.
 
   INLINE CPTA_ushort get_vertices() const;
-  INLINE CPTA_ushort get_flat_first_vertices() const;
-  INLINE CPTA_ushort get_flat_last_vertices() const;
   PTA_ushort modify_vertices();
   void set_vertices(CPTA_ushort vertices);
 
@@ -147,7 +146,6 @@ public:
   virtual int get_min_num_vertices_per_primitive() const;
   virtual int get_num_unused_vertices_per_primitive() const;
 
-  void clear_cache();
   void prepare(PreparedGraphicsObjects *prepared_objects);
 
 public:
@@ -172,9 +170,6 @@ protected:
   virtual CPTA_ushort rotate_impl() const;
   virtual void append_unused_vertices(PTA_ushort &vertices, int vertex);
 
-protected:
-  static PStatCollector _rotate_pcollector;
-
 private:
   // A GeomPrimitive keeps a list (actually, a map) of all the
   // PreparedGraphicsObjects tables that it has been prepared into.
@@ -183,16 +178,6 @@ private:
   // itself from the other's list.
   typedef pmap<PreparedGraphicsObjects *, IndexBufferContext *> Contexts;
   Contexts _contexts;
-
-  class CacheEntry : public qpGeomCacheEntry {
-  public:
-    virtual void evict_callback();
-    virtual int get_result_size() const;
-    virtual void output(ostream &out) const;
-
-    qpGeomPrimitive *_source;
-    CPT(qpGeomPrimitive) _decomposed;
-  };
     
   // This is the data that must be cycled between pipeline stages.
   class EXPCL_PANDA CData : public CycleData {
@@ -206,7 +191,6 @@ private:
     UsageHint _usage_hint;
     ShadeModel _shade_model;
     PTA_ushort _vertices;
-    CPTA_ushort _rotated_vertices;
     PTA_int _ends;
     PTA_ushort _mins;
     PTA_ushort _maxs;
@@ -215,17 +199,17 @@ private:
     bool _got_minmax;
     unsigned short _min_vertex;
     unsigned short _max_vertex;
-
-    PT(CacheEntry) _cache;
   };
 
   PipelineCycler<CData> _cycler;
   typedef CycleDataReader<CData> CDReader;
   typedef CycleDataWriter<CData> CDWriter;
 
-  CPTA_ushort do_rotate(CDReader &cdata);
   void recompute_minmax(CDWriter &cdata);
 
+  static PStatCollector _decompose_pcollector;
+  static PStatCollector _rotate_pcollector;
+
 public:
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
 

+ 14 - 2
panda/src/gobj/qpgeomTrifans.cxx

@@ -78,6 +78,18 @@ get_primitive_type() const {
   return PT_polygons;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomTrifans::get_geom_rendering
+//       Access: Published, Virtual
+//  Description: Returns the set of GeomRendering bits that represent
+//               the rendering properties required to properly render
+//               this primitive.
+////////////////////////////////////////////////////////////////////
+int qpGeomTrifans::
+get_geom_rendering() const {
+  return GR_triangle_fan;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomTrifans::draw
 //       Access: Public, Virtual
@@ -147,8 +159,8 @@ CPTA_ushort qpGeomTrifans::
 rotate_impl() const {
   // Actually, we can't rotate fans without chaging the winding order.
   // It's an error to define a flat shade model for a GeomTrifan.
-  nassertr(false, get_vertices());
-  return get_vertices();
+  nassertr(false, CPTA_ushort());
+  return CPTA_ushort();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/gobj/qpgeomTrifans.h

@@ -37,6 +37,7 @@ PUBLISHED:
 public:
   virtual PT(qpGeomPrimitive) make_copy() const;
   virtual PrimitiveType get_primitive_type() const;
+  virtual int get_geom_rendering() const;
 
 public:
   virtual void draw(GraphicsStateGuardianBase *gsg) const;

+ 13 - 1
panda/src/gobj/qpgeomTristrips.cxx

@@ -79,6 +79,18 @@ get_primitive_type() const {
   return PT_polygons;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomTristrips::get_geom_rendering
+//       Access: Published, Virtual
+//  Description: Returns the set of GeomRendering bits that represent
+//               the rendering properties required to properly render
+//               this primitive.
+////////////////////////////////////////////////////////////////////
+int qpGeomTristrips::
+get_geom_rendering() const {
+  return GR_triangle_strip;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomTristrips::get_num_unused_vertices_per_primitive
 //       Access: Public, Virtual
@@ -256,7 +268,7 @@ rotate_impl() const {
   // If this assertion is triggered, there was a triangle strip with
   // an odd number of vertices and either SM_flat_first_vertex or
   // SM_flat_last_vertex specified--which is not allowed.
-  nassertr(!any_odd, new_vertices);
+  nassertr(!any_odd, CPTA_ushort());
   return new_vertices;
 }
 

+ 1 - 0
panda/src/gobj/qpgeomTristrips.h

@@ -37,6 +37,7 @@ PUBLISHED:
 public:
   virtual PT(qpGeomPrimitive) make_copy() const;
   virtual PrimitiveType get_primitive_type() const;
+  virtual int get_geom_rendering() const;
   virtual int get_num_unused_vertices_per_primitive() const;
 
 public:

+ 0 - 1
panda/src/gobj/qpgeomVertexData.cxx

@@ -230,7 +230,6 @@ void qpGeomVertexData::
 set_array(int i, const qpGeomVertexArrayData *array) {
   CDWriter cdata(_cycler);
   nassertv(i >= 0 && i < (int)cdata->_arrays.size());
-  nassertv(array->get_array_format() == cdata->_arrays[i]->get_array_format());
   cdata->_arrays[i] = (qpGeomVertexArrayData *)array;
   cdata->_modified = qpGeom::get_next_modified();
   cdata->_animated_vertices_modified = UpdateSeq();

+ 1 - 1
panda/src/gsgbase/graphicsStateGuardianBase.h

@@ -120,7 +120,7 @@ class Lens;
 class EXPCL_PANDA GraphicsStateGuardianBase : public TypedWritableReferenceCount {
 public:
   virtual bool get_supports_multisample() const=0;
-  virtual int get_supported_point_rendering() const=0;
+  virtual int get_supported_geom_rendering() const=0;
 
   // These functions will be queried by the GeomIssuer to determine if
   // it should issue normals, texcoords, and/or colors, based on the

+ 2 - 2
panda/src/pgraph/cullableObject.cxx

@@ -51,10 +51,10 @@ munge_geom(GraphicsStateGuardianBase *gsg,
       CPT(qpGeom) qpgeom = DCAST(qpGeom, _geom);
       _munged_data = qpgeom->get_vertex_data();
 
-      int point_rendering = _state->get_point_rendering(qpgeom->get_point_rendering());
+      int geom_rendering = _state->get_geom_rendering(qpgeom->get_geom_rendering());
 
       GraphicsStateGuardianBase *gsg = traverser->get_gsg();
-      if ((point_rendering & ~gsg->get_supported_point_rendering()) != 0) {
+      if ((geom_rendering & ~gsg->get_supported_geom_rendering() & qpGeom::GR_point_bits) != 0) {
         // The GSG doesn't support rendering these fancy points
         // directly; we have to render them in software instead.
         // Munge them into quads.  This will replace the _geom and

+ 9 - 9
panda/src/pgraph/renderModeAttrib.I

@@ -73,25 +73,25 @@ get_perspective() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: RenderModeAttrib::get_point_rendering
+//     Function: RenderModeAttrib::get_geom_rendering
 //       Access: Published
-//  Description: Returns the union of the Geom::PointRendering bits
+//  Description: Returns the union of the Geom::GeomRendering bits
 //               that will be required once this RenderModeAttrib is
 //               applied to a geom which includes the indicated
-//               geom_point_rendering bits.
+//               geom_rendering bits.
 ////////////////////////////////////////////////////////////////////
 INLINE int RenderModeAttrib::
-get_point_rendering(int geom_point_rendering) const {
+get_geom_rendering(int geom_rendering) const {
   if (_mode == M_point) {
-    geom_point_rendering |= qpGeom::PR_point;
+    geom_rendering |= qpGeom::GR_point;
   }
-  if ((geom_point_rendering & qpGeom::PR_point) != 0) {
+  if ((geom_rendering & qpGeom::GR_point) != 0) {
     if (_perspective) {
-      geom_point_rendering |= (qpGeom::PR_perspective | qpGeom::PR_uniform_size);
+      geom_rendering |= (qpGeom::GR_point_perspective | qpGeom::GR_point_uniform_size);
     } else if (_thickness != 1.0f) {
-      geom_point_rendering |= qpGeom::PR_uniform_size;
+      geom_rendering |= qpGeom::GR_point_uniform_size;
     }
   }
 
-  return geom_point_rendering;
+  return geom_rendering;
 }

+ 1 - 1
panda/src/pgraph/renderModeAttrib.h

@@ -50,7 +50,7 @@ PUBLISHED:
   INLINE float get_thickness() const;
   INLINE bool get_perspective() const;
 
-  INLINE int get_point_rendering(int geom_point_rendering) const;
+  INLINE int get_geom_rendering(int geom_rendering) const;
 
 public:
   virtual void issue(GraphicsStateGuardianBase *gsg) const;

+ 7 - 7
panda/src/pgraph/renderState.I

@@ -250,23 +250,23 @@ get_render_mode() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: RenderState::get_point_rendering
+//     Function: RenderState::get_geom_rendering
 //       Access: Published
-//  Description: Returns the union of the Geom::PointRendering bits
+//  Description: Returns the union of the Geom::GeomRendering bits
 //               that will be required once this RenderState is
 //               applied to a geom which includes the indicated
-//               geom_point_rendering bits.
+//               geom_rendering bits.
 ////////////////////////////////////////////////////////////////////
 INLINE int RenderState::
-get_point_rendering(int geom_point_rendering) const {
+get_geom_rendering(int geom_rendering) const {
   if (get_render_mode() != (const RenderModeAttrib *)NULL) {
-    geom_point_rendering = _render_mode->get_point_rendering(geom_point_rendering);
+    geom_rendering = _render_mode->get_geom_rendering(geom_rendering);
   }
   if (get_tex_gen() != (const TexGenAttrib *)NULL) {
-    geom_point_rendering = _tex_gen->get_point_rendering(geom_point_rendering);
+    geom_rendering = _tex_gen->get_geom_rendering(geom_rendering);
   }
 
-  return geom_point_rendering;
+  return geom_rendering;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/pgraph/renderState.h

@@ -127,7 +127,7 @@ PUBLISHED:
   INLINE const TexGenAttrib *get_tex_gen() const;
   INLINE const RenderModeAttrib *get_render_mode() const;
 
-  INLINE int get_point_rendering(int geom_point_rendering) const;
+  INLINE int get_geom_rendering(int geom_rendering) const;
 
 public:
   CPT(RenderState) issue_delta_modify(const RenderState *other, 

+ 7 - 7
panda/src/pgraph/texGenAttrib.I

@@ -44,22 +44,22 @@ TexGenAttrib(const TexGenAttrib &copy) :
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: TexGenAttrib::get_point_rendering
+//     Function: TexGenAttrib::get_geom_rendering
 //       Access: Published
-//  Description: Returns the union of the Geom::PointRendering bits
+//  Description: Returns the union of the Geom::GeomRendering bits
 //               that will be required once this TexGenAttrib is
 //               applied to a geom which includes the indicated
-//               geom_point_rendering bits.
+//               geom_rendering bits.
 ////////////////////////////////////////////////////////////////////
 INLINE int TexGenAttrib::
-get_point_rendering(int geom_point_rendering) const {
-  if ((geom_point_rendering & qpGeom::PR_point) != 0) {
+get_geom_rendering(int geom_rendering) const {
+  if ((geom_rendering & qpGeom::GR_point) != 0) {
     if (_num_point_sprites > 0) {
-      return geom_point_rendering |= qpGeom::PR_sprite;
+      return geom_rendering |= qpGeom::GR_point_sprite;
     }
   }
 
-  return geom_point_rendering;
+  return geom_rendering;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/pgraph/texGenAttrib.h

@@ -104,7 +104,7 @@ PUBLISHED:
   bool has_stage(TextureStage *stage) const;
   Mode get_mode(TextureStage *stage) const;
 
-  INLINE int get_point_rendering(int geom_point_rendering) const;
+  INLINE int get_geom_rendering(int geom_rendering) const;
 
 public:
   INLINE const Geom::NoTexCoordStages &get_no_texcoords() const;

+ 2 - 1
panda/src/pstatclient/pStatProperties.cxx

@@ -129,6 +129,8 @@ static TimeCollectorProperties time_properties[] = {
   { 1, "Cull:Munge",                       { 0.3, 0.3, 0.9 } },
   { 1, "Cull:Munge:Points",                { 0.2, 0.8, 0.4 } },
   { 1, "Cull:Munge:Data",                  { 0.7, 0.5, 0.2 } },
+  { 1, "Cull:Munge:Rotate",                { 0.9, 0.8, 0.5 } },
+  { 1, "Cull:Munge:Decompose",             { 0.1, 0.3, 0.1 } },
   { 1, "Draw",                             { 1.0, 0.0, 0.0 },  1.0 / 30.0 },
   { 1, "Draw:Make current",                { 0.4, 0.2, 0.6 } },
   { 1, "Draw:Copy texture",                { 0.2, 0.6, 0.4 } },
@@ -140,7 +142,6 @@ static TimeCollectorProperties time_properties[] = {
   { 1, "Draw:Flip:End",                    { 0.9, 0.3, 0.6 } },
   { 1, "Draw:Bins",                        { 0.3, 0.6, 0.0 } },
   { 0, "Draw:Primitive",                   { 0.0, 0.0, 0.5 } },
-  { 1, "Draw:Rotate",                      { 0.9, 0.8, 0.5 } },
   { 0, NULL }
 };
 

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio