GRASS 8 Programmer's Manual 8.6.0dev(2026)-fc1694ea64
Loading...
Searching...
No Matches
nviz/render.c
Go to the documentation of this file.
1/*!
2 \file lib/nviz/render.c
3
4 \brief Nviz library -- GLX context manipulation
5
6 Based on visualization/nviz/src/togl.c
7
8 (C) 2008, 2010, 2018 by the GRASS Development Team
9 This program is free software under the GNU General Public License
10 (>=v2). Read the file COPYING that comes with GRASS for details.
11
12 \author Updated/modified by Martin Landa <landa.martin gmail.com> (Google SoC
13 2008/2010)
14 \author Support for framebuffer objects by Huidae Cho <grass4u gmail.com>
15 (July 2018)
16 */
17
18#include <grass/glocale.h>
19#include <grass/nviz.h>
20
21#if defined(OPENGL_WINDOWS) && defined(OPENGL_FBO)
22static int gl_funcs_found = 0;
30
31/* https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions */
32static void *GetAnyGLFuncAddress(const char *name)
33{
34 void *p = (void *)wglGetProcAddress(name);
35
36 if (p == 0 || p == (void *)0x1 || p == (void *)0x2 || p == (void *)0x3 ||
37 p == (void *)-1) {
38 HMODULE module = LoadLibraryA("opengl32.dll");
39
40 p = (void *)GetProcAddress(module, name);
41 }
42 if (!p)
43 G_fatal_error(_("Unable to get function address for %s"), name);
44 return p;
45}
46
47static void find_gl_funcs()
48{
50 return;
51
61 "glRenderbufferStorage");
64 "glFramebufferRenderbuffer");
67 "glCheckFramebufferStatus");
68
70}
71#endif
72
73/*!
74 \brief Allocate memory for render window
75
76 \return pointer to render_window struct
77 \return NULL on failure
78 */
80{
81 struct render_window *rwin;
82
83 /* G_malloc() calls G_fatal_error() on failure */
84 rwin = (struct render_window *)G_malloc(sizeof(struct render_window));
85
86 return rwin;
87}
88
89/*!
90 \brief Initialize render window
91
92 \param rwin pointer to render_window struct
93 */
95{
96#if defined(OPENGL_X11)
97 rwin->displayId = NULL;
98 rwin->contextId = NULL;
99 rwin->pixmap = 0;
100 rwin->windowId = 0;
101#elif defined(OPENGL_AQUA)
102#if defined(OPENGL_AGL)
103 rwin->pixelFmtId = NULL;
104 rwin->contextId = NULL;
105 rwin->windowId = NULL;
106#else
107 rwin->contextId = NULL;
108#endif
109#elif defined(OPENGL_WINDOWS)
110 rwin->displayId = NULL;
111 rwin->contextId = NULL;
112#endif
113
114 rwin->width = 0;
115 rwin->height = 0;
116}
117
118/*!
119 \brief Free render window
120
121 \param win pointer to render_window struct
122 */
124{
125#if defined(OPENGL_X11)
126 glXDestroyGLXPixmap(rwin->displayId, rwin->windowId);
127 XFreePixmap(rwin->displayId, rwin->pixmap);
128 glXDestroyContext(rwin->displayId, rwin->contextId);
129 XCloseDisplay(rwin->displayId);
130#elif defined(OPENGL_AQUA)
131#if defined(OPENGL_AGL)
132 aglDestroyPixelFormat(rwin->pixelFmtId);
133 aglDestroyContext(rwin->contextId);
134 aglDestroyPBuffer(rwin->windowId);
135#else
136 CGLDestroyContext(rwin->contextId);
137#endif
138#elif defined(OPENGL_WINDOWS)
139 wglDeleteContext(rwin->contextId);
140 DeleteDC(rwin->displayId);
141#endif
142
143 G_free((void *)rwin);
144}
145
146/*!
147 \brief Create render window
148
149 \param rwin pointer to render_window struct
150 \param display display instance (NULL for offscreen) [unused]
151 \param width window width
152 \param height window height
153
154 \return 0 on success
155 \return -1 on error
156 */
158 int width, int height)
159{
160#if defined(OPENGL_X11)
161 int attributeList[] = {GLX_RGBA,
163 1,
165 1,
167 1,
169 1,
170#if !defined(OPENGL_FBO)
172#endif
173 None};
174 XVisualInfo *v;
175
176 rwin->displayId = XOpenDisplay((char *)display);
177 if (!rwin->displayId) {
178 G_fatal_error(_("Bad server connection"));
179 }
180
181 v = glXChooseVisual(rwin->displayId, DefaultScreen(rwin->displayId),
183 if (!v) {
184 G_warning(_("Unable to get visual info"));
185 return -1;
186 }
187
188 rwin->contextId = glXCreateContext(rwin->displayId, v, NULL, GL_TRUE);
189
190 if (!rwin->contextId) {
191 G_warning(_("Unable to create rendering context"));
192 return -1;
193 }
194
195 /* create win pixmap to render to (same depth as RootWindow) */
196 rwin->pixmap =
197 XCreatePixmap(rwin->displayId, RootWindow(rwin->displayId, v->screen),
198 width, height, v->depth);
199
200 /* create an off-screen GLX rendering area */
201 rwin->windowId = glXCreateGLXPixmap(rwin->displayId, v, rwin->pixmap);
202
203 XFree(v);
204#elif defined(OPENGL_AQUA)
205#if defined(OPENGL_AGL)
206 int attributeList[] = {AGL_RGBA,
208 1,
210 1,
212 1,
214 1,
215#if !defined(OPENGL_FBO)
217#endif
218 AGL_NONE};
219
220 /* TODO: open mac display */
221
222 /* TODO: dev = NULL, ndev = 0 ? */
223 rwin->pixelFmtId = aglChoosePixelFormat(NULL, 0, attributeList);
224
225 rwin->contextId = aglCreateContext(rwin->pixelFmtId, NULL);
226
227 /* create an off-screen AGL rendering area */
229 &(rwin->windowId));
230 aglSetPBuffer(rwin->contextId, rwin->windowId, 0, 0, 0);
231#else
235 GLint nvirt;
237
239 if (error) {
240 G_warning(_("Unable to choose pixel format (CGL error = %d)"), error);
241 return -1;
242 }
243
244 error = CGLCreateContext(pix, NULL, &rwin->contextId);
245 if (error) {
246 G_warning(_("Unable to create context (CGL error = %d)"), error);
247 return -1;
248 }
249
251#endif
252#elif defined(OPENGL_WINDOWS)
253 WNDCLASS wc = {0};
254 HWND hWnd;
255
257 sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
258 1, /* version number */
259 PFD_DRAW_TO_WINDOW | /* support window */
260 PFD_SUPPORT_OPENGL | /* support OpenGL */
261 PFD_DOUBLEBUFFER, /* double buffered */
262 PFD_TYPE_RGBA, /* RGBA type */
263 24, /* 24-bit color depth */
264 0,
265 0,
266 0,
267 0,
268 0,
269 0, /* color bits ignored */
270 0, /* no alpha buffer */
271 0, /* shift bit ignored */
272 0, /* no accumulation buffer */
273 0,
274 0,
275 0,
276 0, /* accum bits ignored */
277 32, /* 32-bit z-buffer */
278 0, /* no stencil buffer */
279 0, /* no auxiliary buffer */
280 PFD_MAIN_PLANE, /* main layer */
281 0, /* reserved */
282 0,
283 0,
284 0 /* layer masks ignored */
285 };
286 int iPixelFormat;
287
288 wc.lpfnWndProc = DefWindowProc;
289 wc.lpszClassName = "nviz";
290
291 if (!RegisterClass(&wc)) {
292 G_warning(_("Unable to register window class"));
293 return -1;
294 }
295
296 hWnd = CreateWindow(wc.lpszClassName, wc.lpszClassName, WS_POPUP,
298 wc.hInstance, NULL);
299
300 if (!hWnd) {
301 G_warning(_("Unable to create window"));
302 return -1;
303 }
304
305 rwin->displayId = GetDC(hWnd);
306 iPixelFormat = ChoosePixelFormat(rwin->displayId, &pfd);
307 SetPixelFormat(rwin->displayId, iPixelFormat, &pfd);
308 rwin->contextId = wglCreateContext(rwin->displayId);
309#endif
310
311 rwin->width = width;
312 rwin->height = height;
313
314 return 0;
315}
316
317/*!
318 \brief Make window current for rendering
319
320 \param rwin pointer to render_window struct
321
322 \return 1 on success
323 \return 0 on failure
324 */
326{
327#if defined(OPENGL_X11)
328 if (!rwin->displayId || !rwin->contextId)
329 return 0;
330
331 if (rwin->contextId == glXGetCurrentContext())
332 return 1;
333
334 glXMakeCurrent(rwin->displayId, rwin->windowId, rwin->contextId);
335#elif defined(OPENGL_AQUA)
336#if defined(OPENGL_AGL)
337 if (!rwin->contextId)
338 return 0;
339
340 if (rwin->contextId == aglGetCurrentContext())
341 return 1;
342
343 aglSetCurrentContext(rwin->contextId);
344#else
346
347 error = CGLSetCurrentContext(rwin->contextId);
348 if (error) {
349 G_warning(_("Unable to set current context (CGL error = %d)"), error);
350 return 0;
351 }
352#endif
353#elif defined(OPENGL_WINDOWS)
354 if (!rwin->displayId || !rwin->contextId)
355 return 0;
356
357 wglMakeCurrent(rwin->displayId, rwin->contextId);
358#endif
359
360#if defined(OPENGL_FBO)
361#if defined(OPENGL_WINDOWS)
363#endif
364
366 GLenum status;
367
370
376
380 rwin->height);
383
385 if (status != GL_FRAMEBUFFER_COMPLETE) {
386 G_warning(_("Incomplete framebuffer status (status = %d)"), status);
387 return 0;
388 }
389#endif
390
391 glViewport(0, 0, rwin->width, rwin->height);
392
393 return 1;
394}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:139
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition gis.h:46
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
struct render_window * Nviz_new_render_window(void)
Allocate memory for render window.
Definition nviz/render.c:79
void Nviz_destroy_render_window(struct render_window *rwin)
Free render window.
void Nviz_init_render_window(struct render_window *rwin)
Initialize render window.
Definition nviz/render.c:94
int Nviz_create_render_window(struct render_window *rwin, void *display, int width, int height)
Create render window.
int Nviz_make_current_render_window(const struct render_window *rwin)
Make window current for rendering.
int height
Definition nviz.h:144
int width
Definition nviz.h:144