pbuffer.cpp
上传用户:qccn516
上传日期:2013-05-02
资源大小:3382k
文件大小:9k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /* OpenGL pixel buffer
  2.  *
  3.  * Copyright (C) 2003-2004, Alexander Zaprjagaev <frustum@frustum.org>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #ifndef _WIN32
  20. /* linux
  21.  */
  22. #include <vector>
  23. #include <GL/gl.h>
  24. #include <GL/glx.h>
  25. #include "pbuffer.h"
  26. /*
  27.  */
  28. struct PBuffer_data {
  29. Display *display;
  30. GLXPbuffer pbuffer;
  31. GLXContext context;
  32. GLXPbuffer old_pbuffer;
  33. GLXContext old_context;
  34. };
  35. /*
  36.  */
  37. PBuffer::PBuffer(int width,int height,int flag) : width(width), height(height) {
  38. Display *display = glXGetCurrentDisplay();
  39. int screen = DefaultScreen(display);
  40. GLXContext old_context = glXGetCurrentContext();
  41. std::vector<int> attrib;
  42. if(flag & RGB || flag & RGBA) {
  43. attrib.push_back(GLX_RED_SIZE);
  44. attrib.push_back(flag & FLOAT ? 32 : 8);
  45. attrib.push_back(GLX_GREEN_SIZE);
  46. attrib.push_back(flag & FLOAT ? 32 : 8);
  47. attrib.push_back(GLX_BLUE_SIZE);
  48. attrib.push_back(flag & FLOAT ? 32 : 8);
  49. if(flag & RGBA) {
  50. attrib.push_back(GLX_ALPHA_SIZE);
  51. attrib.push_back(flag & FLOAT ? 32 : 8);
  52. }
  53. }
  54. if(flag & DEPTH) {
  55. attrib.push_back(GLX_DEPTH_SIZE);
  56. attrib.push_back(24);
  57. }
  58. if(flag & STENCIL) {
  59. attrib.push_back(GLX_STENCIL_SIZE);
  60. attrib.push_back(8);
  61. }
  62. if(flag & FLOAT) {
  63. attrib.push_back(GLX_FLOAT_COMPONENTS_NV);
  64. attrib.push_back(true);
  65. }
  66. if(flag & MULTISAMPLE_2 || flag & MULTISAMPLE_4) {
  67. attrib.push_back(GLX_SAMPLE_BUFFERS_ARB);
  68. attrib.push_back(true);
  69. attrib.push_back(GLX_SAMPLES_ARB);
  70. attrib.push_back(flag & MULTISAMPLE_2 ? 2 : 4);
  71. }
  72. attrib.push_back(GLX_DRAWABLE_TYPE);
  73. attrib.push_back(GLX_PBUFFER_BIT);
  74. attrib.push_back(GLX_RENDER_TYPE);
  75. attrib.push_back(GLX_RGBA_BIT);
  76. attrib.push_back(0);
  77. std::vector<int> pattrib;
  78. pattrib.push_back(GLX_LARGEST_PBUFFER);
  79. pattrib.push_back(true);
  80. pattrib.push_back(GLX_PRESERVED_CONTENTS);
  81. pattrib.push_back(true);
  82. GLXPbuffer pbuffer;
  83. GLXContext context;
  84. try {
  85. int count;
  86. GLXFBConfig *config;
  87. const char *extensions = glXQueryExtensionsString(display,screen);
  88. if(strstr(extensions,"GLX_SGIX_pbuffer") && strstr(extensions,"GLX_SGIX_fbconfig")) {
  89. pattrib.push_back(0);
  90. config = glXChooseFBConfigSGIX(display,screen,&attrib[0],&count);
  91. if(!config) throw("glXChooseFBConfigSGIX() failed");
  92. pbuffer = glXCreateGLXPbufferSGIX(display,config[0],width,height,&pattrib[0]);
  93. if(!pbuffer) throw("glXCreateGLXPbufferSGIX() failed");
  94. context = glXCreateContextWithConfigSGIX(display,config[0],GLX_RGBA_TYPE,old_context,true);
  95. if(!context) throw("glXCreateContextWithConfigSGIX() failed");
  96. } else {
  97. pattrib.push_back(GLX_PBUFFER_WIDTH);
  98. pattrib.push_back(width);
  99. pattrib.push_back(GLX_PBUFFER_HEIGHT);
  100. pattrib.push_back(height);
  101. pattrib.push_back(0);
  102. config = glXChooseFBConfig(display,screen,&attrib[0],&count);
  103. if(!config) throw("glXChooseFBConfig() failed");
  104. pbuffer = glXCreatePbuffer(display,config[0],&pattrib[0]);
  105. if(!pbuffer) throw("glXCreatePbuffer() failed");
  106. XVisualInfo *visual = glXGetVisualFromFBConfig(display,config[0]);
  107. if(!visual) throw("glXGetVisualFromFBConfig() failed");
  108. context = glXCreateContext(display,visual,old_context,true);
  109. if(!context) throw("glXCreateContext() failed");
  110. }
  111. }
  112. catch(const char *error) {
  113. fprintf(stderr,"PBuffer::PBuffer: %sn",error);
  114. pbuffer = glXGetCurrentDrawable();
  115. context = old_context;
  116. }
  117. data = new PBuffer_data;
  118. data->display = display;
  119. data->pbuffer = pbuffer;
  120. data->context = context;
  121. data->old_pbuffer = glXGetCurrentDrawable();
  122. data->old_context = old_context;
  123. }
  124. /*
  125.  */
  126. PBuffer::~PBuffer() {
  127. if(data->context) glXDestroyContext(data->display,data->context);
  128. if(data->pbuffer) glXDestroyPbuffer(data->display,data->pbuffer);
  129. delete data;
  130. }
  131. /*
  132.  */
  133. void PBuffer::enable() {
  134. glXWaitGL(); // very BIG bug fix :)
  135. data->old_pbuffer = glXGetCurrentDrawable();
  136. data->old_context = glXGetCurrentContext();
  137. if(!glXMakeCurrent(data->display,data->pbuffer,data->context)) {
  138. fprintf(stderr,"PBuffer::enable(): glXMakeCurrent() failedn");
  139. }
  140. }
  141. /*
  142.  */
  143. void PBuffer::disable() {
  144. glXWaitGL();
  145. if(!glXMakeCurrent(data->display,data->old_pbuffer,data->old_context)) {
  146. fprintf(stderr,"PBuffer::disable(): glXMakeCurrent() failedn");
  147. }
  148. }
  149. #else
  150. /* windows
  151.  */
  152. #include <vector>
  153. #include <windows.h>
  154. #include <GL/gl.h>
  155. #include <GL/glext.h>
  156. #include <GL/wglext.h>
  157. #include "pbuffer.h"
  158. /*
  159.  */
  160. struct PBuffer_data {
  161. HDC hdc;
  162. HPBUFFERARB pbuffer;
  163. HGLRC context;
  164. HDC old_hdc;
  165. HGLRC old_context;
  166. };
  167. static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = 0;
  168. static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = 0;
  169. static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = 0;
  170. static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = 0;
  171. static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = 0;
  172. /*
  173.  */
  174. PBuffer::PBuffer(int width,int height,int flag) : width(width), height(height) {
  175. HDC old_hdc = wglGetCurrentDC();
  176. HGLRC old_context = wglGetCurrentContext();
  177. std::vector<int> attrib;
  178. if(flag & RGB || flag & RGBA) {
  179. attrib.push_back(WGL_RED_BITS_ARB);
  180. attrib.push_back(flag & FLOAT ? 32 : 8);
  181. attrib.push_back(WGL_GREEN_BITS_ARB);
  182. attrib.push_back(flag & FLOAT ? 32 : 8);
  183. attrib.push_back(WGL_BLUE_BITS_ARB);
  184. attrib.push_back(flag & FLOAT ? 32 : 8);
  185. if(flag & RGBA) {
  186. attrib.push_back(WGL_ALPHA_BITS_ARB);
  187. attrib.push_back(flag & FLOAT ? 32 : 8);
  188. }
  189. }
  190. if(flag & DEPTH) {
  191. attrib.push_back(WGL_DEPTH_BITS_ARB);
  192. attrib.push_back(24);
  193. }
  194. if(flag & STENCIL) {
  195. attrib.push_back(WGL_STENCIL_BITS_ARB);
  196. attrib.push_back(8);
  197. }
  198. if(flag & FLOAT) {
  199. attrib.push_back(WGL_FLOAT_COMPONENTS_NV);
  200. attrib.push_back(true);
  201. }
  202. if(flag & MULTISAMPLE_2 || flag & MULTISAMPLE_4) {
  203. attrib.push_back(WGL_SAMPLE_BUFFERS_ARB);
  204. attrib.push_back(true);
  205. attrib.push_back(WGL_SAMPLES_ARB);
  206. attrib.push_back(flag & MULTISAMPLE_2 ? 2 : 4);
  207. }
  208. attrib.push_back(WGL_DRAW_TO_PBUFFER_ARB);
  209. attrib.push_back(true);
  210. attrib.push_back(WGL_SUPPORT_OPENGL_ARB);
  211. attrib.push_back(true);
  212. attrib.push_back(WGL_PIXEL_TYPE_ARB);
  213. attrib.push_back(WGL_TYPE_RGBA_ARB);
  214. attrib.push_back(0);
  215. HDC hdc;
  216. HPBUFFERARB pbuffer;
  217. HGLRC context;
  218. try {
  219. if(!wglChoosePixelFormatARB) wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
  220. if(!wglChoosePixelFormatARB) throw("wglGetProcAddress("wglChoosePixelFormatARB") failed");
  221. if(!wglCreatePbufferARB) wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB");
  222. if(!wglCreatePbufferARB) throw("wglGetProcAddress("wglCreatePbufferARB") failed");
  223. if(!wglGetPbufferDCARB) wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB");
  224. if(!wglGetPbufferDCARB) throw("wglGetProcAddress("wglGetPbufferDCARB") failed");
  225. if(!wglReleasePbufferDCARB) wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB");
  226. if(!wglReleasePbufferDCARB) throw("wglGetProcAddress("wglReleasePbufferDCARB") failedn");
  227. if(!wglDestroyPbufferARB) wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress("wglDestroyPbufferARB");
  228. if(!wglDestroyPbufferARB) throw("wglGetProcAddress("wglDestroyPbufferARB") failedn");
  229. int format;
  230. unsigned int count;
  231. wglChoosePixelFormatARB(old_hdc,&attrib[0],NULL,1,&format,&count);
  232. if(count == 0) throw("wglChoosePixelFormatARB() failed");
  233. int pattrib[] = { 0 };
  234. pbuffer = wglCreatePbufferARB(old_hdc,format,width,height,pattrib);
  235. if(!pbuffer) throw("wglCreatePbufferARB() failed");
  236. hdc = wglGetPbufferDCARB(pbuffer);
  237. if(!hdc) throw("wglGetPbufferDCARB() failed");
  238. context = wglCreateContext(hdc);
  239. if(!context) throw("wglCreateContext() failed");
  240. if(!wglShareLists(old_context,context)) throw("wglShareLists() failed");
  241. }
  242. catch(const char *error) {
  243. fprintf(stderr,"PBuffer::PBuffer: %sn",error);
  244. hdc = old_hdc;
  245. context = old_context;
  246. }
  247. data = new PBuffer_data;
  248. data->hdc = hdc;
  249. data->pbuffer = pbuffer;
  250. data->context = context;
  251. data->old_hdc = old_hdc;
  252. data->old_context = old_context;
  253. }
  254. /*
  255.  */
  256. PBuffer::~PBuffer() {
  257. wglDeleteContext(data->context);
  258. wglReleasePbufferDCARB(data->pbuffer,data->hdc);
  259. wglDestroyPbufferARB(data->pbuffer);
  260. wglMakeCurrent(data->hdc,data->context);
  261. }
  262. /*
  263.  */
  264. void PBuffer::enable() {
  265. data->old_hdc = wglGetCurrentDC();
  266. data->old_context = wglGetCurrentContext();
  267. if(!wglMakeCurrent(data->hdc,data->context)) {
  268. fprintf(stderr,"PBuffer::disable(): wglMakeCurrent() failedn");
  269. }
  270. }
  271. /*
  272.  */
  273. void PBuffer::disable() {
  274. if(!wglMakeCurrent(data->old_hdc,data->old_context)) {
  275. fprintf(stderr,"PBuffer::disable(): wglMakeCurrent() failedn");
  276. }
  277. }
  278. #endif