[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