2 // "$Id: Fl_Gl_Choice.cxx 8396 2011-02-07 13:51:17Z manolo $"
4 // OpenGL visual selection code for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
34 # include "Fl_Gl_Choice.H"
35 # include <FL/gl_draw.H>
36 # include "flstring.h"
37 # include <FL/fl_utf8.h>
40 # include <ApplicationServices/ApplicationServices.h>
41 # include <FL/Fl_Window.H>
45 void fl_save_dc(HWND
, HDC
);
48 static Fl_Gl_Choice
*first
;
50 // this assumes one of the two arguments is zero:
51 // We keep the list system in Win32 to stay compatible and interpret
53 Fl_Gl_Choice
*Fl_Gl_Choice::find(int m
, const int *alistp
) {
56 for (g
= first
; g
; g
= g
->next
)
57 if (g
->mode
== m
&& g
->alist
== alistp
)
69 list
[n
++] = GLX_BUFFER_SIZE
;
70 list
[n
++] = 8; // glut tries many sizes, but this should work...
73 list
[n
++] = GLX_GREEN_SIZE
;
74 list
[n
++] = (m
& FL_RGB8
) ? 8 : 1;
76 list
[n
++] = GLX_ALPHA_SIZE
;
77 list
[n
++] = (m
& FL_RGB8
) ? 8 : 1;
80 list
[n
++] = GLX_ACCUM_GREEN_SIZE
;
83 list
[n
++] = GLX_ACCUM_ALPHA_SIZE
;
89 list
[n
++] = GLX_DOUBLEBUFFER
;
92 list
[n
++] = GLX_DEPTH_SIZE
; list
[n
++] = 1;
95 list
[n
++] = GLX_STENCIL_SIZE
; list
[n
++] = 1;
98 list
[n
++] = GLX_STEREO
;
100 # if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
101 if (m
& FL_MULTISAMPLE
) {
102 list
[n
++] = GLX_SAMPLES_SGIS
;
103 list
[n
++] = 4; // value Glut uses
111 XVisualInfo
*visp
= glXChooseVisual(fl_display
, fl_screen
, (int *)blist
);
113 # if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
114 if (m
&FL_MULTISAMPLE
) return find(m
&~FL_MULTISAMPLE
,0);
119 #elif defined(__APPLE_QUARTZ__)
120 // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
129 list
[n
++] = AGL_BUFFER_SIZE
;
130 list
[n
++] = 8; // glut tries many sizes, but this should work...
132 list
[n
++] = AGL_RGBA
;
133 list
[n
++] = AGL_GREEN_SIZE
;
134 list
[n
++] = (m
& FL_RGB8
) ? 8 : 1;
136 list
[n
++] = AGL_ALPHA_SIZE
;
137 list
[n
++] = (m
& FL_RGB8
) ? 8 : 1;
140 list
[n
++] = AGL_ACCUM_GREEN_SIZE
;
143 list
[n
++] = AGL_ACCUM_ALPHA_SIZE
;
149 list
[n
++] = AGL_DOUBLEBUFFER
;
152 list
[n
++] = AGL_DEPTH_SIZE
; list
[n
++] = 24;
154 if (m
& FL_STENCIL
) {
155 list
[n
++] = AGL_STENCIL_SIZE
; list
[n
++] = 1;
159 list
[n
++] = AGL_STEREO
;
166 AGLPixelFormat fmt
= aglChoosePixelFormat(NULL
, 0, (GLint
*)blist
);
171 // Replacement for ChoosePixelFormat() that finds one with an overlay
173 if (!fl_gc
) fl_GetDC(0);
175 PIXELFORMATDESCRIPTOR chosen_pfd
;
176 for (int i
= 1; ; i
++) {
177 PIXELFORMATDESCRIPTOR pfd
;
178 if (!DescribePixelFormat(fl_gc
, i
, sizeof(pfd
), &pfd
)) break;
179 // continue if it does not satisfy our requirements:
180 if (~pfd
.dwFlags
& (PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
)) continue;
181 if (pfd
.iPixelType
!= ((m
&FL_INDEX
)?PFD_TYPE_COLORINDEX
:PFD_TYPE_RGBA
)) continue;
182 if ((m
& FL_ALPHA
) && !pfd
.cAlphaBits
) continue;
183 if ((m
& FL_ACCUM
) && !pfd
.cAccumBits
) continue;
184 if ((!(m
& FL_DOUBLE
)) != (!(pfd
.dwFlags
& PFD_DOUBLEBUFFER
))) continue;
185 if ((!(m
& FL_STEREO
)) != (!(pfd
.dwFlags
& PFD_STEREO
))) continue;
186 if ((m
& FL_DEPTH
) && !pfd
.cDepthBits
) continue;
187 if ((m
& FL_STENCIL
) && !pfd
.cStencilBits
) continue;
188 // see if better than the one we have already:
190 // offering non-generic rendering is better (read: hardware accelleration)
191 if (!(chosen_pfd
.dwFlags
& PFD_GENERIC_FORMAT
) &&
192 (pfd
.dwFlags
& PFD_GENERIC_FORMAT
)) continue;
193 // offering overlay is better:
194 else if (!(chosen_pfd
.bReserved
& 15) && (pfd
.bReserved
& 15)) {}
195 // otherwise more bit planes is better:
196 else if (chosen_pfd
.cColorBits
> pfd
.cColorBits
) continue;
197 else if (chosen_pfd
.cDepthBits
> pfd
.cDepthBits
) continue;
202 //printf("Chosen pixel format is %d\n", pixelformat);
203 if (!pixelformat
) return 0;
205 # error platform unsupported
208 g
= new Fl_Gl_Choice
;
217 if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */
218 visp
->visualid
== fl_visual
->visualid
&&
219 !fl_getenv("MESA_PRIVATE_CMAP"))
220 g
->colormap
= fl_colormap
;
222 g
->colormap
= XCreateColormap(fl_display
, RootWindow(fl_display
,fl_screen
),
223 visp
->visual
, AllocNone
);
224 # elif defined(WIN32)
225 g
->pixelformat
= pixelformat
;
227 # elif defined(__APPLE_QUARTZ__)
228 // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
229 g
->pixelformat
= fmt
;
231 # error unsupported platform
237 static GLContext
*context_list
= 0;
238 static int nContext
= 0, NContext
= 0;
240 static void add_context(GLContext ctx
) {
242 if (nContext
==NContext
) {
243 if (!NContext
) NContext
= 8;
245 context_list
= (GLContext
*)realloc(
246 context_list
, NContext
*sizeof(GLContext
));
248 context_list
[nContext
++] = ctx
;
251 static void del_context(GLContext ctx
) {
253 for (i
=0; i
<nContext
; i
++) {
254 if (context_list
[i
]==ctx
) {
255 memmove(context_list
+i
, context_list
+i
+1,
256 (nContext
-i
-1) * sizeof(GLContext
));
257 context_list
[--nContext
] = 0;
261 if (!nContext
) gl_remove_displaylist_fonts();
266 GLContext
fl_create_gl_context(XVisualInfo
* vis
) {
267 GLContext shared_ctx
= 0;
268 if (context_list
&& nContext
) shared_ctx
= context_list
[0];
269 GLContext context
= glXCreateContext(fl_display
, vis
, shared_ctx
, 1);
271 add_context(context
);
277 GLContext
fl_create_gl_context(Fl_Window
* window
, const Fl_Gl_Choice
* g
, int layer
) {
278 Fl_X
* i
= Fl_X::i(window
);
279 HDC hdc
= i
->private_dc
;
281 hdc
= i
->private_dc
= GetDCEx(i
->xid
, 0, DCX_CACHE
);
282 fl_save_dc(i
->xid
, hdc
);
283 SetPixelFormat(hdc
, g
->pixelformat
, (PIXELFORMATDESCRIPTOR
*)(&g
->pfd
));
285 if (fl_palette
) SelectPalette(hdc
, fl_palette
, FALSE
);
289 layer
? wglCreateLayerContext(hdc
, layer
) : wglCreateContext(hdc
);
291 if (context_list
&& nContext
)
292 wglShareLists(context_list
[0], context
);
293 add_context(context
);
298 # elif defined(__APPLE_QUARTZ__)
299 #if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && __LP64__)
300 static CGrafPtr
fl_GetWindowPort(WindowRef window
)
302 typedef CGrafPtr (*wf
)(WindowRef
);
304 if ( ! f
) f
= (wf
)Fl_X::get_carbon_function("GetWindowPort");
309 // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
310 GLContext
fl_create_gl_context(Fl_Window
* window
, const Fl_Gl_Choice
* g
, int layer
) {
311 GLContext context
, shared_ctx
= 0;
312 if (context_list
&& nContext
) shared_ctx
= context_list
[0];
313 context
= aglCreateContext( g
->pixelformat
, shared_ctx
);
314 if (!context
) return 0;
315 add_context((GLContext
)context
);
316 if ( window
->parent() ) {
317 int H
= window
->window()->h();
318 GLint rect
[] = { window
->x(), H
-window
->h()-window
->y(), window
->w(), window
->h() };
319 aglSetInteger( (GLContext
)context
, AGL_BUFFER_RECT
, rect
);
320 aglEnable( (GLContext
)context
, AGL_BUFFER_RECT
);
322 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
325 aglSetWindowRef(context
, Fl_X::i(window
)->window_ref() );
327 // 32 bit version >= 10.5
328 if (aglSetWindowRef
!= NULL
)
329 aglSetWindowRef(context
, Fl_X::i(window
)->window_ref() );
331 aglSetDrawable( context
, fl_GetWindowPort( Fl_X::i(window
)->window_ref() ) );
334 // 32 bit version < 10.5
335 aglSetDrawable( context
, fl_GetWindowPort( Fl_X::i(window
)->window_ref() ) );
340 # error unsupported platform
343 static GLContext cached_context
;
344 static Fl_Window
* cached_window
;
346 void fl_set_gl_context(Fl_Window
* w
, GLContext context
) {
347 if (context
!= cached_context
|| w
!= cached_window
) {
348 cached_context
= context
;
350 # if defined(USE_X11)
351 glXMakeCurrent(fl_display
, fl_xid(w
), context
);
352 # elif defined(WIN32)
353 wglMakeCurrent(Fl_X::i(w
)->private_dc
, context
);
354 # elif defined(__APPLE_QUARTZ__)
355 // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
356 if ( w
->parent() ) { //: resize our GL buffer rectangle
357 int H
= w
->window()->h();
358 GLint rect
[] = { w
->x(), H
-w
->h()-w
->y(), w
->w(), w
->h() };
359 aglSetInteger( context
, AGL_BUFFER_RECT
, rect
);
360 aglEnable( context
, AGL_BUFFER_RECT
);
362 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
365 aglSetWindowRef(context
, Fl_X::i(w
)->window_ref() );
367 // 32 bit version >= 10.5
368 if (aglSetWindowRef
!= NULL
)
369 aglSetWindowRef(context
, Fl_X::i(w
)->window_ref() );
371 aglSetDrawable( context
, fl_GetWindowPort( Fl_X::i(w
)->window_ref() ) );
374 // 32 bit version < 10.5
375 aglSetDrawable( context
, fl_GetWindowPort( Fl_X::i(w
)->window_ref() ) );
377 aglSetCurrentContext(context
);
379 # error unsupported platform
384 void fl_no_gl_context() {
387 # if defined(USE_X11)
388 glXMakeCurrent(fl_display
, 0, 0);
389 # elif defined(WIN32)
390 wglMakeCurrent(0, 0);
391 # elif defined(__APPLE_QUARTZ__)
392 // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
393 AGLContext ctx
= aglGetCurrentContext();
394 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
395 if (aglSetWindowRef
!= NULL
)
396 { if(ctx
) aglSetWindowRef(ctx
, NULL
); }
399 if(ctx
) aglSetDrawable( ctx
, NULL
);
400 aglSetCurrentContext(0);
402 # error unsupported platform
406 void fl_delete_gl_context(GLContext context
) {
407 if (cached_context
== context
) fl_no_gl_context();
408 # if defined(USE_X11)
409 glXDestroyContext(fl_display
, context
);
410 # elif defined(WIN32)
411 wglDeleteContext(context
);
412 # elif defined(__APPLE_QUARTZ__)
413 // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
414 aglDestroyContext( context
);
416 # error unsupported platform
418 del_context(context
);
425 // End of "$Id: Fl_Gl_Choice.cxx 8396 2011-02-07 13:51:17Z manolo $".