UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
win32_gl_common.c
Go to the documentation of this file.
1
9/*
10 * Copyright (c) 2013-2014 CESNET z.s.p.o.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, is permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * 3. Neither the name of CESNET nor the names of its contributors may be
25 * used to endorse or promote products derived from this software without
26 * specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
30 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
31 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
32 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
38 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42#ifdef HAVE_CONFIG_H
43#include "config.h"
44#include "config_unix.h"
45#include "config_win32.h"
46#endif
47
48#include <assert.h>
49#include <GL/glew.h>
50#include <GL/wglew.h>
51#include <wingdi.h>
52#include <winuser.h>
53
54#include "debug.h"
55#include "utils/windows.h"
56#include "win32_gl_common.h"
57
58#define VERSION_GET_MAJOR(version) (version >> 8u)
59#define VERSION_GET_MINOR(version) (version & 0xFF)
60#define VERSION_IS_UNSPECIFIED(version) (!version)
61#define VERSION_IS_LEGACY(version) (version == OPENGL_VERSION_LEGACY)
62
63#define WNDCLASSNAME "GLClass"
64
65pthread_once_t register_windows_class_once = PTHREAD_ONCE_INIT;
66
72
74{
75 HWND win;
76 HDC hdc;
77 HGLRC hglrc;
79 pthread_mutex_t lock;
80 pthread_cond_t status_cv;
81 pthread_t thread_id;
84 pthread_cond_t loop_cv;
85};
86
87static HWND CreateWnd (int width, int height);
88static BOOL SetGLFormat(HDC hdc);
89static void PrintError(DWORD err);
90static void create_and_register_windows_class(void);
92 *context);
93
94static void *owner_thread(void *arg) {
95 struct state_win32_gl_context *context =
96 (struct state_win32_gl_context *) arg;
97
98 context->win = CreateWnd(512, 512);
99 assert(context->win != NULL);
100
101 if ((context->hdc = GetDC(context->win)) == NULL) // get device context
102 {
103 fprintf(stderr, "Failed to Get the Window Device Context\n");
104 goto failed;
105 }
106
107 if(!SetGLFormat(context->hdc)) {
108 fprintf(stderr, "Unable to set pixel format.\n");
109 goto failed;
110 }
111
112 if ((context->hglrc = wglCreateContext(context->hdc)) == NULL) // create the rendering context
113 {
114 fprintf(stderr, "Failed to Create the OpenGL Rendering Context.\n");
115 goto release_context;
116 }
117
118 if(wglMakeCurrent(context->hdc, context->hglrc) == FALSE) {
119 fprintf(stderr, "Unable to make context current.\n");
120 PrintError(GetLastError());
121 goto release_context;
122 }
123
124 int err = glewInit();
125 if(err != GLEW_OK) {
126 fprintf(stderr, "Error intializing GLEW.\n");
127 goto release_context;
128 }
129
130 if(!VERSION_IS_UNSPECIFIED(context->version) &&
131 !VERSION_IS_LEGACY(context->version)) {
132 if(glewIsSupported("GL_ARB_create_context_profile") != GLEW_OK) {
133 fprintf(stderr, "OpenGL implementation is not capable "
134 "of selecting profile.\n");
135 goto release_context;
136 } else {
137 // first destroy current context
138 wglMakeCurrent(context->hdc, NULL);
139 wglDeleteContext(context->hglrc);
140
141 const int attrib_list[] = {
142 WGL_CONTEXT_MAJOR_VERSION_ARB, VERSION_GET_MAJOR(context->version),
143 WGL_CONTEXT_MINOR_VERSION_ARB, VERSION_GET_MINOR(context->version),
144 0
145 };
146
147 if ((context->hglrc = wglCreateContextAttribsARB(context->hdc, NULL, attrib_list)) == NULL)
148 {
149 fprintf(stderr, "Failed to Create the OpenGL Rendering Context %d,%d.\n",
150 VERSION_GET_MAJOR(context->version),
151 VERSION_GET_MINOR(context->version));
152 goto release_context;
153 }
154 }
155 }
156
157
158 //ShowWindow(context->win, SW_SHOW);
159 //UpdateWindow(context->win);
160 wglMakeCurrent(context->hdc, NULL);
161
162 pthread_mutex_lock(&context->lock);
163 context->status = SUCCESS;
164 pthread_cond_signal(&context->status_cv);
165 pthread_mutex_unlock(&context->lock);
166
167 pthread_mutex_lock(&context->lock);
168 while (!context->should_exit)
169 pthread_cond_wait(&context->loop_cv, &context->lock);
170 pthread_mutex_unlock(&context->lock);
171
172 wglMakeCurrent(context->hdc, NULL);
173 wglDeleteContext(context->hglrc);
174
175 PostQuitMessage(0);
176
177 return NULL;
178
179release_context:
180 wglMakeCurrent(context->hdc, NULL);
181 wglDeleteContext(context->hglrc);
182
183failed:
184 PostQuitMessage(0);
185 pthread_mutex_lock(&context->lock);
186 context->status = FAILED;
187 pthread_cond_signal(&context->status_cv);
188 pthread_mutex_unlock(&context->lock);
189
190 return NULL;
191}
192
193static void PrintError(DWORD err)
194{
195 // Display the error message and exit the process
196 log_msg(LOG_LEVEL_FATAL, "win32_gl_common %ld: %s\n", err,
197 get_win32_error(err));
198}
199
200static BOOL SetGLFormat(HDC hdc)
201{
202 // number of available formats
203 int indexPixelFormat = 0;
204
205 PIXELFORMATDESCRIPTOR pfd =
206 {
207 sizeof(PIXELFORMATDESCRIPTOR),
208 1,
209 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,
210 PFD_TYPE_RGBA,
211 32,
212 0,0,0,0,0,0,0,0,0,0,0,0,0, // useles parameters
213 16,
214 0,0,0,0,0,0,0
215 };
216
217 // Choose the closest pixel format available
218 indexPixelFormat = ChoosePixelFormat(hdc, &pfd);
219
220 // Set the pixel format for the provided window DC
221 return SetPixelFormat(hdc, indexPixelFormat, &pfd);// number of available formats
222}
223
225{
226 WNDCLASSEX ex;
227
228 ex.cbSize = sizeof(WNDCLASSEX);
229 ex.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
230 ex.lpfnWndProc = DefWindowProc;
231 ex.cbClsExtra = 0;
232 ex.cbWndExtra = 0;
233 ex.hInstance = NULL;
234 ex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
235 ex.hCursor = LoadCursor(NULL, IDC_ARROW);
236 ex.hbrBackground = NULL;
237 ex.lpszMenuName = NULL;
238 ex.lpszClassName = WNDCLASSNAME;
239 ex.hIconSm = NULL;
240
241 ATOM res = RegisterClassEx(&ex);
242 if (res == 0) {
243 PrintError(GetLastError());
244 abort();
245 }
246}
247
248static HWND CreateWnd (int width, int height)
249{
250 HWND win;
251 // center position of the window
252 int posx = (GetSystemMetrics(SM_CXSCREEN) / 2) - (width / 2);
253 int posy = (GetSystemMetrics(SM_CYSCREEN) / 2) - (height / 2);
254
255 // set up the window for a windowed application by default
256 long wndStyle = WS_OVERLAPPEDWINDOW;
257
258 // create the window
259 win = CreateWindowEx(0,
261 "OpenGL Context Window",
262 wndStyle|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
263 posx, posy,
264 width, height,
265 NULL,
266 NULL,
267 NULL,
268 NULL);
269
270 if(!win) {
271 PrintError(GetLastError());
272 }
273
274 // at this point WM_CREATE message is sent/received
275 // the WM_CREATE branch inside WinProc function will execute here
276 return win;
277}
278
280{
281 struct state_win32_gl_context *context;
282
283 context = calloc(1, sizeof(struct state_win32_gl_context));
284 if(!context) {
285 fprintf(stderr, "Unable to allocate memory.\n");
286 return NULL;
287 }
288 context->version = version;
289 context->status = UNKNOWN;
290
291 pthread_once(&register_windows_class_once,
293
294 pthread_mutex_init(&context->lock, NULL);
295 pthread_cond_init(&context->status_cv, NULL);
296 pthread_cond_init(&context->loop_cv, NULL);
297 pthread_create(&context->thread_id, NULL, owner_thread, context);
298
299 pthread_mutex_lock(&context->lock);
300 while (context->status == UNKNOWN) {
301 pthread_cond_wait(&context->status_cv, &context->lock);
302 }
303 pthread_mutex_unlock(&context->lock);
304
305 if (context->status == FAILED) {
306 pthread_join(context->thread_id, NULL);
308 return NULL;
309 }
310
311 wglMakeCurrent(context->hdc, context->hglrc);
312
313 return context;
314}
315
317{
318 struct state_win32_gl_context *context = arg;
319 BOOL ret;
320
321 if(!arg) {
322 ret = wglMakeCurrent(NULL, NULL);
323 } else {
324 ret = wglMakeCurrent(context->hdc, context->hglrc);
325 }
326 if(ret == FALSE) {
327 fprintf(stderr, "Warning: wglMakeCurrent did not succeeded!\n");
328 PrintError(GetLastError());
329 }
330}
331
333 *context)
334{
335 pthread_mutex_destroy(&context->lock);
336 pthread_cond_destroy(&context->status_cv);
337 pthread_cond_destroy(&context->loop_cv);
338
339 free(context);
340}
341
342void win32_context_free(void *arg)
343{
344 if(!arg)
345 return;
346
347 struct state_win32_gl_context *context = arg;
348
349 pthread_mutex_lock(&context->lock);
350 context->should_exit = true;
351 pthread_cond_signal(&context->loop_cv);
352 pthread_mutex_unlock(&context->lock);
353
354 pthread_join(context->thread_id, NULL);
356}
357
#define FALSE
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_FATAL
errors that prevent UG run
Definition debug.h:58
win32_opengl_version_t version
@ UNKNOWN
@ SUCCESS
@ FAILED
void win32_context_make_current(void *arg)
#define WNDCLASSNAME
static void * owner_thread(void *arg)
static void win32_context_cleanup_common(struct state_win32_gl_context *context)
#define VERSION_GET_MAJOR(version)
#define VERSION_GET_MINOR(version)
void win32_context_free(void *arg)
pthread_once_t register_windows_class_once
static void create_and_register_windows_class(void)
void * win32_context_init(win32_opengl_version_t version)
static BOOL SetGLFormat(HDC hdc)
static void PrintError(DWORD err)
#define VERSION_IS_UNSPECIFIED(version)
static HWND CreateWnd(int width, int height)
#define VERSION_IS_LEGACY(version)
uint32_t win32_opengl_version_t