0024452: TKOpenGl - Memory leak in OpenGl_ShaderManager
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
index 95491ad..d5ad6b9 100644 (file)
@@ -27,6 +27,7 @@
 #include <OpenGl_Context.hxx>
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
+#include <OpenGl_Workspace.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
@@ -249,6 +250,36 @@ const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
   return myWorldViewState;
 }
 
+//! Packed properties of light source
+class OpenGl_ShaderLightParameters
+{
+public:
+
+  OpenGl_Vec4 Color;
+  OpenGl_Vec4 Position;
+  OpenGl_Vec4 Direction;
+  OpenGl_Vec4 Parameters;
+
+  //! Returns packed (serialized) representation of light source properties
+  const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
+  static Standard_Integer NbOfVec4() { return 4; }
+
+};
+
+//! Packed light source type information
+class OpenGl_ShaderLightType
+{
+public:
+
+  Standard_Integer Type;
+  Standard_Integer IsHeadlight;
+
+  //! Returns packed (serialized) representation of light source type
+  const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
+  static Standard_Integer NbOfVec2i() { return 1; }
+
+};
+
 // =======================================================================
 // function : PushLightSourceState
 // purpose  : Pushes state of OCCT light sources to the program
@@ -261,8 +292,11 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr
     return;
   }
 
-  const GLint aTypesLoc  = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES);
-  const GLint aParamsLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS);
+  OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
+  for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
+  {
+    aLightTypeArray[aLightIt].Type = -1;
+  }
 
   const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
   if (aLightsDefNb < 1)
@@ -273,12 +307,16 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr
     theProgram->SetUniform (myContext,
                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
                             OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
+    theProgram->SetUniform (myContext,
+                            theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
+                            OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
+                            aLightTypeArray[0].Packed());
     theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
+    delete[] aLightTypeArray;
     return;
   }
 
-  OpenGl_Vec2i* aTypesArray  = new OpenGl_Vec2i[aLightsDefNb];
-  OpenGl_Vec4*  aParamsArray = new OpenGl_Vec4 [aLightsDefNb * 4];
+  OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
 
   OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
   Standard_Integer aLightsNb = 0;
@@ -295,18 +333,20 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr
       continue;
     }
 
-    aTypesArray[aLightsNb].x() = aLight.Type;
-    aTypesArray[aLightsNb].y() = aLight.IsHeadlight;
+    OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
+    aLightType.Type        = aLight.Type;
+    aLightType.IsHeadlight = aLight.IsHeadlight;
 
-    aParamsArray[aLightsNb * 4 + 0] =   aLight.Color;
-    aParamsArray[aLightsNb * 4 + 1] =   aLight.Type == Visual3d_TOLS_DIRECTIONAL
-                                    ?  -aLight.Direction
-                                    :   aLight.Position;
+    OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
+    aLightParams.Color    = aLight.Color;
+    aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
+                         ? -aLight.Direction
+                         :  aLight.Position;
     if (aLight.Type == Visual3d_TOLS_SPOT)
     {
-      aParamsArray[aLightsNb * 4 + 2] = aLight.Direction;
+      aLightParams.Direction = aLight.Direction;
     }
-    aParamsArray[aLightsNb * 4 + 3] =   aLight.Params;
+    aLightParams.Parameters = aLight.Params;
     ++aLightsNb;
   }
 
@@ -316,13 +356,19 @@ void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgr
   theProgram->SetUniform (myContext,
                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
                           anAmbient);
+  theProgram->SetUniform (myContext,
+                          theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
+                          OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
+                          aLightTypeArray[0].Packed());
   if (aLightsNb > 0)
   {
-    myContext->core20->glUniform2iv (aTypesLoc,  aLightsNb,     aTypesArray [0].GetData());
-    myContext->core20->glUniform4fv (aParamsLoc, aLightsNb * 4, aParamsArray[0].GetData());
+    theProgram->SetUniform (myContext,
+                            theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
+                            aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
+                            aLightParamsArray[0].Packed());
   }
-  delete[] aTypesArray;
-  delete[] aParamsArray;
+  delete[] aLightParamsArray;
+  delete[] aLightTypeArray;
 
   theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
 }
@@ -468,7 +514,7 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
   }
 
   GLuint aPlanesNb = 0;
-  for (Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
+  for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
        anIter.More(); anIter.Next())
   {
     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
@@ -487,7 +533,7 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
   OpenGl_Vec4* anEquations = new OpenGl_Vec4[aPlanesNb];
   GLint*       aSpaces     = new GLint      [aPlanesNb];
   GLuint aPlaneId = 0;
-  for (Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
+  for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
        anIter.More(); anIter.Next())
   {
     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
@@ -504,8 +550,9 @@ void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)
     aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
     ++aPlaneId;
   }
-  myContext->core20->glUniform4fv (aLocEquations, aPlanesNb, anEquations[0].GetData());
-  myContext->core20->glUniform1iv (aLocSpaces,    aPlanesNb, aSpaces);
+  theProgram->SetUniform (myContext, aLocEquations, aPlanesNb, anEquations[0].GetData());
+  theProgram->SetUniform (myContext, aLocSpaces,    aPlanesNb, aSpaces);
+
   delete[] anEquations;
   delete[] aSpaces;
 }
@@ -576,7 +623,7 @@ static void PushAspectFace (const Handle(OpenGl_Context)&       theCtx,
                           theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
                           theAspect->DistinguishingMode());
 
-  OpenGl_Vec4 aParams[5];
+  OpenGl_Material aParams;
   for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
   {
     const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
@@ -587,30 +634,9 @@ static void PushAspectFace (const Handle(OpenGl_Context)&       theCtx,
       continue;
     }
 
-    const OPENGL_SURF_PROP& aProps = (anIndex == 0) ? theAspect->IntFront() : theAspect->IntBack();
-    const OpenGl_Vec4 anEmission (aProps.emscol.rgb[0] * aProps.emsv,
-                                  aProps.emscol.rgb[1] * aProps.emsv,
-                                  aProps.emscol.rgb[2] * aProps.emsv,
-                                  aProps.emscol.rgb[3] * aProps.emsv);
-    const OpenGl_Vec4 anAmbient  (aProps.ambcol.rgb[0] * aProps.amb,
-                                  aProps.ambcol.rgb[1] * aProps.amb,
-                                  aProps.ambcol.rgb[2] * aProps.amb,
-                                  aProps.ambcol.rgb[3] * aProps.amb);
-    const OpenGl_Vec4 aDiffuse   (aProps.difcol.rgb[0] * aProps.diff,
-                                  aProps.difcol.rgb[1] * aProps.diff,
-                                  aProps.difcol.rgb[2] * aProps.diff,
-                                  aProps.difcol.rgb[3] * aProps.diff);
-    const OpenGl_Vec4 aSpecular  (aProps.speccol.rgb[0] * aProps.spec,
-                                  aProps.speccol.rgb[1] * aProps.spec,
-                                  aProps.speccol.rgb[2] * aProps.spec,
-                                  aProps.speccol.rgb[3] * aProps.spec);
-    aParams[0] = anEmission;
-    aParams[1] = anAmbient;
-    aParams[2] = aDiffuse;
-    aParams[3] = aSpecular;
-    aParams[4].x() = aProps.shine;
-    aParams[4].y() = aProps.trans;
-    theCtx->core20->glUniform4fv (aLoc, 5, aParams[0].GetData());
+    aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
+    theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
+                            aParams.Packed());
   }
 }
 
@@ -636,8 +662,8 @@ static void PushAspectLine (const Handle(OpenGl_Context)&       theCtx,
   aParams[3] = THE_COLOR_BLACK_VEC4;
   aParams[4].x() = 0.0f; // shininess
   aParams[4].y() = 0.0f; // transparency
-  theCtx->core20->glUniform4fv (theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
-                                5, aParams[0].GetData());
+  theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
+                          5, aParams);
 }
 
 // =======================================================================
@@ -672,8 +698,8 @@ static void PushAspectText (const Handle(OpenGl_Context)&       theCtx,
   aParams[3] = THE_COLOR_BLACK_VEC4;
   aParams[4].x() = 0.0f; // shininess
   aParams[4].y() = 0.0f; // transparency
-  theCtx->core20->glUniform4fv (theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
-                                5, aParams[0].GetData());
+  theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
+                          5, aParams);
 }
 
 // =======================================================================
@@ -699,8 +725,8 @@ static void PushAspectMarker (const Handle(OpenGl_Context)&       theCtx,
   aParams[3] = THE_COLOR_BLACK_VEC4;
   aParams[4].x() = 0.0f; // shininess
   aParams[4].y() = 0.0f; // transparency
-  theCtx->core20->glUniform4fv (theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
-                                5, aParams[0].GetData());
+  theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
+                          5, aParams);
 }
 
 }; // nameless namespace