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