Ghost Context Refactor
[blender-staging.git] / intern / ghost / intern / GHOST_ContextSDL.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2014 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Jason Wilkins
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file ghost/intern/GHOST_ContextSDL.cpp
29  *  \ingroup GHOST
30  *
31  * Definition of GHOST_ContextSDL class.
32  */
33
34 #include "GHOST_ContextSDL.h"
35
36 #include <vector>
37
38 #include <cassert>
39 #include <cstdio>
40 #include <cstring>
41
42
43 SDL_GLContext GHOST_ContextSDL::s_sharedContext = NULL;
44 int           GHOST_ContextSDL::s_sharedCount   = 0;
45
46
47 GHOST_ContextSDL::GHOST_ContextSDL(
48         bool stereoVisual,
49         GHOST_TUns16 numOfAASamples,
50         SDL_Window *window,
51         int contextProfileMask,
52         int contextMajorVersion,
53         int contextMinorVersion,
54         int contextFlags,
55         int contextResetNotificationStrategy)
56     : GHOST_Context(stereoVisual, numOfAASamples),
57       m_window(window),
58       m_contextProfileMask(contextProfileMask),
59       m_contextMajorVersion(contextMajorVersion),
60       m_contextMinorVersion(contextMinorVersion),
61       m_contextFlags(contextFlags),
62       m_contextResetNotificationStrategy(contextResetNotificationStrategy),
63       m_context(NULL)
64 {
65         assert(m_window  != NULL);
66 }
67
68
69 GHOST_ContextSDL::~GHOST_ContextSDL()
70 {
71         if (m_context != NULL) {
72                 if (m_window != 0 && m_context == SDL_GL_GetCurrentContext())
73                         SDL_GL_MakeCurrent(m_window, m_context);
74
75                 if (m_context != s_sharedContext || s_sharedCount == 1) {
76                         assert(s_sharedCount > 0);
77
78                         s_sharedCount--;
79
80                         if (s_sharedCount == 0)
81                                 s_sharedContext = NULL;
82
83                         SDL_GL_DeleteContext(m_context);
84                 }
85         }
86 }
87
88
89 GHOST_TSuccess GHOST_ContextSDL::swapBuffers()
90 {
91         SDL_GL_SwapWindow(m_window);
92
93         return GHOST_kSuccess;
94 }
95
96
97 GHOST_TSuccess GHOST_ContextSDL::activateDrawingContext()
98 {
99         if (m_context) {
100                 activateGLEW();
101
102                 return SDL_GL_MakeCurrent(m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
103         }
104         else {
105                 return GHOST_kFailure;
106         }
107 }
108
109
110 GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
111 {
112 #ifdef GHOST_OPENGL_ALPHA
113         const bool needAlpha   = true;
114 #else
115         const bool needAlpha   = false;
116 #endif
117
118 #ifdef GHOST_OPENGL_STENCIL
119         const bool needStencil = true;
120 #else
121         const bool needStencil = false;
122 #endif
123
124         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, m_contextProfileMask);
125         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, m_contextMajorVersion);
126         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, m_contextMinorVersion);
127         SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, m_contextFlags);
128
129         SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
130         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
131         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
132         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
133         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
134         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
135
136         if (needAlpha) {
137                 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
138         }
139
140         if (needStencil) {
141                 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
142         }
143
144         if (m_stereoVisual) {
145                 SDL_GL_SetAttribute(SDL_GL_STEREO, 1);
146         }
147
148         if (m_numOfAASamples) {
149                 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
150                 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, m_numOfAASamples);
151         }
152
153         m_context = SDL_GL_CreateContext(m_window);
154
155         GHOST_TSuccess success;
156
157         if (m_context != NULL) {
158                 if (!s_sharedContext)
159                         s_sharedContext = m_context;
160
161                 s_sharedCount++;
162
163                 success = (SDL_GL_MakeCurrent(m_window, m_context) < 0) ?
164                            GHOST_kFailure : GHOST_kSuccess;
165
166                 initContextGLEW();
167
168                 initClearGL();
169                 SDL_GL_SwapWindow(m_window);
170
171                 success = GHOST_kSuccess;
172         }
173         else {
174                 success = GHOST_kFailure;
175         }
176
177         return success;
178 }
179
180
181 GHOST_TSuccess GHOST_ContextSDL::releaseNativeHandles()
182 {
183         m_window = NULL;
184
185         return GHOST_kSuccess;
186 }
187
188
189 GHOST_TSuccess GHOST_ContextSDL::setSwapInterval(int interval)
190 {
191         if (SDL_GL_SetSwapInterval(interval) != -1) {
192                 return GHOST_kSuccess;
193         }
194         else {
195                 return GHOST_kFailure;
196         }
197 }
198
199
200 GHOST_TSuccess GHOST_ContextSDL::getSwapInterval(int &intervalOut)
201 {
202         intervalOut = SDL_GL_GetSwapInterval();
203         return GHOST_kSuccess;
204 }