IVT
GLContext.cpp
Go to the documentation of this file.
1 // ****************************************************************************
2 // This file is part of the Integrating Vision Toolkit (IVT).
3 //
4 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
5 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
6 //
7 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // 3. Neither the name of the KIT nor the names of its contributors may be
21 // used to endorse or promote products derived from this software
22 // without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
25 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
28 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // ****************************************************************************
35 // ****************************************************************************
36 // Filename: GLContext.cpp
37 // Author: Florian Hecht
38 // Date: 2008
39 // ****************************************************************************
40 
41 
42 // ****************************************************************************
43 // Includes
44 // ****************************************************************************
45 
46 #include "GLContext.h"
47 
48 #include "Image/ByteImage.h"
49 
50 #include <stdio.h>
51 #include <memory.h>
52 
53 
54 
55 #ifdef WIN32
56 
58 {
59  m_hDC = NULL;
60  m_hBmp = NULL;
61  m_hBmpOld = NULL;
62  m_hGLRC = NULL;
63 
64  m_nWidth = 0;
65  m_nHeight = 0;
66  m_pPixels = NULL;
67 }
69 {
70  DeleteContext();
71 }
72 
73 bool CGLContext::CreateContext(int width, int height, void *shareContext)
74 {
75  m_hDC = CreateCompatibleDC(NULL);
76  if (!m_hDC)
77  {
78  printf("ERROR: couldn't allocate DC\n");
79 
80  return false;
81  }
82 
83  BITMAPINFO bminfo;
84  // create a bitmap with rgb pixels
85  bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
86  bminfo.bmiHeader.biWidth = width;
87  bminfo.bmiHeader.biHeight = height;
88  bminfo.bmiHeader.biPlanes = 1;
89  bminfo.bmiHeader.biBitCount = 24;
90  bminfo.bmiHeader.biCompression = BI_RGB;
91  bminfo.bmiHeader.biSizeImage = 0; // it's OK for RGB images
92  bminfo.bmiHeader.biXPelsPerMeter = 1;
93  bminfo.bmiHeader.biYPelsPerMeter = 1;
94  bminfo.bmiHeader.biClrUsed = 0;
95  bminfo.bmiHeader.biClrImportant = 0;
96 
97  m_hBmp = CreateDIBSection(m_hDC, &bminfo, DIB_RGB_COLORS, (void**)&m_pPixels, NULL, 0);
98  if (!m_hBmp)
99  {
100  printf("ERROR: couldn't allocate Bitmap\n");
101 
102  DeleteDC(m_hDC);
103  m_hDC = NULL;
104 
105  return false;
106  }
107 
108  m_hBmpOld = (HBITMAP)SelectObject(m_hDC, m_hBmp);
109 
110  PIXELFORMATDESCRIPTOR pfd = {
111  sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
112  1, // version number
113  PFD_DRAW_TO_BITMAP | // support drawing to bitmap
114  PFD_SUPPORT_OPENGL, // support OpenGL
115  PFD_TYPE_RGBA, // RGBA type
116  24, // 24-bit color depth
117  0, 0, 0, 0, 0, 0, // color bits ignored
118  0, // no alpha buffer
119  0, // shift bit ignored
120  0, // no accumulation buffer
121  0, 0, 0, 0, // accum bits ignored
122  32, // 32-bit z-buffer
123  0, // no stencil buffer
124  0, // no auxiliary buffer
125  PFD_MAIN_PLANE, // main layer
126  0, // reserved
127  0, 0, 0 // layer masks ignored
128  };
129 
130  int iPixelFormat;
131 
132  // get the best available match of pixel format for the device context
133  iPixelFormat = ChoosePixelFormat(m_hDC, &pfd);
134 
135  // make that the pixel format of the device context
136  BOOL bResult = SetPixelFormat(m_hDC, iPixelFormat, &pfd);
137  if (!bResult)
138  {
139  printf("ERROR: SetPixelFormat failed\n");
140 
141  SelectObject(m_hDC, m_hBmpOld);
142  DeleteObject(m_hBmp);
143  DeleteDC(m_hDC);
144  m_hDC = NULL;
145 
146  return false;
147  }
148 
149  m_hGLRC = wglCreateContext(m_hDC);
150  if (!m_hGLRC)
151  {
152  printf("ERROR: couldn't allocate HGLRC\n");
153 
154  SelectObject(m_hDC, m_hBmpOld);
155  DeleteObject(m_hBmp);
156  DeleteDC(m_hDC);
157  m_hDC = NULL;
158 
159  return NULL;
160  }
161 
162  wglMakeCurrent(m_hDC, m_hGLRC);
163 
164  m_nWidth = width;
165  m_nHeight = height;
166 
167  return true;
168 }
169 
171 {
172  if (m_hDC != NULL)
173  {
174  wglMakeCurrent(NULL, NULL);
175 
176  wglDeleteContext(m_hGLRC);
177  m_hGLRC = NULL;
178 
179  SelectObject(m_hDC, m_hBmpOld);
180  m_hBmpOld = NULL;
181 
182  DeleteObject(m_hBmp);
183  m_hBmp = NULL;
184 
185  DeleteDC(m_hDC);
186  m_hDC = NULL;
187  }
188 }
189 
191 {
192  if (m_hDC != NULL)
193  wglMakeCurrent(m_hDC, m_hGLRC);
194 }
195 
197 {
198  wglMakeCurrent(NULL, NULL);
199 }
200 
201 bool CGLContext::GetImage(CByteImage *pImage)
202 {
203  if (m_hDC == NULL)
204  return false;
205 
206  if (pImage->width != m_nWidth || pImage->height != m_nHeight)
207  {
208  printf("ERROR: CGLContext::GetImage: Image dimensions do not match (%d, %d) vs. (%d, %d)\n", pImage->width, pImage->height, m_nWidth, m_nHeight);
209  return false;
210  }
211 
212  glFlush();
213 
214  if (pImage->type == CByteImage::eRGB24)
215  {
216  unsigned char *in = m_pPixels + 3 * m_nWidth * (m_nHeight-1);
217  unsigned char *out = pImage->pixels;
218 
219  for (int y = 0; y < m_nHeight; y++, in -= 2*3*m_nWidth)
220  {
221  for (int x = 0; x < m_nWidth; x++, out += 3, in += 3)
222  {
223  // BGR -> RGB
224  out[0] = in[2];
225  out[1] = in[1];
226  out[2] = in[0];
227  }
228  }
229  }
230  else
231  {
232  unsigned char *in = m_pPixels + 3 * m_nWidth * (m_nHeight-1);
233  unsigned char *out = pImage->pixels;
234 
235  for (int y = 0; y < m_nHeight; y++, in -= 2*3*m_nWidth)
236  {
237  for (int x = 0; x < m_nWidth; x++, out += 3, in += 3)
238  {
239  *out = (in[0] + in[1] + in[2]) / 3;
240  }
241  }
242  }
243 
244  return true;
245 }
246 
247 #endif /* WIN32 */
248 
249 
250 
251 #ifdef USE_QTGUI
252 
253 #include <qapplication.h>
254 #include <qpixmap.h>
255 
256 #include "Helpers/helpers.h"
257 
258 
259 class MyQGLContext : public QGLContext
260 {
261 public:
262  MyQGLContext(const QGLFormat &format, QPaintDevice *device)
263  : QGLContext(format, device)
264  {
265  }
266  virtual ~MyQGLContext()
267  {
268  }
269 
270  void clearCurrent()
271  {
272  doneCurrent();
273  }
274 };
275 
277 : m_pApp(NULL), m_pPixmap(NULL), m_pGLContext(NULL)
278 {
279 }
281 {
282  DeleteContext();
283 }
284 
285 static char app_name[] = "IVT_APPLICATION\0";
286 static int my_argc = 1;
287 static char *my_argv[2] = { app_name, NULL};
288 
289 bool CGLContext::CreateContext(int width, int height, void *shareContext)
290 {
291 #ifdef USE_OPENGL
292  if (qApp == NULL)
293  {
294  m_pApp = new QApplication(my_argc, my_argv);
295  }
296 
297  m_pPixmap = new QPixmap(width, height);
298 
299  QGLFormat f = QGLFormat::defaultFormat();
300  //f.setDoubleBuffer(FALSE); // this instruction disables the HW acceleration, so we have to use double buffering
301 
302  m_pGLContext = new MyQGLContext(f, m_pPixmap);
303 
304  m_pGLContext->create((QGLContext*)shareContext);
305  if (!m_pGLContext->isValid())
306  {
307  printf("ERROR: CGLContext::CreateContext: couldn't create GLContext!\n");
308  return false;
309  }
310 
311  if (shareContext != NULL && !m_pGLContext->isSharing())
312  {
313  printf("WARNING: CGLContext::CreateContext: sharing of GLContext failed!\n");
314  }
315 
316  m_pGLContext->makeCurrent();
317 
318  return true;
319 #else
320  return false;
321 #endif
322 }
323 
325 {
326 #ifdef USE_OPENGL
327  DoneCurrent();
328 
329  if (m_pGLContext)
330  {
331  delete m_pGLContext;
332  m_pGLContext = NULL;
333  }
334 
335  if (m_pPixmap)
336  {
337  delete m_pPixmap;
338  m_pPixmap = NULL;
339  }
340 
341  if (m_pApp)
342  {
343  delete m_pApp;
344  m_pApp = NULL;
345  }
346 #endif
347 }
348 
350 {
351 #ifdef USE_OPENGL
352  if (m_pGLContext)
353  m_pGLContext->makeCurrent();
354 #endif
355 }
356 
358 {
359 #ifdef USE_OPENGL
360  if (m_pGLContext)
361  m_pGLContext->clearCurrent();
362 #endif
363 }
364 
365 bool CGLContext::GetImage(CByteImage *pImage)
366 {
367 #ifdef USE_OPENGL
368  if (!m_pGLContext)
369  return false;
370 
371  int width = m_pPixmap->width();
372  int height = m_pPixmap->height();
373 
374  if (pImage->width != width || pImage->height != height)
375  {
376  printf("ERROR: CGLContext::GetImage: Image dimensions do not match (%d, %d) vs. (%d, %d)\n", pImage->width, pImage->height, width, height);
377  return false;
378  }
379 
380  glFlush();
381  m_pGLContext->swapBuffers();
382 
383  if (pImage->type == CByteImage::eRGB24)
384  {
385  glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pImage->pixels);
386 
387  unsigned char *tmp = new unsigned char[3*width];
388 
389  for (int i = 0; i < (height/2); i++)
390  {
391  memcpy(tmp, &pImage->pixels[3*i*width], 3*width);
392  memcpy(&pImage->pixels[3*i*width], &pImage->pixels[3*(height - i - 1)*width], 3*width);
393  memcpy(&pImage->pixels[3*(height - i - 1)*width], tmp, 3*width);
394  }
395 
396  delete [] tmp;
397  }
398  else
399  {
400  glReadPixels(0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, pImage->pixels);
401 
402  unsigned char *tmp = new unsigned char[width];
403 
404  for (int i = 0; i < (height/2); i++)
405  {
406  memcpy(tmp, &pImage->pixels[i*width], width);
407  memcpy(&pImage->pixels[i*width], &pImage->pixels[(height - i - 1)*width], width);
408  memcpy(&pImage->pixels[(height - i - 1)*width], tmp, width);
409  }
410 
411  delete [] tmp;
412  }
413 
414  return true;
415 #else
416  return false;
417 #endif
418 }
419 
420 #endif /* USE_QTGUI */
421 
422 
423 
424 #ifdef USE_COCOAGUI
425 
426 
427 // these functions are defined in GLContext.m
428 extern "C"
429 {
430  void* CocoaCreateGLContext(int width, int height, unsigned char* buffer);
431  void CocoaDeleteGLContext(void* ptr);
432  void CocoaMakeCurrentGLContext(void* ptr);
433  void CocoaDoneCurrentGLContext(void* ptr);
434  void CocoaSwapBuffersGLContext(void* ptr);
435 }
436 
438 : m_pGLContext(NULL), m_pBuffer(NULL)
439 {
440 }
442 {
443  DeleteContext();
444 }
445 
446 bool CGLContext::CreateContext(int width, int height, void *shareContext)
447 {
448 #ifdef USE_OPENGL
449  m_nWidth = width;
450  m_nHeight = height;
451 
452  // RGBA buffer
453  m_pBuffer = new unsigned char[width*height*4];
454 
455  m_pGLContext = CocoaCreateGLContext(width, height, m_pBuffer);
456  if (!m_pGLContext)
457  {
458  delete [] m_pBuffer;
459  m_pBuffer = NULL;
460 
461  return false;
462  }
463 
464  return true;
465 #else
466  return false;
467 #endif
468 }
469 
471 {
472 #ifdef USE_OPENGL
473  if (m_pGLContext)
474  {
475  CocoaDeleteGLContext(m_pGLContext);
476  m_pGLContext = NULL;
477 
478  delete [] m_pBuffer;
479  m_pBuffer = NULL;
480  }
481 #endif
482 }
483 
485 {
486 #ifdef USE_OPENGL
487  if (m_pGLContext)
488  CocoaMakeCurrentGLContext(m_pGLContext);
489 #endif
490 }
491 
493 {
494 #ifdef USE_OPENGL
495  if (m_pGLContext)
496  CocoaDoneCurrentGLContext(m_pGLContext);
497 #endif
498 }
499 
500 bool CGLContext::GetImage(CByteImage *pImage)
501 {
502 #ifdef USE_OPENGL
503  if (!m_pGLContext)
504  return false;
505 
506  if (pImage->width != m_nWidth || pImage->height != m_nHeight)
507  {
508  printf("error: CGLContext::GetImage: image dimensions do not match dimensions of the GL context!\n");
509  return false;
510  }
511 
512  glFlush();
513  CocoaSwapBuffersGLContext(m_pGLContext);
514 
515  if (pImage->type == CByteImage::eRGB24)
516  {
517  glReadPixels(0, 0, m_nWidth, m_nHeight, GL_RGB, GL_UNSIGNED_BYTE, pImage->pixels);
518 
519  unsigned char *pixels = pImage->pixels;
520  unsigned char *tmp = new unsigned char[3*m_nWidth];
521 
522  for (int i = 0; i < (m_nHeight/2); i++)
523  {
524  memcpy(tmp, &pixels[3*i*m_nWidth], 3*m_nWidth);
525  memcpy(&pixels[3*i*m_nWidth], &pixels[3*(m_nHeight - i - 1)*m_nWidth], 3*m_nWidth);
526  memcpy(&pixels[3*(m_nHeight - i - 1)*m_nWidth], tmp, 3*m_nWidth);
527  }
528 
529  delete [] tmp;
530  }
531  else
532  {
533  glReadPixels(0, 0, m_nWidth, m_nHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, pImage->pixels);
534 
535  unsigned char *tmp = new unsigned char[m_nWidth];
536 
537  for (int i = 0; i < (m_nHeight/2); i++)
538  {
539  memcpy(tmp, &pImage->pixels[i*m_nWidth], m_nWidth);
540  memcpy(&pImage->pixels[i*m_nWidth], &pImage->pixels[(m_nHeight - i - 1)*m_nWidth], m_nWidth);
541  memcpy(&pImage->pixels[(m_nHeight - i - 1)*m_nWidth], tmp, m_nWidth);
542  }
543 
544  delete [] tmp;
545  }
546 
547  return true;
548 #else
549  return false;
550 #endif
551 }
552 
553 
554 #endif /* USE_COCOAGUI */
555 
556 
557 #ifdef USE_GTKGUI
558 
560 : m_pXDisplay(NULL), m_glxpixmap(0), m_glxcontext(0)
561 {
562 }
564 {
565  DeleteContext();
566 }
567 
568 bool CGLContext::CreateContext(int width, int height, void *shareContext)
569 {
570 #ifdef USE_OPENGL
571  m_pXDisplay = XOpenDisplay(NULL);
572  if (!m_pXDisplay)
573  {
574  printf("CGLContext::CreateContext: couldn't open XServer connection.\n");
575  return false;
576  }
577 
578  if (glXQueryExtension(m_pXDisplay, NULL, NULL) == False)
579  {
580  printf("CGLContext::CreateContext: no OpenGL support.\n");
581  return false;
582  }
583 
584  m_nWidth = width;
585  m_nHeight = height;
586 
587  int attrlist[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 16, None};
588 
589  XVisualInfo *vi = glXChooseVisual(m_pXDisplay, DefaultScreen(m_pXDisplay), attrlist);
590  if (!vi)
591  {
592  printf("CGLContext::CreateContext: couldn't find a suitable Visual\n");
593  return false;
594  }
595 
596  m_pFrontBuffer = XCreatePixmap(m_pXDisplay, RootWindow(m_pXDisplay, vi->screen), m_nWidth, m_nHeight, vi->depth);
597  if (!m_pFrontBuffer)
598  {
599  XFree(vi);
600  DeleteContext();
601  printf("CGLContext::CreateContext: XCreatePixmap failed.\n");
602  return false;
603  }
604 
605  m_glxpixmap = glXCreateGLXPixmap(m_pXDisplay, vi, m_pFrontBuffer);
606  if (m_glxpixmap == None)
607  {
608  XFree(vi);
609  DeleteContext();
610  printf("CGLContext::CreateContext: glXCreateGLXPixmap failed.\n");
611  return false;
612  }
613 
614  if (shareContext)
615  m_glxcontext = glXCreateContext(m_pXDisplay, vi, (GLXContext)shareContext, False);
616  else
617  m_glxcontext = glXCreateContext(m_pXDisplay, vi, 0, False);
618 
619  if (m_glxcontext == NULL)
620  {
621  XFree(vi);
622  DeleteContext();
623  printf("CGLContext::CreateContext: glXCreateContext failed.\n");
624  return false;
625  }
626 
627  XFree(vi);
628 
629  return true;
630 #else
631  return false;
632 #endif
633 }
634 
636 {
637 #ifdef USE_OPENGL
638  if (!m_glxcontext)
639  return;
640 
641  glFinish();
642  glXWaitX();
643 
644  if (m_glxcontext == glXGetCurrentContext())
645  glXMakeCurrent(m_pXDisplay, None, NULL);
646 
647  if (m_glxpixmap != None) {
648  glXDestroyGLXPixmap(m_pXDisplay, m_glxpixmap);
649  glXWaitGL();
650  m_glxpixmap = None;
651  }
652 
653  if (m_pFrontBuffer) {
654  XFreePixmap(m_pXDisplay, m_pFrontBuffer);
655  glXWaitX();
656  m_pFrontBuffer = 0;
657  }
658 
659  if (m_glxcontext)
660  {
661  glXDestroyContext(m_pXDisplay, m_glxcontext);
662  m_glxcontext = NULL;
663  }
664 
665  if (m_pXDisplay)
666  {
667  XCloseDisplay(m_pXDisplay);
668  m_pXDisplay = NULL;
669  }
670 #endif
671 }
672 
674 {
675 #ifdef USE_OPENGL
676  if (m_glxcontext)
677  {
678  if (m_glxcontext != glXGetCurrentContext())
679  glXMakeCurrent(m_pXDisplay, m_glxpixmap, m_glxcontext);
680  }
681 #endif
682 }
683 
685 {
686 #ifdef USE_OPENGL
687  glXMakeCurrent(m_pXDisplay, None, NULL);
688 #endif
689 }
690 
691 bool CGLContext::GetImage(CByteImage *pImage)
692 {
693 #ifdef USE_OPENGL
694  if (!m_glxcontext)
695  return false;
696 
697  if (pImage->width != m_nWidth || pImage->height != m_nHeight)
698  {
699  printf("ERROR: CGLContext::GetImage: Image dimensions do not match (%d, %d) vs. (%d, %d)\n", pImage->width, pImage->height, m_nWidth, m_nHeight);
700  return false;
701  }
702 
703  glFlush();
704  glXSwapBuffers(m_pXDisplay, m_glxpixmap);
705 
706  if (pImage->type == CByteImage::eRGB24)
707  {
708  glReadPixels(0, 0, m_nWidth, m_nHeight, GL_RGB, GL_UNSIGNED_BYTE, pImage->pixels);
709 
710  unsigned char *tmp = new unsigned char[3*m_nWidth];
711 
712  for (int i = 0; i < (m_nHeight/2); i++)
713  {
714  memcpy(tmp, &pImage->pixels[3*i*m_nWidth], 3*m_nWidth);
715  memcpy(&pImage->pixels[3*i*m_nWidth], &pImage->pixels[3*(m_nHeight - i - 1)*m_nWidth], 3*m_nWidth);
716  memcpy(&pImage->pixels[3*(m_nHeight - i - 1)*m_nWidth], tmp, 3*m_nWidth);
717  }
718 
719  delete [] tmp;
720  }
721  else
722  {
723  glReadPixels(0, 0, m_nWidth, m_nHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, pImage->pixels);
724 
725  unsigned char *tmp = new unsigned char[m_nWidth];
726 
727  for (int i = 0; i < (m_nHeight/2); i++)
728  {
729  memcpy(tmp, &pImage->pixels[i*m_nWidth], m_nWidth);
730  memcpy(&pImage->pixels[i*m_nWidth], &pImage->pixels[(m_nHeight - i - 1)*m_nWidth], m_nWidth);
731  memcpy(&pImage->pixels[(m_nHeight - i - 1)*m_nWidth], tmp, m_nWidth);
732  }
733 
734  delete [] tmp;
735  }
736 
737  return true;
738 #else
739  return false;
740 #endif
741 }
742 
743 #endif /* USE_GTKGUI */
void MakeCurrent()
bool CreateContext(int width, int height, void *shareContext=0)
bool GetImage(CByteImage *pImage)
void DoneCurrent()
ImageType type
The type of the image.
Definition: ByteImage.h:292
int width
The width of the image in pixels.
Definition: ByteImage.h:257
int height
The height of the image in pixels.
Definition: ByteImage.h:264
unsigned char * pixels
The pointer to the the pixels.
Definition: ByteImage.h:283
Data structure for the representation of 8-bit grayscale images and 24-bit RGB (or HSV) color images ...
Definition: ByteImage.h:80
void DeleteContext()