[GRASS-SVN] r73010 - in grass/branches/releasebranch_7_4: include lib/nviz lib/ogsf
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Jul 27 20:37:07 PDT 2018
Author: hcho
Date: 2018-07-27 20:37:07 -0700 (Fri, 27 Jul 2018)
New Revision: 73010
Modified:
grass/branches/releasebranch_7_4/include/config.h.in
grass/branches/releasebranch_7_4/include/nviz.h
grass/branches/releasebranch_7_4/lib/nviz/render.c
grass/branches/releasebranch_7_4/lib/ogsf/gsd_prim.c
grass/branches/releasebranch_7_4/lib/ogsf/gsd_views.c
Log:
nviz, ogsf: Fix m.nviz.image (merge from trunk r73006, etc)
Modified: grass/branches/releasebranch_7_4/include/config.h.in
===================================================================
--- grass/branches/releasebranch_7_4/include/config.h.in 2018-07-27 08:33:51 UTC (rev 73009)
+++ grass/branches/releasebranch_7_4/include/config.h.in 2018-07-28 03:37:07 UTC (rev 73010)
@@ -306,4 +306,7 @@
/* define if langinfo.h exists */
#undef HAVE_LANGINFO_H
+/* Use framebuffer objects for off-screen OpenGL rendering */
+#define OPENGL_FBO 1
+
#endif /* _config_h */
Modified: grass/branches/releasebranch_7_4/include/nviz.h
===================================================================
--- grass/branches/releasebranch_7_4/include/nviz.h 2018-07-27 08:33:51 UTC (rev 73009)
+++ grass/branches/releasebranch_7_4/include/nviz.h 2018-07-28 03:37:07 UTC (rev 73010)
@@ -9,6 +9,8 @@
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
# include <winnt.h>
+# include <GL/gl.h>
+# include <GL/glext.h>
/*** X Window System headers ***/
#elif defined(OPENGL_X11)
@@ -15,13 +17,20 @@
# include <X11/Xlib.h>
# include <X11/Xutil.h>
# include <X11/Xatom.h> /* for XA_RGB_DEFAULT_MAP atom */
+# define GL_GLEXT_PROTOTYPES
# include <GL/glx.h>
/*** Mac headers ***/
#elif defined(OPENGL_AQUA)
-# define Cursor QDCursor
-# include <AGL/agl.h>
-# undef Cursor
+# if defined(OPENGL_AGL)
+# define Cursor QDCursor
+# include <AGL/agl.h>
+# undef Cursor
+# else
+# include <OpenGL/CGLTypes.h>
+# include <OpenGL/CGLCurrent.h>
+# include <OpenGL/OpenGL.h>
+# endif
# include <ApplicationServices/ApplicationServices.h>
#else /* make sure only one platform defined */
@@ -125,17 +134,21 @@
#if defined(OPENGL_X11)
Display *displayId; /* display connection */
GLXContext contextId; /* GLX rendering context */
+ Pixmap pixmap;
GLXPixmap windowId;
- Pixmap pixmap;
#elif defined(OPENGL_AQUA)
+#if defined(OPENGL_AGL)
AGLPixelFormat pixelFmtId;
AGLContext contextId;
AGLPbuffer windowId;
+#else
+ CGLContextObj contextId;
+#endif
#elif defined(OPENGL_WINDOWS)
HDC displayId; /* display context */
HGLRC contextId; /* rendering context */
- HBITMAP bitmapId;
#endif
+ int width, height;
};
#include <grass/defs/nviz.h>
Modified: grass/branches/releasebranch_7_4/lib/nviz/render.c
===================================================================
--- grass/branches/releasebranch_7_4/lib/nviz/render.c 2018-07-27 08:33:51 UTC (rev 73009)
+++ grass/branches/releasebranch_7_4/lib/nviz/render.c 2018-07-28 03:37:07 UTC (rev 73010)
@@ -4,17 +4,59 @@
\brief Nviz library -- GLX context manipulation
Based on visualization/nviz/src/togl.c
-
- (C) 2008, 2010 by the GRASS Development Team
+
+ (C) 2008, 2010, 2018 by the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.
\author Updated/modified by Martin Landa <landa.martin gmail.com> (Google SoC 2008/2010)
+ \author Support for framebuffer objects by Huidae Cho <grass4u gmail.com> (July 2018)
*/
#include <grass/glocale.h>
#include <grass/nviz.h>
+#if defined(OPENGL_WINDOWS) && defined(OPENGL_FBO)
+static int gl_funcs_found = 0;
+static PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
+static PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
+static PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
+static PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
+static PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
+static PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
+static PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
+
+/* https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions */
+static void *GetAnyGLFuncAddress(const char *name)
+{
+ void *p = (void *)wglGetProcAddress(name);
+ if (p == 0 || p == (void*)0x1 || p == (void*)0x2 || p == (void*)0x3 ||
+ p == (void*)-1) {
+ HMODULE module = LoadLibraryA("opengl32.dll");
+ p = (void *)GetProcAddress(module, name);
+ }
+ if (!p)
+ G_fatal_error(_("Unable to get function address for %s"), name);
+ return p;
+}
+
+static void find_gl_funcs()
+{
+ if (gl_funcs_found)
+ return;
+
+ glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)GetAnyGLFuncAddress("glGenFramebuffers");
+ glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)GetAnyGLFuncAddress("glBindFramebuffer");
+ glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)GetAnyGLFuncAddress("glGenRenderbuffers");
+ glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)GetAnyGLFuncAddress("glBindRenderbuffer");
+ glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)GetAnyGLFuncAddress("glRenderbufferStorage");
+ glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)GetAnyGLFuncAddress("glFramebufferRenderbuffer");
+ glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)GetAnyGLFuncAddress("glCheckFramebufferStatus");
+
+ gl_funcs_found = 1;
+}
+#endif
+
/*!
\brief Allocate memory for render window
@@ -44,14 +86,20 @@
rwin->pixmap = 0;
rwin->windowId = 0;
#elif defined(OPENGL_AQUA)
+#if defined(OPENGL_AGL)
rwin->pixelFmtId = NULL;
rwin->contextId = NULL;
rwin->windowId = NULL;
+#else
+ rwin->contextId = NULL;
+#endif
#elif defined(OPENGL_WINDOWS)
rwin->displayId = NULL;
rwin->contextId = NULL;
- rwin->bitmapId = NULL;
#endif
+
+ rwin->width = 0;
+ rwin->height = 0;
}
/*!
@@ -67,14 +115,16 @@
glXDestroyContext(rwin->displayId, rwin->contextId);
XCloseDisplay(rwin->displayId);
#elif defined(OPENGL_AQUA)
+#if defined(OPENGL_AGL)
aglDestroyPixelFormat(rwin->pixelFmtId);
aglDestroyContext(rwin->contextId);
aglDestroyPBuffer(rwin->windowId);
- /* TODO FreePixMap */
+#else
+ CGLDestroyContext(rwin->contextId);
+#endif
#elif defined(OPENGL_WINDOWS)
wglDeleteContext(rwin->contextId);
DeleteDC(rwin->displayId);
- DeleteObject(rwin->bitmapId);
#endif
G_free((void *)rwin);
@@ -95,9 +145,16 @@
int width, int height)
{
#if defined(OPENGL_X11)
- int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 1, None
+ int attributeList[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+#if !defined(OPENGL_FBO)
+ GLX_DOUBLEBUFFER,
+#endif
+ None
};
XVisualInfo *v;
@@ -112,7 +169,7 @@
G_warning(_("Unable to get visual info"));
return -1;
}
-
+
rwin->contextId = glXCreateContext(rwin->displayId, v, NULL, GL_TRUE);
if (!rwin->contextId) {
@@ -130,10 +187,19 @@
XFree(v);
#elif defined(OPENGL_AQUA)
- int attributeList[] = { AGL_RGBA, AGL_RED_SIZE, 1,
- AGL_GREEN_SIZE, 1, AGL_BLUE_SIZE, 1,
- AGL_DEPTH_SIZE, 1, AGL_NONE
+#if defined(OPENGL_AGL)
+ int attributeList[] = {
+ AGL_RGBA,
+ AGL_RED_SIZE, 1,
+ AGL_GREEN_SIZE, 1,
+ AGL_BLUE_SIZE, 1,
+ AGL_DEPTH_SIZE, 1,
+#if !defined(OPENGL_FBO)
+ AGL_DOUBLEBUFFER,
+#endif
+ AGL_NONE
};
+
/* TODO: open mac display */
/* TODO: dev = NULL, ndev = 0 ? */
@@ -143,37 +209,82 @@
/* create an off-screen AGL rendering area */
aglCreatePBuffer(width, height, GL_TEXTURE_2D, GL_RGBA, 0, &(rwin->windowId));
+ aglSetPBuffer(rwin->contextId, rwin->windowId, 0, 0, 0);
+#else
+ CGLPixelFormatAttribute attributeList[] = {
+ kCGLPFAColorSize, 24,
+ kCGLPFADepthSize, 32,
+ (CGLPixelFormatAttribute) 0
+ };
+ CGLPixelFormatObj pix;
+ GLint nvirt;
+ CGLError error;
+
+ error = CGLChoosePixelFormat(attributeList, &pix, &nvirt);
+ if (error) {
+ G_warning(_("Unable to choose pixel format (CGL error = %d)"), error);
+ return -1;
+ }
+
+ error = CGLCreateContext(pix, NULL, &rwin->contextId);
+ if (error) {
+ G_warning(_("Unable to create context (CGL error = %d)"), error);
+ return -1;
+ }
+
+ CGLDestroyPixelFormat(pix);
+#endif
#elif defined(OPENGL_WINDOWS)
+ WNDCLASS wc = {0};
+ HWND hWnd;
PIXELFORMATDESCRIPTOR pfd = {
- sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
- 1, /* version number */
- PFD_DRAW_TO_WINDOW | /* support window */
- PFD_SUPPORT_OPENGL | /* support OpenGL */
- PFD_DOUBLEBUFFER, /* double buffered */
- PFD_TYPE_RGBA, /* RGBA type */
- 24, /* 24-bit color depth */
- 0, 0, 0, 0, 0, 0, /* color bits ignored */
- 0, /* no alpha buffer */
- 0, /* shift bit ignored */
- 0, /* no accumulation buffer */
- 0, 0, 0, 0, /* accum bits ignored */
- 32, /* 32-bit z-buffer */
- 0, /* no stencil buffer */
- 0, /* no auxiliary buffer */
- PFD_MAIN_PLANE, /* main layer */
- 0, /* reserved */
- 0, 0, 0 /* layer masks ignored */
+ sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
+ 1, /* version number */
+ PFD_DRAW_TO_WINDOW | /* support window */
+ PFD_SUPPORT_OPENGL | /* support OpenGL */
+ PFD_DOUBLEBUFFER, /* double buffered */
+ PFD_TYPE_RGBA, /* RGBA type */
+ 24, /* 24-bit color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits ignored */
+ 0, /* no alpha buffer */
+ 0, /* shift bit ignored */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits ignored */
+ 32, /* 32-bit z-buffer */
+ 0, /* no stencil buffer */
+ 0, /* no auxiliary buffer */
+ PFD_MAIN_PLANE, /* main layer */
+ 0, /* reserved */
+ 0, 0, 0 /* layer masks ignored */
};
int iPixelFormat;
- rwin->displayId = CreateCompatibleDC(NULL);
+ wc.lpfnWndProc = DefWindowProc;
+ wc.lpszClassName = "nviz";
+
+ if (!RegisterClass(&wc)) {
+ G_warning(_("Unable to register window class"));
+ return -1;
+ }
+
+ hWnd = CreateWindow(wc.lpszClassName, wc.lpszClassName, WS_POPUP,
+ CW_USEDEFAULT, CW_USEDEFAULT, width, height,
+ NULL, NULL, wc.hInstance, NULL);
+
+ if (!hWnd) {
+ G_warning(_("Unable to create window"));
+ return -1;
+ }
+
+ rwin->displayId = GetDC(hWnd);
iPixelFormat = ChoosePixelFormat(rwin->displayId, &pfd);
SetPixelFormat(rwin->displayId, iPixelFormat, &pfd);
- rwin->bitmapId = CreateCompatibleBitmap(rwin->displayId, width, height);
- SelectObject(rwin->displayId, rwin->bitmapId);
rwin->contextId = wglCreateContext(rwin->displayId);
- /* TODO */
#endif
+
+ rwin->width = width;
+ rwin->height = height;
+
return 0;
}
@@ -196,6 +307,7 @@
glXMakeCurrent(rwin->displayId, rwin->windowId, rwin->contextId);
#elif defined(OPENGL_AQUA)
+#if defined(OPENGL_AGL)
if (!rwin->contextId)
return 0;
@@ -203,7 +315,15 @@
return 1;
aglSetCurrentContext(rwin->contextId);
- aglSetPBuffer(rwin->contextId, rwin->windowId, 0, 0, 0);
+#else
+ CGLError error;
+
+ error = CGLSetCurrentContext(rwin->contextId);
+ if (error) {
+ G_warning(_("Unable to set current context (CGL error = %d)"), error);
+ return 0;
+ }
+#endif
#elif defined(OPENGL_WINDOWS)
if (!rwin->displayId || !rwin->contextId)
return 0;
@@ -211,5 +331,39 @@
wglMakeCurrent(rwin->displayId, rwin->contextId);
#endif
+#if defined(OPENGL_FBO)
+#if defined(OPENGL_WINDOWS)
+ find_gl_funcs();
+#endif
+
+ GLuint framebuf, renderbuf, depthbuf;
+ GLenum status;
+
+ glGenFramebuffers(1, &framebuf);
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuf);
+
+ glGenRenderbuffers(1, &renderbuf);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8,
+ rwin->width, rwin->height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, renderbuf);
+
+ glGenRenderbuffers(1, &depthbuf);
+ glBindRenderbuffer(GL_RENDERBUFFER, depthbuf);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,
+ rwin->width, rwin->height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, depthbuf);
+
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ G_warning(_("Incomplete framebuffer status (status = %d)"), status);
+ return 0;
+ }
+#endif
+
+ glViewport(0, 0, rwin->width, rwin->height);
+
return 1;
}
Modified: grass/branches/releasebranch_7_4/lib/ogsf/gsd_prim.c
===================================================================
--- grass/branches/releasebranch_7_4/lib/ogsf/gsd_prim.c 2018-07-27 08:33:51 UTC (rev 73009)
+++ grass/branches/releasebranch_7_4/lib/ogsf/gsd_prim.c 2018-07-28 03:37:07 UTC (rev 73010)
@@ -5,7 +5,7 @@
GRASS OpenGL gsurf OGSF Library
- (C) 1999-2008 by the GRASS Development Team
+ (C) 1999-2008, 2018 by the GRASS Development Team
This program is free software under the
GNU General Public License (>=v2).
@@ -14,6 +14,7 @@
\author Bill Brown USACERL (January 1993)
\author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
+ \author Support for framebuffer objects by Huidae Cho <grass4u gmail.com> (July 2018)
*/
#include <stdlib.h>
@@ -21,13 +22,21 @@
#include <grass/config.h>
-#if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
+#if defined(OPENGL_X11)
#include <GL/gl.h>
#include <GL/glu.h>
+#include <GL/glx.h>
#elif defined(OPENGL_AQUA)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
+#if defined(OPENGL_AGL)
+#include <AGL/agl.h>
#endif
+#elif defined(OPENGL_WINDOWS)
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <wingdi.h>
+#endif
#include <grass/gis.h>
#include <grass/ogsf.h>
@@ -404,13 +413,13 @@
/*!
\brief Set shaded model
- \param bool type non-zero for GL_SMOOTH otherwise GL_FLAT
+ \param shade non-zero for GL_SMOOTH otherwise GL_FLAT
*/
-void gsd_shademodel(int bool)
+void gsd_shademodel(int shade)
{
- Shade = bool;
+ Shade = shade;
- if (bool) {
+ if (shade) {
glShadeModel(GL_SMOOTH);
}
else {
@@ -431,40 +440,38 @@
}
/*!
- \brief ADD
+ \brief Draw to the front and back buffers
*/
void gsd_bothbuffers(void)
{
- /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
+#if !defined(OPENGL_FBO)
+ /* OGLXXX bothbuffer: other possibilities include GL_FRONT, GL_BACK */
glDrawBuffer(GL_FRONT_AND_BACK);
-
+#endif
return;
}
/*!
- \brief Specify which color buffers are to be drawn
- into
-
- \param bool non-zero for enable otherwise disable front buffer
+ \brief Draw to the front buffer
*/
void gsd_frontbuffer(void)
{
+#if !defined(OPENGL_FBO)
/* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
glDrawBuffer(GL_FRONT);
-
+#endif
return;
}
/*!
- \brief Specify which color buffers are to be drawn
- into
-
- \param bool non-zero for enable otherwise disable back buffer
+ \brief Draw to the back buffer
*/
void gsd_backbuffer(void)
{
+#if !defined(OPENGL_FBO)
/* OGLXXX backbuffer: other possibilities include GL_FRONT_AND_BACK */
glDrawBuffer(GL_BACK);
+#endif
return;
}
@@ -473,12 +480,17 @@
*/
void gsd_swapbuffers(void)
{
- /* OGLXXX swapbuffers:
- glXSwapBuffers(*display, window);
- replace display and window */
-
- Swap_func();
-
+#if !defined(OPENGL_FBO)
+ /* OGLXXX swapbuffers: copy the back buffer to the front;
+ * the back buffer becomes undefined afterward */
+#if defined(OPENGL_X11)
+ glXSwapBuffers(glXGetCurrentDisplay(), glXGetCurrentDrawable());
+#elif defined(OPENGL_AQUA)
+ aglSwapBuffers(aglGetCurrentContext());
+#elif defined(OPENGL_WINDOWS)
+ SwapBuffers(wglGetCurrentDC());
+#endif
+#endif
return;
}
@@ -910,12 +922,17 @@
*xsize = r - l + 1;
*ysize = t - b + 1;
+ if (!*xsize || !*ysize)
+ return (0);
+
*pixbuf = (unsigned char *)G_malloc((*xsize) * (*ysize) * 4); /* G_fatal_error */
if (!*pixbuf)
return (0);
+#if !defined(OPENGL_FBO)
glReadBuffer(GL_FRONT);
+#endif
/* OGLXXX lrectread: see man page for glReadPixels */
glReadPixels(l, b, (r) - (l) + 1, (t) - (b) + 1, GL_RGBA,
@@ -947,6 +964,9 @@
\param pixbuf data buffer
\param xsize,ysize picture dimension
+
+ \return 0 on failure
+ \return 1 on success
*/
int gsd_writeView(unsigned char **pixbuf, unsigned int xsize,
unsigned int ysize)
@@ -958,8 +978,10 @@
return (0);
}
+#if !defined(OPENGL_FBO)
/* Read image buffer */
glReadBuffer(GL_FRONT);
+#endif
/* Read Pixels into Buffer */
glReadPixels(0, 0, xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, *pixbuf);
Modified: grass/branches/releasebranch_7_4/lib/ogsf/gsd_views.c
===================================================================
--- grass/branches/releasebranch_7_4/lib/ogsf/gsd_views.c 2018-07-27 08:33:51 UTC (rev 73009)
+++ grass/branches/releasebranch_7_4/lib/ogsf/gsd_views.c 2018-07-28 03:37:07 UTC (rev 73010)
@@ -66,8 +66,8 @@
vect[TO][Z] = tz;
/* DEBUG - should just be a dot */
- /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
- glDrawBuffer((1) ? GL_FRONT : GL_BACK);
+ /* OGLXXX frontbuffer: other possibilities include GSD_BOTH */
+ GS_set_draw((1) ? GSD_FRONT : GSD_BACK);
glPushMatrix();
gsd_do_scale(1);
gsd_linewidth(3);
@@ -82,8 +82,8 @@
gsd_linewidth(1);
glPopMatrix();
- /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
- glDrawBuffer((0) ? GL_FRONT : GL_BACK);
+ /* OGLXXX frontbuffer: other possibilities include GSD_BOTH */
+ GS_set_draw((0) ? GSD_FRONT : GSD_BACK);
return (1);
}
More information about the grass-commit
mailing list