28 #include "ascension/window.h" |
28 #include "ascension/window.h" |
29 #include "ascension/context.h" |
29 #include "ascension/context.h" |
30 #include "ascension/error.h" |
30 #include "ascension/error.h" |
31 #include "ascension/utils.h" |
31 #include "ascension/utils.h" |
32 |
32 |
33 #include <cx/printf.h> |
|
34 |
|
35 #include <GL/glew.h> |
33 #include <GL/glew.h> |
36 |
34 |
37 static void asc_gl_debug_callback( |
|
38 GLenum source, GLenum type, GLuint id, GLenum severity, |
|
39 GLsizei length, const GLchar* message, |
|
40 const void* userParam |
|
41 ) { |
|
42 cxmutstr buf = cx_asprintf( |
|
43 "source = %d, id = %u, type = %d, severity= %d, message = %.*s", |
|
44 source, id, type, severity, length, message); |
|
45 if (type == GL_DEBUG_TYPE_ERROR) { |
|
46 asc_error(buf.ptr); |
|
47 } else { |
|
48 asc_dprintf("GL debug: %.*s", (int)buf.length, buf.ptr); |
|
49 } |
|
50 cx_strfree(&buf); |
|
51 } |
|
52 |
|
53 void asc_window_settings_init_defaults(AscWindowSettings* settings) { |
35 void asc_window_settings_init_defaults(AscWindowSettings* settings) { |
54 settings->depth_size = 24; |
|
55 settings->vsync = 1; |
|
56 settings->dimensions.width = 800; |
36 settings->dimensions.width = 800; |
57 settings->dimensions.height = 600; |
37 settings->dimensions.height = 600; |
58 settings->fullscreen = 0; |
38 settings->fullscreen = 0; |
59 settings->gl_major_version = 4; |
39 settings->glsettings.depth_size = 24; |
60 settings->gl_minor_version = 0; |
40 settings->glsettings.vsync = 1; |
|
41 settings->glsettings.gl_major_version = 4; |
|
42 settings->glsettings.gl_minor_version = 0; |
61 settings->title = "Ascended Window"; |
43 settings->title = "Ascended Window"; |
62 } |
44 } |
63 |
45 |
64 static void asc_window_init_scenes(AscWindow *window) { |
46 static void asc_window_init_scenes(AscWindow *window) { |
65 asc_scene_init(&window->ui); |
47 asc_scene_init(&window->ui); |
101 &window->dimensions.width, |
83 &window->dimensions.width, |
102 &window->dimensions.height |
84 &window->dimensions.height |
103 ); |
85 ); |
104 window->resized = true; // count initial sizing as resize |
86 window->resized = true; // count initial sizing as resize |
105 |
87 |
106 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); |
88 if (asc_gl_context_initialize(&window->glctx, window->window, &settings->glsettings)) { |
107 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, settings->gl_major_version); |
89 asc_dprintf("Window %u initialized", window->id); |
108 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, settings->gl_minor_version); |
90 asc_context.active_window = window; |
109 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, settings->depth_size); |
91 asc_window_init_scenes(window); |
110 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
92 return window; |
111 window->glctx = SDL_GL_CreateContext(window->window); |
93 } else { |
112 if (window->glctx == NULL) { |
|
113 asc_dprintf("Creating GL context failed for window %u", window->id); |
94 asc_dprintf("Creating GL context failed for window %u", window->id); |
114 } else { |
95 // cleanup on error |
115 glewExperimental = GL_TRUE; |
96 SDL_DestroyWindow(window->window); |
116 GLenum err = glewInit(); |
97 window->window = NULL; |
117 if (err == GLEW_OK) { |
98 window->id = 0; |
118 SDL_GL_SetSwapInterval(settings->vsync); |
99 return NULL; |
119 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |
|
120 glEnable(GL_DEBUG_OUTPUT); |
|
121 glDebugMessageCallback(asc_gl_debug_callback, NULL); |
|
122 |
|
123 asc_dprintf("Window %u initialized", window->id); |
|
124 if (asc_primitives_init(&window->primitives)) { |
|
125 asc_context.active_window = window; |
|
126 asc_window_init_scenes(window); |
|
127 return window; |
|
128 } else { |
|
129 asc_dprintf("!!! Creating primitives for window %u failed !!!", window->id); |
|
130 } |
|
131 } else { |
|
132 asc_error(glewGetErrorString(err)); |
|
133 } |
|
134 } |
100 } |
135 |
|
136 // cleanup on error |
|
137 if (window->glctx != NULL) { |
|
138 SDL_GL_DeleteContext(window->glctx); |
|
139 } |
|
140 window->glctx = NULL; |
|
141 SDL_DestroyWindow(window->window); |
|
142 window->window = NULL; |
|
143 window->id = 0; |
|
144 } |
101 } |
145 |
102 |
146 void asc_window_destroy(AscWindow* window) { |
103 void asc_window_destroy(AscWindow* window) { |
147 // safeguard |
104 // safeguard |
148 if (window->id == 0) return; |
105 if (window->id == 0) return; |
153 } |
110 } |
154 |
111 |
155 // destroy all scenes |
112 // destroy all scenes |
156 asc_scene_destroy(&window->ui); |
113 asc_scene_destroy(&window->ui); |
157 |
114 |
158 // release context related data (we have to make the GL context current for this) |
115 // release context related data |
159 SDL_GL_MakeCurrent(window->window, window->glctx); |
116 asc_gl_context_destroy(&window->glctx); |
160 asc_primitives_destroy(&window->primitives); |
|
161 |
117 |
162 // destroy the GL context and the window |
118 // destroy window |
163 if (window->glctx != NULL) { |
|
164 SDL_GL_DeleteContext(window->glctx); |
|
165 } |
|
166 if (window->window != NULL) { |
119 if (window->window != NULL) { |
167 SDL_DestroyWindow(window->window); |
120 SDL_DestroyWindow(window->window); |
168 } |
121 } |
169 |
122 |
170 // if another window was active, make the other context current again |
123 // if another window was active, make the other context current again |
171 if (asc_context.active_window != NULL) { |
124 if (asc_context.active_window != NULL) { |
172 AscWindow const *aw = asc_context.active_window; |
125 asc_gl_context_activate(&asc_context.active_window->glctx); |
173 SDL_GL_MakeCurrent(aw->window, aw->glctx); |
|
174 } |
126 } |
175 |
127 |
176 // clean the data |
128 // clean the data |
177 asc_dprintf("Window %u and its OpenGL context destroyed.", window->id); |
129 asc_dprintf("Window %u and its OpenGL context destroyed.", window->id); |
178 memset(window, 0, sizeof(AscWindow)); |
130 memset(window, 0, sizeof(AscWindow)); |
179 } |
131 } |
180 |
132 |
181 void asc_window_sync(AscWindow* window) { |
133 void asc_window_sync(AscWindow* window) { |
182 AscWindow const *active_window = asc_context.active_window; |
134 AscWindow *active_window = asc_context.active_window; |
183 if (window != active_window) { |
135 if (window != active_window) { |
184 asc_window_activate(window); |
136 asc_window_activate(window); |
185 } |
137 } |
186 |
138 |
187 // Draw the UI |
139 // Draw the UI |
196 if (window != active_window) { |
148 if (window != active_window) { |
197 asc_window_activate(active_window); |
149 asc_window_activate(active_window); |
198 } |
150 } |
199 } |
151 } |
200 |
152 |
201 void asc_window_activate(AscWindow const *window) { |
153 void asc_window_activate(AscWindow *window) { |
202 SDL_GL_MakeCurrent(window->window, window->glctx); |
154 asc_gl_context_activate(&window->glctx); |
203 asc_context.active_window = (AscWindow *)window; |
155 asc_context.active_window = (AscWindow *)window; |
204 } |
156 } |