[GRASS-SVN] r73006 - in grass/trunk: include lib/nviz lib/ogsf
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Jul 25 18:14:16 PDT 2018
Author: hcho
Date: 2018-07-25 18:14:16 -0700 (Wed, 25 Jul 2018)
New Revision: 73006
Modified:
grass/trunk/include/config.h.in
grass/trunk/include/nviz.h
grass/trunk/lib/nviz/render.c
grass/trunk/lib/ogsf/gsd_prim.c
Log:
nviz, ogsf: Use framebuffer objects for off-screen GL rendering; Use Core OpenGL (CGL) for the MacOS instead of deprecated 32-bit only AGL (Fix #3600, #2114, #3606)
Modified: grass/trunk/include/config.h.in
===================================================================
--- grass/trunk/include/config.h.in 2018-07-25 20:35:14 UTC (rev 73005)
+++ grass/trunk/include/config.h.in 2018-07-26 01:14:16 UTC (rev 73006)
@@ -318,4 +318,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/trunk/include/nviz.h
===================================================================
--- grass/trunk/include/nviz.h 2018-07-25 20:35:14 UTC (rev 73005)
+++ grass/trunk/include/nviz.h 2018-07-26 01:14:16 UTC (rev 73006)
@@ -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,12 +134,16 @@
#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 */
Modified: grass/trunk/lib/nviz/render.c
===================================================================
--- grass/trunk/lib/nviz/render.c 2018-07-25 20:35:14 UTC (rev 73005)
+++ grass/trunk/lib/nviz/render.c 2018-07-26 01:14:16 UTC (rev 73006)
@@ -4,17 +4,57 @@
\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);
+ }
+ 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,9 +84,13 @@
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;
@@ -69,10 +113,13 @@
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);
@@ -96,9 +143,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, GLX_DOUBLEBUFFER, 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;
@@ -113,7 +167,7 @@
G_warning(_("Unable to get visual info"));
return -1;
}
-
+
rwin->contextId = glXCreateContext(rwin->displayId, v, NULL, GL_TRUE);
if (!rwin->contextId) {
@@ -131,10 +185,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_DOUBLEBUFFER, 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 ? */
@@ -145,28 +208,52 @@
/* 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;
@@ -218,6 +305,7 @@
glXMakeCurrent(rwin->displayId, rwin->windowId, rwin->contextId);
#elif defined(OPENGL_AQUA)
+#if defined(OPENGL_AGL)
if (!rwin->contextId)
return 0;
@@ -225,6 +313,15 @@
return 1;
aglSetCurrentContext(rwin->contextId);
+#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;
@@ -232,6 +329,38 @@
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/trunk/lib/ogsf/gsd_prim.c
===================================================================
--- grass/trunk/lib/ogsf/gsd_prim.c 2018-07-25 20:35:14 UTC (rev 73005)
+++ grass/trunk/lib/ogsf/gsd_prim.c 2018-07-26 01:14:16 UTC (rev 73006)
@@ -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>
@@ -28,7 +29,9 @@
#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>
@@ -441,9 +444,10 @@
*/
void gsd_bothbuffers(void)
{
+#if !defined(OPENGL_FBO)
/* OGLXXX bothbuffer: other possibilities include GL_FRONT, GL_BACK */
glDrawBuffer(GL_FRONT_AND_BACK);
-
+#endif
return;
}
@@ -452,9 +456,10 @@
*/
void gsd_frontbuffer(void)
{
+#if !defined(OPENGL_FBO)
/* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
glDrawBuffer(GL_FRONT);
-
+#endif
return;
}
@@ -463,9 +468,10 @@
*/
void gsd_backbuffer(void)
{
+#if !defined(OPENGL_FBO)
/* OGLXXX backbuffer: other possibilities include GL_FRONT_AND_BACK */
glDrawBuffer(GL_BACK);
-
+#endif
return;
}
@@ -474,6 +480,7 @@
*/
void gsd_swapbuffers(void)
{
+#if !defined(OPENGL_FBO)
/* OGLXXX swapbuffers: copy the back buffer to the front;
* the back buffer becomes undefined afterward */
#if defined(OPENGL_X11)
@@ -483,7 +490,7 @@
#elif defined(OPENGL_WINDOWS)
SwapBuffers(wglGetCurrentDC());
#endif
-
+#endif
return;
}
@@ -923,7 +930,9 @@
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,
@@ -969,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);
More information about the grass-commit
mailing list