0024450: TKOpenGl - Fixed pipeline materials update optimization does not distinguish...
[occt.git] / src / OpenGl / OpenGl_Workspace.cxx
1 // Created on: 2011-09-20
2 // Created by: Sergey ZERCHANINOV
3 // Copyright (c) 2011-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #ifdef HAVE_CONFIG_H
21   #include <config.h>
22 #endif
23
24 #include <OpenGl_GlCore15.hxx>
25
26 #include <InterfaceGraphic.hxx>
27
28 #include <OpenGl_AspectLine.hxx>
29 #include <OpenGl_AspectFace.hxx>
30 #include <OpenGl_AspectMarker.hxx>
31 #include <OpenGl_AspectText.hxx>
32 #include <OpenGl_Context.hxx>
33 #include <OpenGl_FrameBuffer.hxx>
34 #include <OpenGl_Texture.hxx>
35 #include <OpenGl_View.hxx>
36 #include <OpenGl_Workspace.hxx>
37 #include <OpenGl_Element.hxx>
38
39 #include <Graphic3d_TextureParams.hxx>
40
41 #if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
42   #include <OpenGl_AVIWriter.hxx>
43 #endif
44
45 IMPLEMENT_STANDARD_HANDLE(OpenGl_Workspace,OpenGl_Window)
46 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Workspace,OpenGl_Window)
47
48 namespace
49 {
50   static const TEL_COLOUR  THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } };
51   static const OpenGl_Vec4 THE_BLACK_COLOR      (0.0f, 0.0f, 0.0f, 1.0f);
52
53   static const OpenGl_AspectLine myDefaultAspectLine;
54   static const OpenGl_AspectFace myDefaultAspectFace;
55   static const OpenGl_AspectMarker myDefaultAspectMarker;
56   static const OpenGl_AspectText myDefaultAspectText;
57
58   static const OpenGl_TextParam myDefaultTextParam =
59   {
60     16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
61   };
62
63   static const OpenGl_Matrix myDefaultMatrix =
64   {
65     {{ 1.0F, 0.0F, 0.0F, 0.0F },
66      { 0.0F, 1.0F, 0.0F, 0.0F },
67      { 0.0F, 0.0F, 1.0F, 0.0F },
68      { 0.0F, 0.0F, 0.0F, 1.0F }}
69   };
70
71 };
72
73 // =======================================================================
74 // function : Init
75 // purpose  :
76 // =======================================================================
77 void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp)
78 {
79   // ambient component
80   if (theProp.color_mask & OPENGL_AMBIENT_MASK)
81   {
82     const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
83     Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb,
84                            aSrcAmb[1] * theProp.amb,
85                            aSrcAmb[2] * theProp.amb,
86                            1.0f);
87   }
88   else
89   {
90     Ambient = THE_BLACK_COLOR;
91   }
92
93   // diffusion component
94   if (theProp.color_mask & OPENGL_DIFFUSE_MASK)
95   {
96     const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
97     Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff,
98                            aSrcDif[1] * theProp.diff,
99                            aSrcDif[2] * theProp.diff,
100                            1.0f);
101   }
102   else
103   {
104     Diffuse = THE_BLACK_COLOR;
105   }
106
107   // specular component
108   if (theProp.color_mask & OPENGL_SPECULAR_MASK)
109   {
110     const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb;
111     Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec,
112                             aSrcSpe[1] * theProp.spec,
113                             aSrcSpe[2] * theProp.spec,
114                             1.0f);
115   }
116   else
117   {
118     Specular = THE_BLACK_COLOR;
119   }
120
121   // emission component
122   if (theProp.color_mask & OPENGL_EMISSIVE_MASK)
123   {
124     const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
125     Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv,
126                             aSrcEms[1] * theProp.emsv,
127                             aSrcEms[2] * theProp.emsv,
128                             1.0f);
129   }
130   else
131   {
132     Emission = THE_BLACK_COLOR;
133   }
134
135   ChangeShine()        = theProp.shine;
136   ChangeTransparency() = theProp.trans;
137 }
138
139 // =======================================================================
140 // function : OpenGl_Workspace
141 // purpose  :
142 // =======================================================================
143 OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_Display)& theDisplay,
144                                     const CALL_DEF_WINDOW&        theCWindow,
145                                     Aspect_RenderingContext       theGContext,
146                                     const Handle(OpenGl_Caps)&    theCaps,
147                                     const Handle(OpenGl_Context)& theShareCtx)
148 : OpenGl_Window (theDisplay, theCWindow, theGContext, theCaps, theShareCtx),
149   NamedStatus (0),
150   HighlightColor (&THE_WHITE_COLOR),
151   //
152   myIsTransientOpen (Standard_False),
153   myRetainMode (Standard_False),
154   myTransientDrawToFront (Standard_True),
155   myUseTransparency (Standard_False),
156   myUseZBuffer (Standard_False),
157   myUseDepthTest (Standard_True),
158   myUseGLLight (Standard_True),
159   myBackBufferRestored (Standard_False),
160   //
161   AspectLine_set (&myDefaultAspectLine),
162   AspectLine_applied (NULL),
163   AspectFace_set (&myDefaultAspectFace),
164   AspectFace_applied (NULL),
165   AspectMarker_set (&myDefaultAspectMarker),
166   AspectMarker_applied (NULL),
167   AspectText_set (&myDefaultAspectText),
168   AspectText_applied (NULL),
169   TextParam_set (&myDefaultTextParam),
170   TextParam_applied (NULL),
171   ViewMatrix_applied (&myDefaultMatrix),
172   StructureMatrix_applied (&myDefaultMatrix),
173   myModelViewMatrix (myDefaultMatrix),
174   PolygonOffset_applied (NULL)
175 {
176   theDisplay->InitAttributes();
177
178   // General initialization of the context
179
180   // Eviter d'avoir les faces mal orientees en noir.
181   // Pourrait etre utiliser pour detecter les problemes d'orientation
182   glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
183
184   // Optimisation pour le Fog et l'antialiasing
185   glHint (GL_FOG_HINT,            GL_FASTEST);
186   glHint (GL_POINT_SMOOTH_HINT,   GL_FASTEST);
187   glHint (GL_LINE_SMOOTH_HINT,    GL_FASTEST);
188   glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
189
190   // Polygon Offset
191   EnablePolygonOffset();
192
193 #ifdef HAVE_OPENCL
194
195   myComputeInitStatus = OpenGl_CLIS_NONE;
196
197   myViewModificationStatus = 0;
198   myLayersModificationStatus = 0;
199
200   myRaytraceOutputTexture[0] = 0;
201   myRaytraceOutputTexture[1] = 0;
202
203   myIsRaytraceDataValid = Standard_False;
204   myToUpdateRaytraceData = Standard_False;
205
206 #endif
207 }
208
209 // =======================================================================
210 // function : SetImmediateModeDrawToFront
211 // purpose  :
212 // =======================================================================
213 Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
214 {
215   const Standard_Boolean aPrevMode = myTransientDrawToFront;
216   myTransientDrawToFront = theDrawToFrontBuffer;
217   return aPrevMode;
218 }
219
220 // =======================================================================
221 // function : ~OpenGl_Workspace
222 // purpose  :
223 // =======================================================================
224 OpenGl_Workspace::~OpenGl_Workspace()
225 {
226 #ifdef HAVE_OPENCL
227   ReleaseOpenCL();
228 #endif
229 }
230
231 // =======================================================================
232 // function : Activate
233 // purpose  :
234 // =======================================================================
235 Standard_Boolean OpenGl_Workspace::Activate()
236 {
237   if (!OpenGl_Window::Activate())
238     return Standard_False;
239
240   ViewMatrix_applied      = &myDefaultMatrix;
241   StructureMatrix_applied = &myDefaultMatrix;
242
243   ResetAppliedAspect();
244
245   return Standard_True;
246 }
247
248 // =======================================================================
249 // function : UseTransparency
250 // purpose  : call_togl_transparency
251 // =======================================================================
252 void OpenGl_Workspace::UseTransparency (const Standard_Boolean theFlag)
253 {
254   myUseTransparency = theFlag;
255 }
256
257 //=======================================================================
258 //function : ResetAppliedAspect
259 //purpose  : Sets default values of GL parameters in accordance with default aspects
260 //=======================================================================
261 void OpenGl_Workspace::ResetAppliedAspect()
262 {
263   NamedStatus           = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
264   HighlightColor        = &THE_WHITE_COLOR;
265   AspectLine_set        = &myDefaultAspectLine;
266   AspectLine_applied    = NULL;
267   AspectFace_set        = &myDefaultAspectFace;
268   AspectFace_applied    = NULL;
269   AspectMarker_set      = &myDefaultAspectMarker;
270   AspectMarker_applied  = NULL;
271   AspectText_set        = &myDefaultAspectText;
272   AspectText_applied    = NULL;
273   TextParam_set         = &myDefaultTextParam;
274   TextParam_applied     = NULL;
275   PolygonOffset_applied = NULL;
276
277   AspectLine(Standard_True);
278   AspectFace(Standard_True);
279   AspectMarker(Standard_True);
280   AspectText(Standard_True);
281 }
282
283 // =======================================================================
284 // function : DisableTexture
285 // purpose  :
286 // =======================================================================
287 Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
288 {
289   if (myTextureBound.IsNull())
290   {
291     return myTextureBound;
292   }
293
294   // reset texture matrix because some code may expect it is identity
295   GLint aMatrixMode = GL_TEXTURE;
296   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
297   glMatrixMode (GL_TEXTURE);
298   glLoadIdentity();
299   glMatrixMode (aMatrixMode);
300
301   myTextureBound->Unbind (myGlContext);
302   switch (myTextureBound->GetTarget())
303   {
304     case GL_TEXTURE_1D:
305     {
306       if (myTextureBound->GetParams()->GenMode() != GL_NONE)
307       {
308         glDisable (GL_TEXTURE_GEN_S);
309       }
310       glDisable (GL_TEXTURE_1D);
311       break;
312     }
313     case GL_TEXTURE_2D:
314     {
315       if (myTextureBound->GetParams()->GenMode() != GL_NONE)
316       {
317         glDisable (GL_TEXTURE_GEN_S);
318         glDisable (GL_TEXTURE_GEN_T);
319         if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
320         {
321           glDisable (GL_POINT_SPRITE);
322         }
323       }
324       glDisable (GL_TEXTURE_2D);
325       break;
326     }
327     default: break;
328   }
329
330   Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
331   myTextureBound.Nullify();
332   return aPrevTexture;
333 }
334
335 // =======================================================================
336 // function : setTextureParams
337 // purpose  :
338 // =======================================================================
339 void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&                theTexture,
340                                          const Handle(Graphic3d_TextureParams)& theParams)
341 {
342   const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
343   if (aParams.IsNull())
344   {
345     return;
346   }
347
348   GLint aMatrixMode = GL_TEXTURE;
349   glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
350
351   // setup texture matrix
352   glMatrixMode (GL_TEXTURE);
353   glLoadIdentity();
354   const Graphic3d_Vec2& aScale = aParams->Scale();
355   const Graphic3d_Vec2& aTrans = aParams->Translation();
356   glScalef     ( aScale.x(),  aScale.y(), 1.0f);
357   glTranslatef (-aTrans.x(), -aTrans.y(), 0.0f);
358   glRotatef (-aParams->Rotation(), 0.0f, 0.0f, 1.0f);
359
360   // setup generation of texture coordinates
361   switch (aParams->GenMode())
362   {
363     case Graphic3d_TOTM_OBJECT:
364     {
365       glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
366       glTexGenfv (GL_S, GL_OBJECT_PLANE,     aParams->GenPlaneS().GetData());
367       if (theTexture->GetTarget() != GL_TEXTURE_1D)
368       {
369         glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
370         glTexGenfv (GL_T, GL_OBJECT_PLANE,     aParams->GenPlaneT().GetData());
371       }
372       break;
373     }
374     case Graphic3d_TOTM_SPHERE:
375     {
376       glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
377       if (theTexture->GetTarget() != GL_TEXTURE_1D)
378       {
379         glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
380       }
381       break;
382     }
383     case Graphic3d_TOTM_EYE:
384     {
385       glMatrixMode (GL_MODELVIEW);
386       glPushMatrix();
387       glLoadIdentity();
388
389       glTexGeni  (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
390       glTexGenfv (GL_S, GL_EYE_PLANE,        aParams->GenPlaneS().GetData());
391
392       if (theTexture->GetTarget() != GL_TEXTURE_1D)
393       {
394         glTexGeni  (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
395         glTexGenfv (GL_T, GL_EYE_PLANE,        aParams->GenPlaneT().GetData());
396       }
397       glPopMatrix();
398       break;
399     }
400     case Graphic3d_TOTM_SPRITE:
401     {
402       if (GetGlContext()->core20 != NULL)
403       {
404         glEnable  (GL_POINT_SPRITE);
405         glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
406         glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
407         GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
408       }
409       break;
410     }
411     case Graphic3d_TOTM_MANUAL:
412     default: break;
413   }
414
415   // setup lighting
416   if (aParams->GenMode() != Graphic3d_TOTM_SPRITE)
417   {
418     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, aParams->IsModulate() ? GL_MODULATE : GL_DECAL);
419   }
420
421   // setup texture filtering and wrapping
422   //if (theTexture->GetParams() != theParams)
423   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
424   const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : GL_CLAMP;
425   switch (theTexture->GetTarget())
426   {
427     case GL_TEXTURE_1D:
428     {
429       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
430       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
431       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
432       break;
433     }
434     case GL_TEXTURE_2D:
435     {
436       GLenum aFilterMin = aFilter;
437       if (theTexture->HasMipmaps())
438       {
439         aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
440         if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
441         {
442           aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
443         }
444         else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
445         {
446           aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
447         }
448
449         if (myGlContext->extAnis)
450         {
451           // setup degree of anisotropy filter
452           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
453           switch (aParams->AnisoFilter())
454           {
455             case Graphic3d_LOTA_QUALITY:
456             {
457               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aMaxDegree);
458               break;
459             }
460             case Graphic3d_LOTA_MIDDLE:
461             {
462
463               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2));
464               break;
465             }
466             case Graphic3d_LOTA_FAST:
467             {
468               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2);
469               break;
470             }
471             case Graphic3d_LOTA_OFF:
472             default:
473             {
474               glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
475               break;
476             }
477           }
478         }
479       }
480       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
481       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
482       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
483       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
484       break;
485     }
486     default: break;
487   }
488
489   switch (theTexture->GetTarget())
490   {
491     case GL_TEXTURE_1D:
492     {
493       if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
494       {
495         glEnable (GL_TEXTURE_GEN_S);
496       }
497       glEnable (GL_TEXTURE_1D);
498       break;
499     }
500     case GL_TEXTURE_2D:
501     {
502       if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
503       {
504         glEnable (GL_TEXTURE_GEN_S);
505         glEnable (GL_TEXTURE_GEN_T);
506       }
507       glEnable (GL_TEXTURE_2D);
508       break;
509     }
510     default: break;
511   }
512
513   glMatrixMode (aMatrixMode); // turn back active matrix
514   theTexture->SetParams (aParams);
515 }
516
517 // =======================================================================
518 // function : EnableTexture
519 // purpose  :
520 // =======================================================================
521 Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)&          theTexture,
522                                                         const Handle(Graphic3d_TextureParams)& theParams)
523 {
524   if (theTexture.IsNull() || !theTexture->IsValid())
525   {
526     return DisableTexture();
527   }
528
529   if (myTextureBound == theTexture
530    && (theParams.IsNull() || theParams == theTexture->GetParams()))
531   {
532     // already bound
533     return myTextureBound;
534   }
535
536   Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
537   myTextureBound = theTexture;
538   myTextureBound->Bind (myGlContext);
539   setTextureParams (myTextureBound, theParams);
540
541   return aPrevTexture;
542 }
543
544 // =======================================================================
545 // function : Redraw
546 // purpose  :
547 // =======================================================================
548 void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView,
549                                const Aspect_CLayer2d& theCUnderLayer,
550                                const Aspect_CLayer2d& theCOverLayer)
551 {
552   if (!Activate())
553   {
554     return;
555   }
556
557   // release pending GL resources
558   Handle(OpenGl_Context) aGlCtx = GetGlContext();
559   aGlCtx->ReleaseDelayed();
560
561   // cache render mode state
562   GLint aRendMode = GL_RENDER;
563   glGetIntegerv (GL_RENDER_MODE,  &aRendMode);
564   aGlCtx->SetFeedback (aRendMode == GL_FEEDBACK);
565
566   Tint toSwap = (aRendMode == GL_RENDER); // swap buffers
567   GLint aViewPortBack[4];
568   OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
569   if (aFrameBuffer != NULL)
570   {
571     glGetIntegerv (GL_VIEWPORT, aViewPortBack);
572     aFrameBuffer->SetupViewport (aGlCtx);
573     aFrameBuffer->BindBuffer    (aGlCtx);
574     toSwap = 0; // no need to swap buffers
575   }
576
577 #ifdef HAVE_OPENCL
578   if (!theCView.IsRaytracing || myComputeInitStatus == OpenGl_CLIS_FAIL)
579   {
580 #endif
581     Redraw1 (theCView, theCUnderLayer, theCOverLayer, toSwap);
582     if (aFrameBuffer == NULL || !myTransientDrawToFront)
583     {
584       RedrawImmediatMode();
585     }
586
587     theCView.WasRedrawnGL = Standard_True;
588 #ifdef HAVE_OPENCL
589   }
590   else
591   {
592     int aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
593     int aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
594
595     Raytrace (theCView, aSizeX, aSizeY, toSwap);
596
597     theCView.WasRedrawnGL = Standard_False;
598   }
599 #endif
600
601   if (aFrameBuffer != NULL)
602   {
603     aFrameBuffer->UnbindBuffer (aGlCtx);
604     // move back original viewport
605     glViewport (aViewPortBack[0], aViewPortBack[1], aViewPortBack[2], aViewPortBack[3]);
606   }
607
608 #if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
609   if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
610   {
611     GLint params[4];
612     glGetIntegerv (GL_VIEWPORT, params);
613     int nWidth  = params[2] & ~0x7;
614     int nHeight = params[3] & ~0x7;
615
616     const int nBitsPerPixel = 24;
617     GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
618
619     glPixelStorei (GL_PACK_ALIGNMENT, 1);
620     glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
621     OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
622     delete[] aDumpData;
623   }
624 #endif
625
626   // reset render mode state
627   aGlCtx->SetFeedback (Standard_False);
628 }