1 /********************************************************************************
2 * *
3 * V i s u a l C l a s s *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1999,2021 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
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 *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/> *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "FXArray.h"
26 #include "FXHash.h"
27 #include "FXMutex.h"
28 #include "FXElement.h"
29 #include "FXStream.h"
30 #include "FXString.h"
31 #include "FXSize.h"
32 #include "FXPoint.h"
33 #include "FXRectangle.h"
34 #include "FXException.h"
35 #include "FXStringDictionary.h"
36 #include "FXSettings.h"
37 #include "FXRegistry.h"
38 #include "FXAccelTable.h"
39 #include "FXFont.h"
40 #include "FXEvent.h"
41 #include "FXWindow.h"
42 #include "FXApp.h"
43 #include "FXGLVisual.h"
44
45
46 /*
47 Notes:
48
49 - FXGLVisual builds a visual/pixelformat suitable for GL drawing.
50
51 - Selection of visual/pixelformat is based on a best match to a
52 given set of hints, according to some heuristics:
53
54 1) Prefer color depth close to asked ones; really like to
55 get a bit MORE color, rather than LESS, however.
56
57 2) If we wanted Z-buffer, it is STRONGLY preferred; If there's
58 a choice, we prefer more color depth over more Z-depth; if
59 we already have more colors than requested, we prefer to meet
60 requested Z depth.
61
62 3) If we wanted double buffer, we strongly prefer it over color and
63 Z depth, but HAVING a Z-buffer is still more important.
64
65 4) If we wanted alpha buffer, it is preferred, but Z-buffering
66 and double buffering are considered more important.
67 If there's a choice, we prefer to receive a few MORE bits of
68 alpha buffer than we asked for, rather than LESS.
69
70 5) If we wanted stereo, we prefer it, but almost everything except
71 the color-, alpha-, and Z-depths are more important.
72
73 - Some further tuning may be desired, but I think this should satisfy
74 most cases....
75
76 - Note that as long as OpenGL is in any way supported, you should ALWAYS
77 be able to get at least some visual/pixelformat you can draw on.
78
79 - As far as hardware acceleration goes, H/W acceleration should be
80 enabled, possibly at the expense of color-, alpha-, and Z-depth;
81 but NEVER at the expense of presence or absence of a requested feature.
82 We only drop FEATURES which are requested if there is neither hardware
83 nor software support.
84
85 For example, we may trade in some Z-depth, but not the entire Z-buffer,
86 to get a hardware accelerated visual/pixelformat.
87 */
88
89
90 using namespace FX;
91
92 /*******************************************************************************/
93
94 namespace FX {
95
96 // Object implementation
97 FXIMPLEMENT(FXGLVisual,FXVisual,NULL,0)
98
99
100 // Deserialization
FXGLVisual()101 FXGLVisual::FXGLVisual(){
102 redSize=0;
103 greenSize=0;
104 blueSize=0;
105 alphaSize=0;
106 depthSize=0;
107 stencilSize=0;
108 multiSamples=0;
109 accumRedSize=0;
110 accumGreenSize=0;
111 accumBlueSize=0;
112 accumAlphaSize=0;
113 actualRedSize=0;
114 actualGreenSize=0;
115 actualBlueSize=0;
116 actualAlphaSize=0;
117 actualDepthSize=0;
118 actualStencilSize=0;
119 actualMultiSamples=0;
120 actualAccumRedSize=0;
121 actualAccumGreenSize=0;
122 actualAccumBlueSize=0;
123 actualAccumAlphaSize=0;
124 doubleBuffer=false;
125 stereoBuffer=false;
126 accelerated=false;
127 copying=false;
128 }
129
130
131 // Construct
FXGLVisual(FXApp * a,FXuint flgs)132 FXGLVisual::FXGLVisual(FXApp* a,FXuint flgs):FXVisual(a,flgs,0){
133 FXTRACE((100,"FXGLVisual::FXGLVisual %p\n",this));
134 redSize=8;
135 greenSize=8;
136 blueSize=8;
137 alphaSize=0;
138 depthSize=24;
139 stencilSize=0;
140 multiSamples=0;
141 accumRedSize=0;
142 accumGreenSize=0;
143 accumBlueSize=0;
144 accumAlphaSize=0;
145 actualRedSize=0;
146 actualGreenSize=0;
147 actualBlueSize=0;
148 actualAlphaSize=0;
149 actualDepthSize=0;
150 actualStencilSize=0;
151 actualMultiSamples=0;
152 actualAccumRedSize=0;
153 actualAccumGreenSize=0;
154 actualAccumBlueSize=0;
155 actualAccumAlphaSize=0;
156 doubleBuffer=false;
157 stereoBuffer=false;
158 accelerated=false;
159 copying=false;
160 }
161
162
163 // Test if OpenGL is possible
hasOpenGL(FXApp * application)164 FXbool FXGLVisual::hasOpenGL(FXApp* application){
165 if(application->isInitialized()){
166 #ifdef HAVE_GL_H
167 #ifdef WIN32 // WIN32
168 return true;
169 #else // UNIX
170 return glXQueryExtension((Display*)application->getDisplay(),NULL,NULL);
171 #endif
172 #endif
173 }
174 return false;
175 }
176
177
178 /*******************************************************************************/
179
180 // Describes particular FB configuration
181 struct FXGLVisual::FXGLSpecs {
182 int redsize;
183 int greensize;
184 int bluesize;
185 int alphasize;
186 int depthsize;
187 int stencilsize;
188 int accumredsize;
189 int accumgreensize;
190 int accumbluesize;
191 int accumalphasize;
192 int doublebuffer;
193 int stereobuffer;
194 int multisamples;
195 int composition;
196 int image;
197 int accel;
198 int copy;
199 };
200
201
202 // Match actual GL depth to desired one
matchSpecs(const FXGLSpecs & s)203 FXint FXGLVisual::matchSpecs(const FXGLSpecs& s){
204 FXint match,dred,dgreen,dblue,dalpha,ddepth,dstencil,dsamples,daccred,daccgreen,daccblue,daccalpha;
205
206 // We prefer to get a few MORE bits in RGBA than we asked for
207 dred = s.redsize-redSize; if(dred<0) dred *= -100;
208 dgreen = s.greensize-greenSize; if(dgreen<0) dgreen *= -100;
209 dblue = s.bluesize-blueSize; if(dblue<0) dblue *= -100;
210 dalpha = s.alphasize-alphaSize; if(dalpha<0) dalpha *= -100;
211
212 // Prefer better Z than asked, but colors more important
213 ddepth = s.depthsize-depthSize; if(ddepth<0) ddepth *= -10;
214
215 // We care about colors and Z depth more than stencil depth
216 dstencil = s.stencilsize-stencilSize; if(dstencil<0) dstencil *= -1;
217
218 // Accumulation buffers
219 daccred=s.accumredsize-accumRedSize; if(daccred<0) daccred *= -1;
220 daccgreen=s.accumgreensize-accumGreenSize; if(daccgreen<0) daccgreen *= -1;
221 daccblue=s.accumbluesize-accumBlueSize; if(daccblue<0) daccblue *= -1;
222 daccalpha=s.accumalphasize-accumAlphaSize; if(daccalpha<0) daccalpha *= -1;
223
224 // Want the best colors, of course
225 match=dred+dgreen+dblue+dalpha;
226
227 // Accumulation buffers
228 match+=daccred+daccgreen+daccblue+daccalpha;
229
230 // Hardware accelerated is normally a plus
231 if(!s.accel && !(flags&VISUAL_NO_ACCEL)){
232 match+=10000;
233 }
234
235 // Extra penalty for no alpha if we asked for alpha, but no
236 // penalty at all if there is alpha and we didn't ask for it.
237 if(alphaSize>0){
238 if(s.alphasize<1) match+=100000;
239 }
240
241 // Wanted Z-buffer
242 if(depthSize>0){
243 if(s.depthsize<1) match+=10000000;
244 else match+=ddepth;
245 }
246 else{
247 if(s.depthsize>0) match+=10000000;
248 }
249
250 // Stencil buffers desired
251 if(stencilSize>0){
252 if(s.stencilsize<1) match+=10000;
253 else match+=dstencil;
254 }
255 else{
256 if(s.stencilsize>0) match+=1;
257 }
258
259 // Multisamples
260 if(multiSamples>0){
261 dsamples=s.multisamples-multiSamples;
262 if(dsamples<0) dsamples*=-10;
263 match+=dsamples;
264 }
265 else{
266 if(s.multisamples>0) match+=100;
267 }
268
269 // Double buffering also quite strongly preferred
270 if(flags&VISUAL_DOUBLE_BUFFER){
271 if(!s.doublebuffer) match+=1000000;
272 }
273 else{
274 if(s.doublebuffer) match+=1000000;
275 }
276
277 // Stereo not so important
278 if(flags&VISUAL_STEREO){
279 if(!s.stereobuffer) match+=10000;
280 }
281 else{
282 if(s.stereobuffer) match+=10000;
283 }
284
285 // Swap copies also important
286 if(flags&VISUAL_SWAP_COPY){
287 if(!s.copy) match+=10000000;
288 }
289
290 // Composition support would be nice to have
291 if(!s.composition) match+=100;
292
293 // Off-screen drawing would be nice
294 if(!s.image) match+=1;
295
296 return match;
297 }
298
299
300 #if defined(WIN32) ///////////////// WIN32 //////////////////////////////////////
301
302 #ifndef PFD_SUPPORT_COMPOSITION
303 #define PFD_SUPPORT_COMPOSITION 0x00008000
304 #endif
305
306 #ifdef HAVE_GL_H
307
308 // Palette struct
309 struct LOGPALETTE256 {
310 WORD palVersion;
311 WORD palNumEntries;
312 PALETTEENTRY palPalEntry[257];
313 };
314
315
316 // System colors to match against
317 static FXuchar defSysClr[20][3] = {
318 { 0, 0, 0},
319 {128, 0, 0},
320 { 0,128, 0},
321 {128,128, 0},
322 { 0, 0,128},
323 {128, 0,128},
324 { 0,128,128},
325 {192,192,192},
326
327 {192,220,192},
328 {166,202,240},
329 {255,251,240},
330 {160,160,164},
331
332 {128,128,128},
333 {255, 0, 0},
334 { 0,255, 0},
335 {255,255, 0},
336 { 0, 0,255},
337 {255, 0,255},
338 { 0,255,255},
339 {255,255,255}
340 };
341
342 static int defaultOverride[13] = {
343 0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
344 };
345
346
347 // Make palette
makeOpenGLPalette(PIXELFORMATDESCRIPTOR * info)348 static HPALETTE makeOpenGLPalette(PIXELFORMATDESCRIPTOR* info){
349 LOGPALETTE256 palette;
350 int num,i,j,rr,gg,bb;
351 int rmax,gmax,bmax;
352 HPALETTE hPalette;
353
354 // Size of palette array
355 num=1<<((PIXELFORMATDESCRIPTOR*)info)->cColorBits;
356
357 FXASSERT(num<=256);
358
359 // Maximum values each color
360 rmax=(1 << info->cRedBits)-1;
361 gmax=(1 << info->cGreenBits)-1;
362 bmax=(1 << info->cBlueBits)-1;
363
364 // Build palette
365 for(rr=0; rr<=rmax; rr++){
366 for(gg=0; gg<=gmax; gg++){
367 for(bb=0; bb<=bmax; bb++){
368 i = (rr << info->cRedShift) | (gg << info->cGreenShift) | (bb << info->cBlueShift);
369 palette.palPalEntry[i].peRed = (255*rr)/rmax;
370 palette.palPalEntry[i].peGreen = (255*gg)/gmax;
371 palette.palPalEntry[i].peBlue = (255*bb)/bmax;
372 palette.palPalEntry[i].peFlags = PC_NOCOLLAPSE;
373 }
374 }
375 }
376
377 // For 8-bit palette
378 if((info->cColorBits==8) && (info->cRedBits==3) && (info->cRedShift==0) && (info->cGreenBits==3) && (info->cGreenShift==3) && (info->cBlueBits==2) && (info->cBlueShift==6)){
379 for(j=1; j<=12; j++){
380 palette.palPalEntry[defaultOverride[j]].peRed=defSysClr[j][0];
381 palette.palPalEntry[defaultOverride[j]].peGreen=defSysClr[j][1];
382 palette.palPalEntry[defaultOverride[j]].peBlue=defSysClr[j][1];
383 palette.palPalEntry[defaultOverride[j]].peFlags=0;
384 }
385 }
386
387 // Fill in the rest
388 palette.palVersion=0x300;
389 palette.palNumEntries=num;
390
391 // Make palette
392 hPalette=CreatePalette((const LOGPALETTE*)&palette);
393
394 return hPalette;
395 }
396
397 #endif
398
399
400 // Initialize
create()401 void FXGLVisual::create(){
402 if(!xid){
403 if(getApp()->isInitialized()){
404 FXTRACE((100,"%s::create %p\n",getClassName(),this));
405 #ifdef HAVE_GL_H
406 PIXELFORMATDESCRIPTOR pfd;
407 int bestmatch=1000000000;
408 int best=-1;
409 int match;
410 int npf;
411 HDC hdc;
412
413 // Get some window handle
414 hdc=GetDC(GetDesktopWindow());
415
416 // Get number of supported pixel formats
417 pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
418 pfd.nVersion=1;
419
420 // Get number of supported pixel formats
421 if(0<(npf=DescribePixelFormat(hdc,1,sizeof(PIXELFORMATDESCRIPTOR),&pfd))){
422
423 FXTRACE((140,"Found %d OpenGL configs\n",npf));
424
425 // Try to find the best
426 for(int v=1; v<=npf; v++){
427 FXGLSpecs specs;
428
429 // Get info about this visual
430 DescribePixelFormat(hdc,v,sizeof(PIXELFORMATDESCRIPTOR),&pfd);
431
432 // Make sure this visual is valid
433 // if(ChoosePixelFormat(hdc,&pfd)!=v) continue;
434
435 // Get supported render type; we don't want index mode
436 if(pfd.iPixelType==PFD_TYPE_COLORINDEX) continue;
437
438 // OpenGL support is required
439 if(!(pfd.dwFlags&PFD_SUPPORT_OPENGL)) continue;
440
441 // Draw to window is required
442 if(!(pfd.dwFlags&PFD_DRAW_TO_WINDOW)) continue;
443
444 // Get planes
445 specs.redsize=pfd.cRedBits;
446 specs.greensize=pfd.cGreenBits;
447 specs.bluesize=pfd.cBlueBits;
448 specs.alphasize=pfd.cAlphaBits;
449 specs.depthsize=pfd.cDepthBits;
450 specs.stencilsize=pfd.cStencilBits;
451 specs.accumredsize=pfd.cAccumRedBits;
452 specs.accumgreensize=pfd.cAccumGreenBits;
453 specs.accumbluesize=pfd.cAccumBlueBits;
454 specs.accumalphasize=pfd.cAccumAlphaBits;
455
456 // Double buffer capable
457 specs.doublebuffer=(pfd.dwFlags&PFD_DOUBLEBUFFER)!=0;
458
459 // Stereo capable
460 specs.stereobuffer=(pfd.dwFlags&PFD_STEREO)!=0;
461
462 // Multisample
463 specs.multisamples=0;
464
465 // Windows Vista and Windows 7 composition support
466 specs.composition=(pfd.dwFlags&PFD_SUPPORT_COMPOSITION)!=0;
467
468 // Bitmap drawing would be nice
469 specs.image=(pfd.dwFlags&PFD_DRAW_TO_BITMAP)!=0;
470
471 // Hardware accelerated format
472 specs.accel=(pfd.dwFlags&PFD_GENERIC_FORMAT)==0;
473
474 // Swap buffers by copying
475 specs.copy=(pfd.dwFlags&PFD_SWAP_COPY)!=0;
476
477 // Match specs
478 match=matchSpecs(specs);
479
480 // Trace
481 FXTRACE((150,"Config: #%d: match=%d\n",v,match));
482 FXTRACE((150," drawables = %s%s\n",(pfd.dwFlags&PFD_DRAW_TO_WINDOW)?"PFD_DRAW_TO_WINDOW ":"",(pfd.dwFlags&PFD_DRAW_TO_BITMAP)?"PFD_DRAW_TO_BITMAP ":""));
483 FXTRACE((150," render = %s\n",(pfd.iPixelType==PFD_TYPE_COLORINDEX)?"PFD_TYPE_COLORINDEX":(pfd.iPixelType==PFD_TYPE_RGBA)?"PFD_TYPE_RGBA":""));
484 FXTRACE((150," red size = %d\n",specs.redsize));
485 FXTRACE((150," green size = %d\n",specs.greensize));
486 FXTRACE((150," blue size = %d\n",specs.bluesize));
487 FXTRACE((150," alpha size = %d\n",specs.alphasize));
488 FXTRACE((150," depth size = %d\n",specs.depthsize));
489 FXTRACE((150," stencil = %d\n",specs.stencilsize));
490 FXTRACE((150," acc red = %d\n",specs.accumredsize));
491 FXTRACE((150," acc green = %d\n",specs.accumgreensize));
492 FXTRACE((150," acc blue = %d\n",specs.accumbluesize));
493 FXTRACE((150," acc alpha = %d\n",specs.accumalphasize));
494 FXTRACE((150," double buf = %d\n",specs.doublebuffer));
495 FXTRACE((150," stereo buf = %d\n",specs.stereobuffer));
496 FXTRACE((150," samples = %d\n",specs.multisamples));
497 FXTRACE((150," accel = %d\n",specs.accel));
498
499 // May the best visual win
500 if(match<=bestmatch){
501 actualRedSize=specs.redsize;
502 actualGreenSize=specs.greensize;
503 actualBlueSize=specs.bluesize;
504 actualAlphaSize=specs.alphasize;
505 actualDepthSize=specs.depthsize;
506 actualStencilSize=specs.stencilsize;
507 actualMultiSamples=specs.multisamples;
508 actualAccumRedSize=specs.accumredsize;
509 actualAccumGreenSize=specs.accumgreensize;
510 actualAccumBlueSize=specs.accumbluesize;
511 actualAccumAlphaSize=specs.accumalphasize;
512 doubleBuffer=specs.doublebuffer;
513 stereoBuffer=specs.stereobuffer;
514 accelerated=specs.accel;
515 copying=specs.copy;
516 bestmatch=match;
517 best=v;
518 }
519 }
520 }
521
522 // Hopefully, we got one
523 if(0<=best){
524 FXTRACE((140,"Best Config: #%d: match=%d\n",best,bestmatch));
525
526 // Fill in visual data
527 depth=actualRedSize+actualGreenSize+actualBlueSize;
528 numred=(1<<actualRedSize);
529 numgreen=(1<<actualGreenSize);
530 numblue=(1<<actualBlueSize);
531 numcolors=numred*numgreen*numblue;
532
533 // Make a palette for it if needed
534 if(pfd.dwFlags&PFD_NEED_PALETTE){
535 colormap=makeOpenGLPalette(&pfd);
536 freemap=true;
537 }
538
539 // Remember best config
540 xid=(void*)(FXival)best;
541 }
542
543 // Done with that window
544 ::ReleaseDC(GetDesktopWindow(),hdc);
545
546 // Make non-current
547 wglMakeCurrent(NULL,NULL);
548 #endif
549 }
550
551 // Test if successful
552 if(!xid){
553 throw FXWindowException("unable to create GL context.");
554 }
555 }
556 }
557
558
559 #else //////////////////////////////// X11 OLD //////////////////////////////////
560
561
562 #ifndef GLX_ARB_multisample
563 #define GLX_SAMPLE_BUFFERS_ARB 100000
564 #define GLX_SAMPLES_ARB 100001
565 #endif
566 #ifndef GLX_EXT_visual_rating
567 #define GLX_VISUAL_CAVEAT_EXT 0x20
568 #define GLX_SLOW_VISUAL_EXT 0x8001
569 #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
570 #endif
571
572
573 // Initialize
create()574 void FXGLVisual::create(){
575 if(!xid){
576 if(getApp()->isInitialized()){
577 FXTRACE((100,"%s::create %p\n",getClassName(),this));
578 #ifdef HAVE_GL_H
579 int majoropcode,errorbase,eventbase;
580
581 // Assume the default
582 visual=DefaultVisual((Display*)getApp()->getDisplay(),DefaultScreen((Display*)getApp()->getDisplay()));
583 depth=DefaultDepth((Display*)getApp()->getDisplay(),DefaultScreen((Display*)getApp()->getDisplay()));
584
585 // OpenGL is available if we're talking to an OpenGL-capable X-Server
586 if(XQueryExtension((Display*)getApp()->getDisplay(),"GLX",&majoropcode,&errorbase,&eventbase)){
587 if(glXQueryExtension((Display*)getApp()->getDisplay(),&errorbase,&eventbase)){
588 int major,minor;
589
590 // Try get OpenGL version info
591 if(glXQueryVersion((Display*)getApp()->getDisplay(),&major,&minor)){
592 XVisualInfo vitemplate,*vi; int nvi;
593
594 // Report version found
595 FXTRACE((100,"Found GLX version: %d.%d (Major: %d, Error: %d, Event: %d)\n",major,minor,majoropcode,errorbase,eventbase));
596
597 // Scan for all visuals of given screen
598 vitemplate.screen=DefaultScreen((Display*)getApp()->getDisplay());
599 vi=XGetVisualInfo((Display*)getApp()->getDisplay(),VisualScreenMask,&vitemplate,&nvi);
600 if(vi){
601 int defvisualid=XVisualIDFromVisual(DefaultVisual((Display*)getApp()->getDisplay(),DefaultScreen((Display*)getApp()->getDisplay())));
602 int samplebuffers=0;
603 int bestmatch=1000000000;
604 int best=-1;
605 int value;
606 int match;
607
608 FXTRACE((150,"Found %d configs\n",nvi));
609 FXTRACE((150,"Default visualid=0x%02x\n",defvisualid));
610
611 // Find the best one
612 for(int v=0; v<nvi; v++){
613 FXGLSpecs specs;
614
615 // GL support is requested
616 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_USE_GL,&value)!=Success || (value==0)) continue;
617
618 // Get supported drawable targets
619 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_RGBA,&value)!=Success || (value==0)) continue;
620
621 // Get overlay level
622 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_LEVEL,&value)!=Success || (value!=0)) continue;
623
624 // Get plane depths
625 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_RED_SIZE,&specs.redsize)!=Success) continue;
626 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_GREEN_SIZE,&specs.greensize)!=Success) continue;
627 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_BLUE_SIZE,&specs.bluesize)!=Success) continue;
628 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_ALPHA_SIZE,&specs.alphasize)!=Success) continue;
629 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_DEPTH_SIZE,&specs.depthsize)!=Success) continue;
630 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_STENCIL_SIZE,&specs.stencilsize)!=Success) continue;
631 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_ACCUM_RED_SIZE,&specs.accumredsize)!=Success) continue;
632 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_ACCUM_GREEN_SIZE,&specs.accumgreensize)!=Success) continue;
633 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_ACCUM_BLUE_SIZE,&specs.accumbluesize)!=Success) continue;
634 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_ACCUM_ALPHA_SIZE,&specs.accumalphasize)!=Success) continue;
635
636 // Get stereo and double buffer support
637 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_DOUBLEBUFFER,&specs.doublebuffer)!=Success) continue;
638 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_STEREO,&specs.stereobuffer)!=Success) continue;
639
640 // Get multisample support (if we don't succeed, set it to zero)
641 specs.multisamples=0;
642 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_SAMPLE_BUFFERS_ARB,&samplebuffers)==Success && samplebuffers){
643 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_SAMPLES_ARB,&specs.multisamples)!=Success) continue;
644 }
645
646 // Check if accelerated or not (assume yes)
647 if(glXGetConfig((Display*)getApp()->getDisplay(),&vi[v],GLX_VISUAL_CAVEAT_EXT,&specs.accel)==Success){
648 specs.accel=(specs.accel!=GLX_SLOW_VISUAL_EXT); // Penalize if any caveats present
649 }
650 else{
651 specs.accel=1;
652 }
653
654 // Composition and swap copy
655 specs.composition=false;
656 specs.image=false;
657 specs.copy=false;
658
659 // Match specs
660 match=matchSpecs(specs);
661
662 // Trace
663 FXTRACE((150,"Config: #%d: match=%d\n",v,match));
664 FXTRACE((150," visualid = 0x%02lx\n",vi[v].visualid));
665 FXTRACE((150," red size = %d\n",specs.redsize));
666 FXTRACE((150," green size = %d\n",specs.greensize));
667 FXTRACE((150," blue size = %d\n",specs.bluesize));
668 FXTRACE((150," alpha size = %d\n",specs.alphasize));
669 FXTRACE((150," depth size = %d\n",specs.depthsize));
670 FXTRACE((150," stencil = %d\n",specs.stencilsize));
671 FXTRACE((150," acc red = %d\n",specs.accumredsize));
672 FXTRACE((150," acc green = %d\n",specs.accumgreensize));
673 FXTRACE((150," acc blue = %d\n",specs.accumbluesize));
674 FXTRACE((150," acc alpha = %d\n",specs.accumalphasize));
675 FXTRACE((150," double buf = %d\n",specs.doublebuffer));
676 FXTRACE((150," stereo buf = %d\n",specs.stereobuffer));
677 FXTRACE((150," samples = %d\n",specs.multisamples));
678 FXTRACE((150," accel = %d\n",specs.accel));
679
680 // May the best config win
681 if(match<=bestmatch){
682
683 // All other things being equal, we prefer default visual!
684 if((match<bestmatch) || (vi[v].visualid==defvisualid)){
685 actualRedSize=specs.redsize;
686 actualGreenSize=specs.greensize;
687 actualBlueSize=specs.bluesize;
688 actualAlphaSize=specs.alphasize;
689 actualDepthSize=specs.depthsize;
690 actualStencilSize=specs.stencilsize;
691 actualMultiSamples=specs.multisamples;
692 actualAccumRedSize=specs.accumredsize;
693 actualAccumGreenSize=specs.accumgreensize;
694 actualAccumBlueSize=specs.accumbluesize;
695 actualAccumAlphaSize=specs.accumalphasize;
696 doubleBuffer=specs.doublebuffer;
697 stereoBuffer=specs.stereobuffer;
698 accelerated=specs.accel;
699 copying=specs.copy;
700 bestmatch=match;
701 best=v;
702 }
703 }
704 }
705
706 // We should have one now
707 if(0<=best){
708 FXTRACE((140,"Best Config: #%d: match=%d\n",best,bestmatch));
709
710 // Remember visual, depth, visualid
711 visual=vi[best].visual;
712 depth=vi[best].depth;
713
714 // Initialize colormap
715 setupcolormap();
716
717 // Make GC's for this visual
718 scrollgc=setupgc(true);
719 gc=setupgc(false);
720
721 // Remember best config
722 xid=((Visual*)visual)->visualid;
723 }
724
725 // Free visual info
726 XFree((char*)vi);
727 }
728 }
729 }
730 }
731 #endif
732 }
733
734 // Test if successful
735 if(!xid){
736 throw FXWindowException("no matching GL configuration.");
737 }
738 }
739 }
740
741
742 #endif //////////////////////////////////////////////////////////////////////////
743
744
745 // Detach visual
detach()746 void FXGLVisual::detach(){
747 #ifdef HAVE_GL_H
748 if(xid){
749 FXTRACE((100,"%s::detach %p\n",getClassName(),this));
750 colormap=0;
751 freemap=false;
752 xid=0;
753 }
754 #endif
755 }
756
757
758 // Destroy visual
destroy()759 void FXGLVisual::destroy(){
760 #ifdef HAVE_GL_H
761 if(xid){
762 if(getApp()->isInitialized()){
763 FXTRACE((100,"%s::destroy %p\n",getClassName(),this));
764 #ifdef WIN32
765 if(colormap){ DeleteObject(colormap); }
766 #else
767 if(freemap){ XFreeColormap((Display*)getApp()->getDisplay(),colormap); }
768 if(scrollgc){ XFreeGC((Display*)getApp()->getDisplay(),(GC)scrollgc); }
769 if(gc){ XFreeGC((Display*)getApp()->getDisplay(),(GC)gc); }
770 #endif
771 }
772 #ifndef WIN32
773 scrollgc=0;
774 gc=0;
775 #endif
776 colormap=0;
777 freemap=false;
778 xid=0;
779 }
780 #endif
781 }
782
783
784 // Save to stream
save(FXStream & store) const785 void FXGLVisual::save(FXStream& store) const {
786 FXVisual::save(store);
787 store << redSize;
788 store << greenSize;
789 store << blueSize;
790 store << alphaSize;
791 store << depthSize;
792 store << stencilSize;
793 store << multiSamples;
794 store << accumRedSize;
795 store << accumGreenSize;
796 store << accumBlueSize;
797 store << accumAlphaSize;
798 }
799
800
801 // Load from stream
load(FXStream & store)802 void FXGLVisual::load(FXStream& store){
803 FXVisual::load(store);
804 store >> redSize;
805 store >> greenSize;
806 store >> blueSize;
807 store >> alphaSize;
808 store >> depthSize;
809 store >> stencilSize;
810 store >> multiSamples;
811 store >> accumRedSize;
812 store >> accumGreenSize;
813 store >> accumBlueSize;
814 store >> accumAlphaSize;
815 }
816
817
818 // Destroy
~FXGLVisual()819 FXGLVisual::~FXGLVisual(){
820 FXTRACE((100,"FXGLVisual::~FXGLVisual %p\n",this));
821 destroy();
822 }
823
824
825 }
826