0029768: Visualization, TKOpenGl - structure is entirely clipped by suppressed clipping
[occt.git] / src / OpenGl / OpenGl_Window_1.mm
1 // Created on: 2012-11-12
2 // Created by: Kirill Gavrilov
3 // Copyright (c) 2012-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #if defined(__APPLE__) && !defined(MACOSX_USE_GLX)
17
18 #ifndef GL_GLEXT_LEGACY
19 #define GL_GLEXT_LEGACY // To prevent inclusion of system glext.h on Mac OS X 10.6.8
20 #endif
21
22 #import <TargetConditionals.h>
23
24 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
25   #import <UIKit/UIKit.h>
26 #else
27   #import <Cocoa/Cocoa.h>
28
29 #if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7)
30 @interface NSView (LionAPI)
31 - (NSSize )convertSizeToBacking: (NSSize )theSize;
32 @end
33 #endif
34
35 #endif
36
37 #include <OpenGl_Window.hxx>
38 #include <OpenGl_FrameBuffer.hxx>
39
40 #include <OpenGl_Context.hxx>
41 #include <Aspect_GraphicDeviceDefinitionError.hxx>
42 #include <Cocoa_LocalPool.hxx>
43 #include <TCollection_AsciiString.hxx>
44 #include <TCollection_ExtendedString.hxx>
45
46 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
47   //
48 #else
49   #include <OpenGL/CGLRenderers.h>
50 #endif
51
52 // =======================================================================
53 // function : OpenGl_Window
54 // purpose  :
55 // =======================================================================
56 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
57                               const Handle(Aspect_Window)&  thePlatformWindow,
58                               Aspect_RenderingContext       theGContext,
59                               const Handle(OpenGl_Caps)&    theCaps,
60                               const Handle(OpenGl_Context)& theShareCtx)
61 : myGlContext (new OpenGl_Context (theCaps)),
62   myOwnGContext (theGContext == 0),
63   myPlatformWindow (thePlatformWindow),
64 #if defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
65   myUIView (NULL),
66 #endif
67   mySwapInterval (theCaps->swapInterval)
68 {
69   (void )theDriver;
70   myPlatformWindow->Size (myWidth, myHeight);
71
72 #if defined(__APPLE__)
73   myWidthPt  = myWidth;
74   myHeightPt = myHeight;
75 #endif
76
77 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
78   EAGLContext* aGLContext = theGContext;
79   if (aGLContext == NULL)
80   {
81     void* aViewPtr = (void* )myPlatformWindow->NativeHandle();
82
83     myUIView = (__bridge UIView* )aViewPtr;
84     CAEAGLLayer* anEaglLayer = (CAEAGLLayer* )myUIView.layer;
85     anEaglLayer.opaque = TRUE;
86     anEaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
87                                         [NSNumber numberWithBool: FALSE], kEAGLDrawablePropertyRetainedBacking,
88                                         kEAGLColorFormatRGBA8,            kEAGLDrawablePropertyColorFormat,
89                                         NULL];
90
91     aGLContext = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
92     if (aGLContext == NULL
93     || ![EAGLContext setCurrentContext: aGLContext])
94     {
95       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext creation failed");
96       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
97       return;
98     }
99
100     myGlContext->Init (aGLContext, Standard_False);
101   }
102   else
103   {
104     if (![EAGLContext setCurrentContext: aGLContext])
105     {
106       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext can not be assigned");
107       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
108       return;
109     }
110
111     myGlContext->Init (aGLContext, Standard_False);
112   }
113 #else
114
115   Cocoa_LocalPool aLocalPool;
116
117   // all GL context within one OpenGl_GraphicDriver should be shared!
118   NSOpenGLContext* aGLCtxShare = theShareCtx.IsNull() ? NULL : theShareCtx->myGContext;
119   NSOpenGLContext* aGLContext  = theGContext;
120   bool isCore = false;
121   if (aGLContext == NULL)
122   {
123     NSOpenGLPixelFormatAttribute anAttribs[32] = {};
124     Standard_Integer aLastAttrib = 0;
125     //anAttribs[aLastAttrib++] = NSOpenGLPFAColorSize;    anAttribs[aLastAttrib++] = 32,
126     anAttribs[aLastAttrib++] = NSOpenGLPFADepthSize;    anAttribs[aLastAttrib++] = 24;
127     anAttribs[aLastAttrib++] = NSOpenGLPFAStencilSize;  anAttribs[aLastAttrib++] = 8;
128     anAttribs[aLastAttrib++] = NSOpenGLPFADoubleBuffer;
129     if (theCaps->contextNoAccel)
130     {
131       anAttribs[aLastAttrib++] = NSOpenGLPFARendererID;
132       anAttribs[aLastAttrib++] = (NSOpenGLPixelFormatAttribute )kCGLRendererGenericFloatID;
133     }
134     else
135     {
136       anAttribs[aLastAttrib++] = NSOpenGLPFAAccelerated;
137     }
138     anAttribs[aLastAttrib] = 0;
139     const Standard_Integer aLastMainAttrib = aLastAttrib;
140     Standard_Integer aTryCore   = 0;
141     Standard_Integer aTryStereo = 0;
142     for (aTryCore = 1; aTryCore >= 0; --aTryCore)
143     {
144       aLastAttrib = aLastMainAttrib;
145       if (aTryCore == 1)
146       {
147         if (theCaps->contextCompatible)
148         {
149           continue;
150         }
151
152         // supported since OS X 10.7+
153         anAttribs[aLastAttrib++] = 99;     // NSOpenGLPFAOpenGLProfile
154         anAttribs[aLastAttrib++] = 0x3200; // NSOpenGLProfileVersion3_2Core
155       }
156
157       for (aTryStereo = 1; aTryStereo >= 0; --aTryStereo)
158       {
159         if (aTryStereo == 1)
160         {
161           if (!theCaps->contextStereo)
162           {
163             continue;
164           }
165
166           // deprecated since macOS 10.12 without replacement
167           Standard_DISABLE_DEPRECATION_WARNINGS
168           anAttribs[aLastAttrib++] = NSOpenGLPFAStereo;
169           Standard_ENABLE_DEPRECATION_WARNINGS
170         }
171
172         anAttribs[aLastAttrib] = 0;
173
174         NSOpenGLPixelFormat* aGLFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes: anAttribs] autorelease];
175         aGLContext = [[NSOpenGLContext alloc] initWithFormat: aGLFormat
176                                                 shareContext: aGLCtxShare];
177         if (aGLContext != NULL)
178         {
179           break;
180         }
181       }
182
183       if (aGLContext != NULL)
184       {
185         break;
186       }
187     }
188
189     if (aGLContext == NULL)
190     {
191       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: NSOpenGLContext creation failed");
192       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
193       return;
194     }
195
196     if (aTryStereo == 0
197      && theCaps->contextStereo)
198     {
199       TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: QuadBuffer is unavailable!");
200       myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
201     }
202     if (aTryCore == 0
203     && !theCaps->contextCompatible)
204     {
205       TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
206       myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
207     }
208
209     NSView* aView = (NSView* )myPlatformWindow->NativeHandle();
210     [aGLContext setView: aView];
211     isCore = (aTryCore == 1);
212   }
213
214   myGlContext->Init (aGLContext, isCore);
215 #endif
216
217   myGlContext->Share (theShareCtx);
218   myGlContext->SetSwapInterval (mySwapInterval);
219   Init();
220 }
221
222 // =======================================================================
223 // function : ~OpenGl_Window
224 // purpose  :
225 // =======================================================================
226 OpenGl_Window::~OpenGl_Window()
227 {
228   if (!myOwnGContext
229    ||  myGlContext.IsNull())
230   {
231     myGlContext.Nullify();
232     return;
233   }
234
235 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
236   myGlContext.Nullify();
237   [EAGLContext setCurrentContext: NULL];
238   myUIView = NULL;
239 #else
240   NSOpenGLContext* aGLCtx = myGlContext->myGContext;
241   myGlContext.Nullify();
242
243   [NSOpenGLContext clearCurrentContext];
244   [aGLCtx clearDrawable];
245   [aGLCtx release];
246 #endif
247 }
248
249 // =======================================================================
250 // function : Resize
251 // purpose  : call_subr_resize
252 // =======================================================================
253 void OpenGl_Window::Resize()
254 {
255   // If the size is not changed - do nothing
256   Standard_Integer aWidthPt  = 0;
257   Standard_Integer aHeightPt = 0;
258   myPlatformWindow->Size (aWidthPt, aHeightPt);
259   if (myWidthPt  == aWidthPt
260    && myHeightPt == aHeightPt)
261   {
262   #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
263     return;
264   #else
265     // check backing store change (moving to another screen)
266     NSOpenGLContext* aGLCtx = myGlContext->myGContext;
267     NSView* aView = [aGLCtx view];
268     if (![aView respondsToSelector: @selector(convertSizeToBacking:)])
269     {
270       return;
271     }
272
273     NSRect aBounds = [aView bounds];
274     NSSize aRes    = [aView convertSizeToBacking: aBounds.size];
275     if (myWidth  == Standard_Integer(aRes.width)
276      && myHeight == Standard_Integer(aRes.height))
277     {
278       return;
279     }
280   #endif
281   }
282
283   myWidthPt  = aWidthPt;
284   myHeightPt = aHeightPt;
285
286   Init();
287 }
288
289 // =======================================================================
290 // function : Init
291 // purpose  :
292 // =======================================================================
293 void OpenGl_Window::Init()
294 {
295   if (!Activate())
296   {
297     return;
298   }
299
300 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
301   Handle(OpenGl_FrameBuffer) aDefFbo = myGlContext->SetDefaultFrameBuffer (NULL);
302   if (!aDefFbo.IsNull())
303   {
304     aDefFbo->Release (myGlContext.operator->());
305   }
306   else
307   {
308     aDefFbo = new OpenGl_FrameBuffer();
309   }
310
311   if (myOwnGContext)
312   {
313     EAGLContext* aGLCtx      = myGlContext->myGContext;
314     CAEAGLLayer* anEaglLayer = (CAEAGLLayer* )myUIView.layer;
315     GLuint aWinRBColor = 0;
316     ::glGenRenderbuffers (1, &aWinRBColor);
317     ::glBindRenderbuffer (GL_RENDERBUFFER, aWinRBColor);
318     [aGLCtx renderbufferStorage: GL_RENDERBUFFER fromDrawable: anEaglLayer];
319     ::glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH,  &myWidth);
320     ::glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myHeight);
321     ::glBindRenderbuffer (GL_RENDERBUFFER, 0);
322
323     if (!aDefFbo->InitWithRB (myGlContext, myWidth, myHeight, GL_RGBA8, GL_DEPTH24_STENCIL8, aWinRBColor))
324     {
325       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
326       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
327       return;
328     }
329   }
330   else
331   {
332     if (!aDefFbo->InitWrapper (myGlContext))
333     {
334       TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO wrapper creation failed");
335       throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
336       return;
337     }
338
339     myWidth  = aDefFbo->GetVPSizeX();
340     myHeight = aDefFbo->GetVPSizeY();
341   }
342   myGlContext->SetDefaultFrameBuffer (aDefFbo);
343   aDefFbo->BindBuffer (myGlContext);
344   aDefFbo.Nullify();
345 #else
346   NSOpenGLContext* aGLCtx  = myGlContext->myGContext;
347   NSView*          aView   = [aGLCtx view];
348   NSRect           aBounds = [aView bounds];
349
350   // we should call this method each time when window is resized
351   [aGLCtx update];
352
353   if ([aView respondsToSelector: @selector(convertSizeToBacking:)])
354   {
355     NSSize aRes = [aView convertSizeToBacking: aBounds.size];
356     myWidth  = Standard_Integer(aRes.width);
357     myHeight = Standard_Integer(aRes.height);
358   }
359   else
360   {
361     myWidth  = Standard_Integer(aBounds.size.width);
362     myHeight = Standard_Integer(aBounds.size.height);
363   }
364   myWidthPt  = Standard_Integer(aBounds.size.width);
365   myHeightPt = Standard_Integer(aBounds.size.height);
366 #endif
367
368   ::glDisable (GL_DITHER);
369   ::glDisable (GL_SCISSOR_TEST);
370   ::glViewport (0, 0, myWidth, myHeight);
371 #if !defined(GL_ES_VERSION_2_0)
372   ::glDrawBuffer (GL_BACK);
373   if (myGlContext->core11 != NULL)
374   {
375     ::glMatrixMode (GL_MODELVIEW);
376   }
377 #endif
378 }
379
380 // =======================================================================
381 // function : SetSwapInterval
382 // purpose  :
383 // =======================================================================
384 void OpenGl_Window::SetSwapInterval()
385 {
386   if (mySwapInterval != myGlContext->caps->swapInterval)
387   {
388     mySwapInterval = myGlContext->caps->swapInterval;
389     myGlContext->SetSwapInterval (mySwapInterval);
390   }
391 }
392
393 #endif // __APPLE__