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