[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