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