render.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*!
  2. \file lib/nviz/render.c
  3. \brief Nviz library -- GLX context manipulation
  4. Based on visualization/nviz/src/togl.c
  5. (C) 2008, 2010 by the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Updated/modified by Martin Landa <landa.martin gmail.com> (Google SoC 2008/2010)
  9. */
  10. #include <grass/glocale.h>
  11. #include <grass/nviz.h>
  12. /*!
  13. \brief Allocate memory for render window
  14. \return pointer to render_window struct
  15. \return NULL on failure
  16. */
  17. struct render_window *Nviz_new_render_window(void)
  18. {
  19. struct render_window *rwin;
  20. /* G_malloc() calls G_fatal_error() on failure */
  21. rwin = (struct render_window *)G_malloc(sizeof(struct render_window));
  22. return rwin;
  23. }
  24. /*!
  25. \brief Initialize render window
  26. \param win pointer to render_window struct
  27. */
  28. void Nviz_init_render_window(struct render_window *rwin)
  29. {
  30. #if defined(OPENGL_X11)
  31. rwin->displayId = NULL;
  32. rwin->contextId = NULL;
  33. rwin->pixmap = 0;
  34. rwin->windowId = 0;
  35. #elif defined(OPENGL_AQUA)
  36. rwin->pixelFmtId = NULL;
  37. rwin->contextId = NULL;
  38. rwin->windowId = NULL;
  39. #elif defined(OPENGL_WINDOWS)
  40. rwin->displayId = NULL;
  41. rwin->contextId = NULL;
  42. rwin->bitmapId = NULL;
  43. #endif
  44. }
  45. /*!
  46. \brief Free render window
  47. \param win pointer to render_window struct
  48. */
  49. void Nviz_destroy_render_window(struct render_window *rwin)
  50. {
  51. #if defined(OPENGL_X11)
  52. glXDestroyContext(rwin->displayId, rwin->contextId);
  53. glXDestroyGLXPixmap(rwin->displayId, rwin->windowId);
  54. XFreePixmap(rwin->displayId, rwin->pixmap);
  55. #elif defined(OPENGL_AQUA)
  56. aglDestroyPixelFormat(rwin->pixelFmtId);
  57. aglDestroyContext(rwin->contextId);
  58. aglDestroyPBuffer(rwin->windowId);
  59. /* TODO FreePixMap */
  60. #elif defined(OPENGL_WINDOWS)
  61. wglDeleteContext(rwin->contextId);
  62. DeleteDC(rwin->displayId);
  63. DeleteObject(rwin->bitmapId);
  64. #endif
  65. G_free((void *)rwin);
  66. }
  67. /*!
  68. \brief Create render window
  69. \param rwin pointer to render_window struct
  70. \param display display instance (NULL for offscreen)
  71. \param width window width
  72. \param height window height
  73. \return 1
  74. */
  75. int Nviz_create_render_window(struct render_window *rwin, void *display,
  76. int width, int height)
  77. {
  78. #if defined(OPENGL_X11)
  79. int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1,
  80. GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
  81. GLX_DEPTH_SIZE, 1, None
  82. };
  83. XVisualInfo *v;
  84. rwin->displayId = XOpenDisplay((char *)display);
  85. if (!rwin->displayId) {
  86. G_fatal_error(_("Bad server connection"));
  87. }
  88. v = glXChooseVisual(rwin->displayId,
  89. DefaultScreen(rwin->displayId), attributeList);
  90. rwin->contextId = glXCreateContext(rwin->displayId, v, NULL, GL_FALSE);
  91. if (!rwin->contextId) {
  92. G_fatal_error(_("Unable to create rendering context"));
  93. }
  94. /* create win pixmap to render to (same depth as RootWindow) */
  95. rwin->pixmap = XCreatePixmap(rwin->displayId,
  96. RootWindow(rwin->displayId, v->screen),
  97. width, height, v->depth);
  98. /* create an off-screen GLX rendering area */
  99. rwin->windowId = glXCreateGLXPixmap(rwin->displayId, v, rwin->pixmap);
  100. if (v) {
  101. XFree(v);
  102. }
  103. #elif defined(OPENGL_AQUA)
  104. int attributeList[] = { AGL_RGBA, AGL_RED_SIZE, 1,
  105. AGL_GREEN_SIZE, 1, AGL_BLUE_SIZE, 1,
  106. AGL_DEPTH_SIZE, 1, AGL_NONE
  107. };
  108. /* TODO: open mac display */
  109. /* TODO: dev = NULL, ndev = 0 ? */
  110. rwin->pixelFmtId = aglChoosePixelFormat(NULL, 0, attributeList);
  111. rwin->contextId = aglCreateContext(rwin->pixelFmtId, NULL);
  112. /* create an off-screen AGL rendering area */
  113. aglCreatePBuffer(width, height, GL_TEXTURE_2D, GL_RGBA, 0, &(rwin->windowId));
  114. #elif defined(OPENGL_WINDOWS)
  115. PIXELFORMATDESCRIPTOR pfd = {
  116. sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
  117. 1, /* version number */
  118. PFD_DRAW_TO_WINDOW | /* support window */
  119. PFD_SUPPORT_OPENGL | /* support OpenGL */
  120. PFD_DOUBLEBUFFER, /* double buffered */
  121. PFD_TYPE_RGBA, /* RGBA type */
  122. 24, /* 24-bit color depth */
  123. 0, 0, 0, 0, 0, 0, /* color bits ignored */
  124. 0, /* no alpha buffer */
  125. 0, /* shift bit ignored */
  126. 0, /* no accumulation buffer */
  127. 0, 0, 0, 0, /* accum bits ignored */
  128. 32, /* 32-bit z-buffer */
  129. 0, /* no stencil buffer */
  130. 0, /* no auxiliary buffer */
  131. PFD_MAIN_PLANE, /* main layer */
  132. 0, /* reserved */
  133. 0, 0, 0 /* layer masks ignored */
  134. };
  135. int iPixelFormat;
  136. rwin->displayId = CreateCompatibleDC(NULL);
  137. iPixelFormat = ChoosePixelFormat(rwin->displayId, &pfd);
  138. SetPixelFormat(rwin->displayId, iPixelFormat, &pfd);
  139. rwin->bitmapId = CreateCompatibleBitmap(rwin->displayId, width, height);
  140. SelectObject(rwin->displayId, rwin->bitmapId);
  141. rwin->contextId = wglCreateContext(rwin->displayId);
  142. /* TODO */
  143. #endif
  144. return 1;
  145. }
  146. /*!
  147. \brief Make window current for rendering
  148. \param win pointer to render_window struct
  149. \return 1 on success
  150. \return 0 on failure
  151. */
  152. int Nviz_make_current_render_window(const struct render_window *rwin)
  153. {
  154. #if defined(OPENGL_X11)
  155. if (!rwin->displayId || !rwin->contextId)
  156. return 0;
  157. if (rwin->contextId == glXGetCurrentContext())
  158. return 1;
  159. glXMakeCurrent(rwin->displayId, rwin->windowId, rwin->contextId);
  160. #elif defined(OPENGL_AQUA)
  161. if (!rwin->contextId)
  162. return 0;
  163. if (rwin->contextId == aglGetCurrentContext())
  164. return 1;
  165. aglSetCurrentContext(rwin->contextId);
  166. aglSetPBuffer(rwin->contextId, rwin->windowId, 0, 0, 0);
  167. #elif defined(OPENGL_WINDOWS)
  168. if (!rwin->displayId || !rwin->contextId)
  169. return 0;
  170. wglMakeCurrent(rwin->displayId, rwin->contextId);
  171. #endif
  172. return 1;
  173. }