e259b0dc31cdd1658bcf9fbc4114d09c7084f5e3
[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 #define GL_GLEXT_LEGACY // To prevent inclusion of system glext.h on Mac OS X 10.6.8
19
20 #import <Cocoa/Cocoa.h>
21
22 #include <InterfaceGraphic.hxx>
23
24 #include <OpenGl_Window.hxx>
25
26 #include <OpenGl_Context.hxx>
27 #include <Aspect_GraphicDeviceDefinitionError.hxx>
28 #include <Cocoa_LocalPool.hxx>
29 #include <TCollection_AsciiString.hxx>
30 #include <TCollection_ExtendedString.hxx>
31
32 #include <OpenGL/CGLRenderers.h>
33
34 namespace
35 {
36   static const TEL_COLOUR THE_DEFAULT_BG_COLOR = { { 0.F, 0.F, 0.F, 1.F } };
37 };
38
39 // =======================================================================
40 // function : OpenGl_Window
41 // purpose  :
42 // =======================================================================
43 OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
44                               const CALL_DEF_WINDOW&        theCWindow,
45                               Aspect_RenderingContext       theGContext,
46                               const Handle(OpenGl_Caps)&    theCaps,
47                               const Handle(OpenGl_Context)& theShareCtx)
48 : myGlContext (new OpenGl_Context (theCaps)),
49   myOwnGContext (theGContext == 0),
50   myWidth  ((Standard_Integer )theCWindow.dx),
51   myHeight ((Standard_Integer )theCWindow.dy),
52   myBgColor (THE_DEFAULT_BG_COLOR)
53 {
54   myBgColor.rgb[0] = theCWindow.Background.r;
55   myBgColor.rgb[1] = theCWindow.Background.g;
56   myBgColor.rgb[2] = theCWindow.Background.b;
57
58   Cocoa_LocalPool aLocalPool;
59   //NSOpenGLContext* aGContext = (NSOpenGLContext* )theGContext;
60
61   // all GL context within one OpenGl_GraphicDriver should be shared!
62   NSOpenGLContext* aGLCtxShare = theShareCtx.IsNull() ? NULL : (NSOpenGLContext* )theShareCtx->myGContext;
63   NSOpenGLContext* aGLContext  = NULL;
64
65   NSOpenGLPixelFormatAttribute anAttribs[32] = {};
66   Standard_Integer aLastAttrib = 0;
67   //anAttribs[aLastAttrib++] = NSOpenGLPFAColorSize;    anAttribs[aLastAttrib++] = 32,
68   anAttribs[aLastAttrib++] = NSOpenGLPFADepthSize;    anAttribs[aLastAttrib++] = 24;
69   anAttribs[aLastAttrib++] = NSOpenGLPFAStencilSize;  anAttribs[aLastAttrib++] = 8;
70   anAttribs[aLastAttrib++] = NSOpenGLPFADoubleBuffer;
71   if (theCaps->contextNoAccel)
72   {
73     anAttribs[aLastAttrib++] = NSOpenGLPFARendererID;
74     anAttribs[aLastAttrib++] = (NSOpenGLPixelFormatAttribute )kCGLRendererGenericFloatID;
75   }
76   else
77   {
78     anAttribs[aLastAttrib++] = NSOpenGLPFAAccelerated;
79   }
80   anAttribs[aLastAttrib] = 0;
81   const Standard_Integer aLastMainAttrib = aLastAttrib;
82   Standard_Integer aTryCore   = 0;
83   Standard_Integer aTryStereo = 0;
84   for (aTryCore = 1; aTryCore >= 0; --aTryCore)
85   {
86     aLastAttrib = aLastMainAttrib;
87     if (aTryCore == 1)
88     {
89       if (theCaps->contextCompatible)
90       {
91         continue;
92       }
93
94       // supported since OS X 10.7+
95       anAttribs[aLastAttrib++] = 99;     // NSOpenGLPFAOpenGLProfile
96       anAttribs[aLastAttrib++] = 0x3200; // NSOpenGLProfileVersion3_2Core
97     }
98
99     for (aTryStereo = 1; aTryStereo >= 0; --aTryStereo)
100     {
101       if (aTryStereo == 1)
102       {
103         if (!theCaps->contextStereo)
104         {
105           continue;
106         }
107         anAttribs[aLastAttrib++] = NSOpenGLPFAStereo;
108       }
109
110       anAttribs[aLastAttrib] = 0;
111
112       NSOpenGLPixelFormat* aGLFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes: anAttribs] autorelease];
113       aGLContext = [[NSOpenGLContext alloc] initWithFormat: aGLFormat
114                                               shareContext: aGLCtxShare];
115       if (aGLContext != NULL)
116       {
117         break;
118       }
119     }
120
121     if (aGLContext != NULL)
122     {
123       break;
124     }
125   }
126
127   if (aGLContext == NULL)
128   {
129     TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: NSOpenGLContext creation failed");
130     Aspect_GraphicDeviceDefinitionError::Raise (aMsg.ToCString());
131     return;
132   }
133
134   if (aTryStereo == 0
135    && theCaps->contextStereo)
136   {
137     TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: QuadBuffer is unavailable!");
138     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
139   }
140   if (aTryCore == 0
141   && !theCaps->contextCompatible)
142   {
143     TCollection_ExtendedString aMsg("OpenGl_Window::CreateWindow: core profile creation failed.");
144     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
145   }
146
147   NSView* aView = (NSView* )theCWindow.XWindow;
148   [aGLContext setView: aView];
149
150   myGlContext->Init (aGLContext, aTryCore == 1);
151   myGlContext->Share (theShareCtx);
152   Init();
153 }
154
155 // =======================================================================
156 // function : ~OpenGl_Window
157 // purpose  :
158 // =======================================================================
159 OpenGl_Window::~OpenGl_Window()
160 {
161   NSOpenGLContext* aGLCtx = (NSOpenGLContext* )myGlContext->myGContext;
162   myGlContext.Nullify();
163
164   [NSOpenGLContext clearCurrentContext];
165   if (myOwnGContext)
166   {
167     [aGLCtx clearDrawable];
168     [aGLCtx release];
169   }
170 }
171
172 // =======================================================================
173 // function : Resize
174 // purpose  : call_subr_resize
175 // =======================================================================
176 void OpenGl_Window::Resize (const CALL_DEF_WINDOW& theCWindow)
177 {
178   // If the size is not changed - do nothing
179   if (myWidth  == (Standard_Integer )theCWindow.dx
180    && myHeight == (Standard_Integer )theCWindow.dy)
181   {
182     return;
183   }
184
185   myWidth  = (Standard_Integer )theCWindow.dx;
186   myHeight = (Standard_Integer )theCWindow.dy;
187
188   Init();
189 }
190
191 // =======================================================================
192 // function : Init
193 // purpose  :
194 // =======================================================================
195 void OpenGl_Window::Init()
196 {
197   if (!Activate())
198   {
199     return;
200   }
201
202   NSOpenGLContext* aGLCtx = (NSOpenGLContext* )myGlContext->myGContext;
203   NSRect aBounds = [[aGLCtx view] bounds];
204
205   // we should call this method each time when window is resized
206   [aGLCtx update];
207
208   myWidth  = Standard_Integer(aBounds.size.width);
209   myHeight = Standard_Integer(aBounds.size.height);
210
211   glMatrixMode (GL_MODELVIEW);
212   glViewport (0, 0, myWidth, myHeight);
213
214   glDisable (GL_SCISSOR_TEST);
215   glDrawBuffer (GL_BACK);
216 }
217
218 #endif // __APPLE__