summaryrefslogtreecommitdiffstats
path: root/src/opengl/qgl.cpp
blob: 83b27a0c3b852ab8acbb17171a6afb9ca4577512 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
/****************************************************************************
**
** Implementation of OpenGL classes for TQt
**
** Created : 970112
**
** Copyright (C) 1992-2008 Trolltech ASA.  All rights reserved.
**
** This file is part of the opengl module of the TQt GUI Toolkit.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free TQt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** This file may be used under the terms of the Q Public License as
** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
** included in the packaging of this file.  Licensees holding valid TQt
** Commercial licenses may use this file in accordance with the TQt
** Commercial License Agreement provided with the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/

#include "ntqgl.h"
#include "ntqpixmap.h"
#include "ntqpaintdevicemetrics.h"
#include "ntqimage.h"
#include "ntqcleanuphandler.h"
#include "ntqptrdict.h"

static TQGLFormat* qgl_default_format = 0;
static TQGLFormat* qgl_default_overlay_format = 0;

#if defined(TQ_WS_X11)
#include "private/qt_x11_p.h"
#define INT32 dummy_INT32
#define INT8 dummy_INT8
#include <GL/glx.h>
#undef INT32
#undef INT8
#include "qgl_x11_p.h"
#endif

static TQCleanupHandler<TQGLFormat> qgl_cleanup_format;


/*!
    \class TQGL ntqgl.h
    \brief The TQGL class is a namespace for miscellaneous identifiers
    in the TQt OpenGL module.
\if defined(commercial)
    It is part of the <a href="commercialeditions.html">TQt Enterprise Edition</a>.
\endif

    \module OpenGL
    \ingroup graphics
    \ingroup images


    Normally you can ignore this class. TQGLWidget and the other
    OpenGL<sup>*</sup> module classes inherit it, so when you make your
    own TQGLWidget subclass you can use the identifiers in the TQGL
    namespace without qualification.

    However, you may occasionally find yourself in situations where you
    need to refer to these identifiers from outside the TQGL namespace's
    scope, e.g. in static functions. In such cases, simply write e.g. \c
    TQGL::DoubleBuffer instead of just \c DoubleBuffer.

    <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
    United States and other countries.

*/


/*****************************************************************************
  TQGLFormat implementation
 *****************************************************************************/


/*!
    \class TQGLFormat ntqgl.h
    \brief The TQGLFormat class specifies the display format of an OpenGL
    rendering context.
\if defined(commercial)
    It is part of the <a href="commercialeditions.html">TQt Enterprise Edition</a>.
\endif

    \ingroup graphics
    \ingroup images
    \module OpenGL

    A display format has several characteristics:
    \list
    \i \link setDoubleBuffer() Double or single buffering.\endlink
    \i \link setDepth() Depth buffer.\endlink
    \i \link setRgba() RGBA or color index mode.\endlink
    \i \link setAlpha() Alpha channel.\endlink
    \i \link setAccum() Accumulation buffer.\endlink
    \i \link setStencil() Stencil buffer.\endlink
    \i \link setStereo() Stereo buffers.\endlink
    \i \link setDirectRendering() Direct rendering.\endlink
    \i \link setOverlay() Presence of an overlay.\endlink
    \i \link setPlane() The plane of an overlay format.\endlink
    \endlist

    You create and tell a TQGLFormat object what rendering options you
    want from an OpenGL<sup>*</sup> rendering context.

    OpenGL drivers or accelerated hardware may or may not support
    advanced features such as alpha channel or stereographic viewing.
    If you request some features that the driver/hardware does not
    provide when you create a TQGLWidget, you will get a rendering
    context with the nearest subset of features.

    There are different ways to define the display characteristics of
    a rendering context. One is to create a TQGLFormat and make it the
    default for the entire application:
    \code
    TQGLFormat f;
    f.setAlpha( TRUE );
    f.setStereo( TRUE );
    TQGLFormat::setDefaultFormat( f );
    \endcode

    Or you can specify the desired format when creating an object of
    your TQGLWidget subclass:
    \code
    TQGLFormat f;
    f.setDoubleBuffer( FALSE );                 // single buffer
    f.setDirectRendering( FALSE );              // software rendering
    MyGLWidget* myWidget = new MyGLWidget( f, ... );
    \endcode

    After the widget has been created, you can find out which of the
    requested features the system was able to provide:
    \code
    TQGLFormat f;
    f.setOverlay( TRUE );
    f.setStereo( TRUE );
    MyGLWidget* myWidget = new MyGLWidget( f, ... );
    if ( !w->format().stereo() ) {
	// ok, goggles off
	if ( !w->format().hasOverlay() ) {
	    tqFatal( "Cool hardware required" );
	}
    }
    \endcode

    <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
    United States and other countries.

    \sa TQGLContext, TQGLWidget
*/


/*!
    Constructs a TQGLFormat object with the factory default settings:
    \list
    \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
    \i \link setDepth() Depth buffer:\endlink Enabled.
    \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled).
    \i \link setAlpha() Alpha channel:\endlink Disabled.
    \i \link setAccum() Accumulator buffer:\endlink Disabled.
    \i \link setStencil() Stencil buffer:\endlink Disabled.
    \i \link setStereo() Stereo:\endlink Disabled.
    \i \link setDirectRendering() Direct rendering:\endlink Enabled.
    \i \link setOverlay() Overlay:\endlink Disabled.
    \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
    \endlist
*/

TQGLFormat::TQGLFormat()
{
    opts = DoubleBuffer | DepthBuffer | Rgba | DirectRendering;
    pln = 0;
}


/*!
    Creates a TQGLFormat object that is a copy of the current \link
    defaultFormat() application default format\endlink.

    If \a options is not 0, this copy is modified by these format
    options. The \a options parameter should be \c FormatOption values
    OR'ed together.

    This constructor makes it easy to specify a certain desired format
    in classes derived from TQGLWidget, for example:
    \code
    // The rendering in MyGLWidget depends on using
    // stencil buffer and alpha channel
    MyGLWidget::MyGLWidget( TQWidget* parent, const char* name )
	: TQGLWidget( TQGLFormat( StencilBuffer | AlphaChannel ), parent, name )
    {
	if ( !format().stencil() )
	    tqWarning( "Could not get stencil buffer; results will be suboptimal" );
	if ( !format().alphaChannel() )
	    tqWarning( "Could not get alpha channel; results will be suboptimal" );
	...
    }
    \endcode

    Note that there are \c FormatOption values to turn format settings
    both on and off, e.g. \c DepthBuffer and \c NoDepthBuffer,
    \c DirectRendering and \c IndirectRendering, etc.

    The \a plane parameter defaults to 0 and is the plane which this
    format should be associated with. Not all OpenGL implmentations
    supports overlay/underlay rendering planes.

    \sa defaultFormat(), setOption()
*/

TQGLFormat::TQGLFormat( int options, int plane )
{
    uint newOpts = options;
    opts = defaultFormat().opts;
    opts |= ( newOpts & 0xffff );
    opts &= ~( newOpts >> 16 );
    pln = plane;
}


/*!
    \fn bool TQGLFormat::doubleBuffer() const

    Returns TRUE if double buffering is enabled; otherwise returns
    FALSE. Double buffering is enabled by default.

    \sa setDoubleBuffer()
*/

/*!
    If \a enable is TRUE sets double buffering; otherwise sets single
    buffering.

    Double buffering is enabled by default.

    Double buffering is a technique where graphics are rendered on an
    off-screen buffer and not directly to the screen. When the drawing
    has been completed, the program calls a swapBuffers() function to
    exchange the screen contents with the buffer. The result is
    flicker-free drawing and often better performance.

    \sa doubleBuffer(), TQGLContext::swapBuffers(),
    TQGLWidget::swapBuffers()
*/

void TQGLFormat::setDoubleBuffer( bool enable )
{
    setOption( enable ? DoubleBuffer : SingleBuffer );
}


/*!
    \fn bool TQGLFormat::depth() const

    Returns TRUE if the depth buffer is enabled; otherwise returns
    FALSE. The depth buffer is enabled by default.

    \sa setDepth()
*/

/*!
    If \a enable is TRUE enables the depth buffer; otherwise disables
    the depth buffer.

    The depth buffer is enabled by default.

    The purpose of a depth buffer (or Z-buffering) is to remove hidden
    surfaces. Pixels are assigned Z values based on the distance to
    the viewer. A pixel with a high Z value is closer to the viewer
    than a pixel with a low Z value. This information is used to
    decide whether to draw a pixel or not.

    \sa depth()
*/

void TQGLFormat::setDepth( bool enable )
{
    setOption( enable ? DepthBuffer : NoDepthBuffer );
}


/*!
    \fn bool TQGLFormat::rgba() const

    Returns TRUE if RGBA color mode is set. Returns FALSE if color
    index mode is set. The default color mode is RGBA.

    \sa setRgba()
*/

/*!
    If \a enable is TRUE sets RGBA mode. If \a enable is FALSE sets
    color index mode.

    The default color mode is RGBA.

    RGBA is the preferred mode for most OpenGL applications. In RGBA
    color mode you specify colors as red + green + blue + alpha
    quadruplets.

    In color index mode you specify an index into a color lookup
    table.

    \sa rgba()
*/

void TQGLFormat::setRgba( bool enable )
{
    setOption( enable ? Rgba : ColorIndex );
}


/*!
    \fn bool TQGLFormat::alpha() const

    Returns TRUE if the alpha channel of the framebuffer is enabled;
    otherwise returns FALSE. The alpha channel is disabled by default.

    \sa setAlpha()
*/

/*!
    If \a enable is TRUE enables the alpha channel; otherwise disables
    the alpha channel.

    The alpha buffer is disabled by default.

    The alpha channel is typically used for implementing transparency
    or translucency. The A in RGBA specifies the transparency of a
    pixel.

    \sa alpha()
*/

void TQGLFormat::setAlpha( bool enable )
{
    setOption( enable ? AlphaChannel : NoAlphaChannel );
}


/*!
    \fn bool TQGLFormat::accum() const

    Returns TRUE if the accumulation buffer is enabled; otherwise
    returns FALSE. The accumulation buffer is disabled by default.

    \sa setAccum()
*/

/*!
    If \a enable is TRUE enables the accumulation buffer; otherwise
    disables the accumulation buffer.

    The accumulation buffer is disabled by default.

    The accumulation buffer is used to create blur effects and
    multiple exposures.

    \sa accum()
*/

void TQGLFormat::setAccum( bool enable )
{
    setOption( enable ? AccumBuffer : NoAccumBuffer );
}


/*!
    \fn bool TQGLFormat::stencil() const

    Returns TRUE if the stencil buffer is enabled; otherwise returns
    FALSE. The stencil buffer is disabled by default.

    \sa setStencil()
*/

/*!
    If \a enable is TRUE enables the stencil buffer; otherwise
    disables the stencil buffer.

    The stencil buffer is disabled by default.

    The stencil buffer masks certain parts of the drawing area so that
    masked parts are not drawn on.

    \sa stencil()
*/

void TQGLFormat::setStencil( bool enable )
{
    setOption( enable ? StencilBuffer: NoStencilBuffer );
}


/*!
    \fn bool TQGLFormat::stereo() const

    Returns TRUE if stereo buffering is enabled; otherwise returns
    FALSE. Stereo buffering is disabled by default.

    \sa setStereo()
*/

/*!
    If \a enable is TRUE enables stereo buffering; otherwise disables
    stereo buffering.

    Stereo buffering is disabled by default.

    Stereo buffering provides extra color buffers to generate left-eye
    and right-eye images.

    \sa stereo()
*/

void TQGLFormat::setStereo( bool enable )
{
    setOption( enable ? StereoBuffers : NoStereoBuffers );
}


/*!
    \fn bool TQGLFormat::directRendering() const

    Returns TRUE if direct rendering is enabled; otherwise returns
    FALSE.

    Direct rendering is enabled by default.

    \sa setDirectRendering()
*/

/*!
    If \a enable is TRUE enables direct rendering; otherwise disables
    direct rendering.

    Direct rendering is enabled by default.

    Enabling this option will make OpenGL bypass the underlying window
    system and render directly from hardware to the screen, if this is
    supported by the system.

    \sa directRendering()
*/

void TQGLFormat::setDirectRendering( bool enable )
{
    setOption( enable ? DirectRendering : IndirectRendering );
}


/*!
    \fn bool TQGLFormat::hasOverlay() const

    Returns TRUE if overlay plane is enabled; otherwise returns FALSE.

    Overlay is disabled by default.

    \sa setOverlay()
*/

/*!
    If \a enable is TRUE enables an overlay plane; otherwise disables
    the overlay plane.

    Enabling the overlay plane will cause TQGLWidget to create an
    additional context in an overlay plane. See the TQGLWidget
    documentation for further information.

    \sa hasOverlay()
*/

void TQGLFormat::setOverlay( bool enable )
{
    setOption( enable ? HasOverlay : NoOverlay );
}

/*!
    Returns the plane of this format. The default for normal formats
    is 0, which means the normal plane. The default for overlay
    formats is 1, which is the first overlay plane.

    \sa setPlane()
*/
int TQGLFormat::plane() const
{
    return pln;
}

/*!
    Sets the requested plane to \a plane. 0 is the normal plane, 1 is
    the first overlay plane, 2 is the second overlay plane, etc.; -1,
    -2, etc. are underlay planes.

    Note that in contrast to other format specifications, the plane
    specifications will be matched exactly. This means that if you
    specify a plane that the underlying OpenGL system cannot provide,
    an \link TQGLWidget::isValid() invalid\endlink TQGLWidget will be
    created.

    \sa plane()
*/
void TQGLFormat::setPlane( int plane )
{
    pln = plane;
}

/*!
    Sets the format option to \a opt.

    \sa testOption()
*/

void TQGLFormat::setOption( FormatOption opt )
{
    if ( opt & 0xffff )
	opts |= opt;
    else
       opts &= ~( opt >> 16 );
}



/*!
    Returns TRUE if format option \a opt is set; otherwise returns FALSE.

    \sa setOption()
*/

bool TQGLFormat::testOption( FormatOption opt ) const
{
    if ( opt & 0xffff )
       return ( opts & opt ) != 0;
    else
       return ( opts & ( opt >> 16 ) ) == 0;
}



/*!
    \fn bool TQGLFormat::hasOpenGL()

    Returns TRUE if the window system has any OpenGL support;
    otherwise returns FALSE.

    \warning This function must not be called until the TQApplication
    object has been created.
*/



/*!
    \fn bool TQGLFormat::hasOpenGLOverlays()

    Returns TRUE if the window system supports OpenGL overlays;
    otherwise returns FALSE.

    \warning This function must not be called until the TQApplication
    object has been created.
*/

/*!
    Returns the default TQGLFormat for the application. All TQGLWidgets
    that are created use this format unless another format is
    specified, e.g. when they are constructed.

    If no special default format has been set using
    setDefaultFormat(), the default format is the same as that created
    with TQGLFormat().

    \sa setDefaultFormat()
*/

TQGLFormat TQGLFormat::defaultFormat()
{
    if ( !qgl_default_format ) {
	qgl_default_format = new TQGLFormat;
	qgl_cleanup_format.add( &qgl_default_format );
    }
    return *qgl_default_format;
}

/*!
    Sets a new default TQGLFormat for the application to \a f. For
    example, to set single buffering as the default instead of double
    buffering, your main() might contain code like this:
    \code
    TQApplication a(argc, argv);
    TQGLFormat f;
    f.setDoubleBuffer( FALSE );
    TQGLFormat::setDefaultFormat( f );
    \endcode

    \sa defaultFormat()
*/

void TQGLFormat::setDefaultFormat( const TQGLFormat &f )
{
    if ( !qgl_default_format ) {
	qgl_default_format = new TQGLFormat;
	qgl_cleanup_format.add( &qgl_default_format );
    }
    *qgl_default_format = f;
}


/*!
    Returns the default TQGLFormat for overlay contexts.

    The factory default overlay format is:
    \list
    \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
    \i \link setDepth() Depth buffer:\endlink Disabled.
    \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled).
    \i \link setAlpha() Alpha channel:\endlink Disabled.
    \i \link setAccum() Accumulator buffer:\endlink Disabled.
    \i \link setStencil() Stencil buffer:\endlink Disabled.
    \i \link setStereo() Stereo:\endlink Disabled.
    \i \link setDirectRendering() Direct rendering:\endlink Enabled.
    \i \link setOverlay() Overlay:\endlink Disabled.
    \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
    \endlist

    \sa setDefaultFormat()
*/

TQGLFormat TQGLFormat::defaultOverlayFormat()
{
    if ( !qgl_default_overlay_format ) {
	qgl_default_overlay_format = new TQGLFormat;
	qgl_default_overlay_format->opts = DirectRendering;
	qgl_default_overlay_format->pln = 1;
	qgl_cleanup_format.add( &qgl_default_overlay_format );
    }
    return *qgl_default_overlay_format;
}

/*!
    Sets a new default TQGLFormat for overlay contexts to \a f. This
    format is used whenever a TQGLWidget is created with a format that
    hasOverlay() enabled.

    For example, to get a double buffered overlay context (if
    available), use code like this:

    \code
    TQGLFormat f = TQGLFormat::defaultOverlayFormat();
    f.setDoubleBuffer( TRUE );
    TQGLFormat::setDefaultOverlayFormat( f );
    \endcode

    As usual, you can find out after widget creation whether the
    underlying OpenGL system was able to provide the requested
    specification:

    \code
    // ...continued from above
    MyGLWidget* myWidget = new MyGLWidget( TQGLFormat( TQGL::HasOverlay ), ... );
    if ( myWidget->format().hasOverlay() ) {
	// Yes, we got an overlay, let's check _its_ format:
	TQGLContext* olContext = myWidget->overlayContext();
	if ( olContext->format().doubleBuffer() )
	    ; // yes, we got a double buffered overlay
	else
	    ; // no, only single buffered overlays are available
    }
    \endcode

    \sa defaultOverlayFormat()
*/

void TQGLFormat::setDefaultOverlayFormat( const TQGLFormat &f )
{
    if ( !qgl_default_overlay_format ) {
	qgl_default_overlay_format = new TQGLFormat;
	qgl_cleanup_format.add( &qgl_default_overlay_format );
    }
    *qgl_default_overlay_format = f;
    // Make sure the user doesn't request that the overlays themselves
    // have overlays, since it is unlikely that the system supports
    // infinitely many planes...
    qgl_default_overlay_format->setOverlay( FALSE );
}


/*!
    Returns TRUE if all the options of the two TQGLFormats are equal;
    otherwise returns FALSE.
*/

bool operator==( const TQGLFormat& a, const TQGLFormat& b )
{
    return (a.opts == b.opts) && (a.pln == b.pln);
}


/*!
    Returns FALSE if all the options of the two TQGLFormats are equal;
    otherwise returns TRUE.
*/

bool operator!=( const TQGLFormat& a, const TQGLFormat& b )
{
    return !( a == b );
}



/*****************************************************************************
  TQGLContext implementation
 *****************************************************************************/

TQGLContext* TQGLContext::currentCtx = 0;

/*!
    \class TQGLContext ntqgl.h
    \brief The TQGLContext class encapsulates an OpenGL rendering context.
\if defined(commercial)
    It is part of the <a href="commercialeditions.html">TQt Enterprise Edition</a>.
\endif

    \ingroup graphics
    \ingroup images
    \module OpenGL

    An OpenGL<sup>*</sup> rendering context is a complete set of
    OpenGL state variables.

    The context's \link TQGL::FormatOption format\endlink is set in the
    constructor or later with setFormat(). The format options that are
    actually set are returned by format(); the options you asked for
    are returned by requestedFormat(). Note that after a TQGLContext
    object has been constructed, the actual OpenGL context must be
    created by explicitly calling the \link create() create()\endlink
    function. The makeCurrent() function makes this context the
    current rendering context. You can make \e no context current
    using doneCurrent(). The reset() function will reset the context
    and make it invalid.

    You can examine properties of the context with, e.g. isValid(),
    isSharing(), initialized(), windowCreated() and
    overlayTransparentColor().

    If you're using double buffering you can swap the screen contents
    with the off-screen buffer using swapBuffers().

    Please note that TQGLContext is not thread safe.

    <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
    United States and other countries.

*/


/*!
    Constructs an OpenGL context for the paint device \a device, which
    can be a widget or a pixmap. The \a format specifies several
    display options for the context.

    If the underlying OpenGL/Window system cannot satisfy all the
    features requested in \a format, the nearest subset of features
    will be used. After creation, the format() method will return the
    actual format obtained.

    Note that after a TQGLContext object has been constructed, \link
    create() create()\endlink must be called explicitly to create
    the actual OpenGL context. The context will be \link isValid()
    invalid\endlink if it was not possible to obtain a GL context at
    all.

    \sa format(), isValid()
*/

TQGLContext::TQGLContext( const TQGLFormat &format, TQPaintDevice *device )
    : glFormat(format), reqFormat(format)
{
    init( device );
}

/*!
    \overload
    \internal
*/
TQGLContext::TQGLContext( const TQGLFormat &format )
    : glFormat( format ), reqFormat(format)
{
    init();
}

/*!
    Destroys the OpenGL context and frees its resources.
*/

TQGLContext::~TQGLContext()
{
    reset();
    if ( d )
	delete d;
}


/*!
    \fn TQGLFormat TQGLContext::format() const

    Returns the frame buffer format that was obtained (this may be a
    subset of what was requested).

    \sa requestedFormat()
*/

/*!
    \fn TQGLFormat TQGLContext::requestedFormat() const

    Returns the frame buffer format that was originally requested in
    the constructor or setFormat().

    \sa format()
*/

/*!
    Sets a \a format for this context. The context is \link reset()
    reset\endlink.

    Call create() to create a new GL context that tries to match the
    new format.

    \code
    TQGLContext *cx;
    //  ...
    TQGLFormat f;
    f.setStereo( TRUE );
    cx->setFormat( f );
    if ( !cx->create() )
	exit(); // no OpenGL support, or cannot render on the specified paintdevice
    if ( !cx->format().stereo() )
	exit(); // could not create stereo context
    \endcode

    \sa format(), reset(), create()
*/

void TQGLContext::setFormat( const TQGLFormat &format )
{
    reset();
    glFormat = reqFormat = format;
}

/*!
    \internal
*/
void TQGLContext::setDevice( TQPaintDevice *pDev )
{
    if ( isValid() )
	reset();
    d->paintDevice = pDev;
    if ( d->paintDevice && (d->paintDevice->devType() != TQInternal::Widget
			&& d->paintDevice->devType() != TQInternal::Pixmap) ) {
#if defined(QT_CHECK_RANGE)
	tqWarning( "TQGLContext: Unsupported paint device type" );
#endif
    }
}

void TQGLContext::init( TQPaintDevice *dev )
{
    d = new Private;
    d->valid = FALSE;
#if defined(TQ_WS_X11)
    qt_resolve_gl_symbols();
    gpm = 0;
#endif
    setDevice( dev );
#if defined(TQ_WS_WIN)
    dc = 0;
    win = 0;
    pixelFormatId = 0;
    cmap = 0;
#endif
#if defined(TQ_WS_MAC)
    d->oldR = TQRect(1, 1, 1, 1);
#endif
    d->crWin = FALSE;
    d->initDone = FALSE;
    d->sharing = FALSE;
}

/*!
    \fn bool TQGLContext::isValid() const

    Returns TRUE if a GL rendering context has been successfully
    created; otherwise returns FALSE.
*/

/*!
    \fn void TQGLContext::setValid( bool valid )
    \internal

    Forces the GL rendering context to be valid.
*/

/*!
    \fn bool TQGLContext::isSharing() const

    Returns TRUE if display list sharing with another context was
    requested in the create() call and the GL system was able to
    fulfill this request; otherwise returns FALSE. Note that display
    list sharing might not be supported between contexts with
    different formats.
*/

/*!
    \fn bool TQGLContext::deviceIsPixmap() const

    Returns TRUE if the paint device of this context is a pixmap;
    otherwise returns FALSE.
*/

/*!
    \fn bool TQGLContext::windowCreated() const

    Returns TRUE if a window has been created for this context;
    otherwise returns FALSE.

    \sa setWindowCreated()
*/

/*!
    \fn void TQGLContext::setWindowCreated( bool on )

    If \a on is TRUE the context has had a window created for it. If
    \a on is FALSE no window has been created for the context.

    \sa windowCreated()
*/

/*!
    \fn uint TQGLContext::colorIndex( const TQColor& c ) const

    \internal

    Returns a colormap index for the color c, in ColorIndex mode. Used
    by qglColor() and qglClearColor().
*/


/*!
    \fn bool TQGLContext::initialized() const

    Returns TRUE if this context has been initialized, i.e. if
    TQGLWidget::initializeGL() has been performed on it; otherwise
    returns FALSE.

    \sa setInitialized()
*/

/*!
    \fn void TQGLContext::setInitialized( bool on )

    If \a on is TRUE the context has been initialized, i.e.
    TQGLContext::setInitialized() has been called on it. If \a on is
    FALSE the context has not been initialized.

    \sa initialized()
*/

/*!
    \fn const TQGLContext* TQGLContext::currentContext()

    Returns the current context, i.e. the context to which any OpenGL
    commands will currently be directed. Returns 0 if no context is
    current.

    \sa makeCurrent()
*/

/*!
    \fn TQColor TQGLContext::overlayTransparentColor() const

    If this context is a valid context in an overlay plane, returns
    the plane's transparent color. Otherwise returns an \link
    TQColor::isValid() invalid \endlink color.

    The returned color's \link TQColor::pixel() pixel \endlink value is
    the index of the transparent color in the colormap of the overlay
    plane. (Naturally, the color's RGB values are meaningless.)

    The returned TQColor object will generally work as expected only
    when passed as the argument to TQGLWidget::qglColor() or
    TQGLWidget::qglClearColor(). Under certain circumstances it can
    also be used to draw transparent graphics with a TQPainter. See the
    examples/opengl/overlay_x11 example for details.
*/


/*!
    Creates the GL context. Returns TRUE if it was successful in
    creating a valid GL rendering context on the paint device
    specified in the constructor; otherwise returns FALSE (i.e. the
    context is invalid).

    After successful creation, format() returns the set of features of
    the created GL rendering context.

    If \a shareContext points to a valid TQGLContext, this method will
    try to establish OpenGL display list sharing between this context
    and the \a shareContext. Note that this may fail if the two
    contexts have different formats. Use isSharing() to see if sharing
    succeeded.

    \warning Implementation note: initialization of C++ class
    members usually takes place in the class constructor. TQGLContext
    is an exception because it must be simple to customize. The
    virtual functions chooseContext() (and chooseVisual() for X11) can
    be reimplemented in a subclass to select a particular context. The
    problem is that virtual functions are not properly called during
    construction (even though this is correct C++) because C++
    constructs class hierarchies from the bottom up. For this reason
    we need a create() function.

    \sa chooseContext(), format(), isValid()
*/

bool TQGLContext::create( const TQGLContext* shareContext )
{
    reset();
    d->valid = chooseContext( shareContext );
    return d->valid;
}



/*!
    \fn bool TQGLContext::chooseContext( const TQGLContext* shareContext = 0 )

    This semi-internal function is called by create(). It creates a
    system-dependent OpenGL handle that matches the format() of \a
    shareContext as closely as possible.

    On Windows, it calls the virtual function choosePixelFormat(),
    which finds a matching pixel format identifier. On X11, it calls
    the virtual function chooseVisual() which finds an appropriate X
    visual. On other platforms it may work differently.
*/


/*!
    \fn void TQGLContext::reset()

    Resets the context and makes it invalid.

    \sa create(), isValid()
*/


/*!
    \fn void TQGLContext::makeCurrent()

    Makes this context the current OpenGL rendering context. All GL
    functions you call operate on this context until another context
    is made current.

    In some very rare cases the underlying call may fail. If this
    occurs an error message is output to stderr.
*/


/*!
    \fn void TQGLContext::swapBuffers() const

    Swaps the screen contents with an off-screen buffer. Only works if
    the context is in double buffer mode.

    \sa TQGLFormat::setDoubleBuffer()
*/


/*!
    \fn void TQGLContext::doneCurrent()

    Makes no GL context the current context. Normally, you do not need
    to call this function; TQGLContext calls it as necessary.
*/


/*!
    \fn TQPaintDevice* TQGLContext::device() const

    Returns the paint device set for this context.

    \sa TQGLContext::TQGLContext()
*/

/*!
    \fn void TQGLContext::generateFontDisplayLists( const TQFont& font, int listBase )

    Generates a set of 256 display lists for the 256 first characters
    in the font \a font. The first list will start at index \a listBase.

    \sa TQGLWidget::renderText()
*/


/*****************************************************************************
  TQGLWidget implementation
 *****************************************************************************/


/*!
    \class TQGLWidget ntqgl.h
    \brief The TQGLWidget class is a widget for rendering OpenGL graphics.
\if defined(commercial)
    It is part of the <a href="commercialeditions.html">TQt Enterprise Edition</a>.
\endif

    \ingroup graphics
    \ingroup images
    \mainclass
    \module OpenGL

    TQGLWidget provides functionality for displaying OpenGL<sup>*</sup>
    graphics integrated into a TQt application. It is very simple to
    use. You inherit from it and use the subclass like any other
    TQWidget, except that instead of drawing the widget's contents
    using TQPainter etc. you use the standard OpenGL rendering
    commands.

    TQGLWidget provides three convenient virtual functions that you can
    reimplement in your subclass to perform the typical OpenGL tasks:

    \list
    \i paintGL() - Renders the OpenGL scene. Gets called whenever the widget
    needs to be updated.
    \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
    called whenever the the widget has been resized (and also when it
    is shown for the first time because all newly created widgets get a
    resize event automatically).
    \i initializeGL() - Sets up the OpenGL rendering context, defines display
    lists, etc. Gets called once before the first time resizeGL() or
    paintGL() is called.
    \endlist

    Here is a rough outline of how a TQGLWidget subclass might look:

    \code
    class MyGLDrawer : public TQGLWidget
    {
	TQ_OBJECT	// must include this if you use TQt signals/slots

    public:
	MyGLDrawer( TQWidget *parent, const char *name )
	    : TQGLWidget(parent, name) {}

    protected:

	void initializeGL()
	{
	    // Set up the rendering context, define display lists etc.:
	    ...
	    glClearColor( 0.0, 0.0, 0.0, 0.0 );
	    glEnable(GL_DEPTH_TEST);
	    ...
	}

	void resizeGL( int w, int h )
	{
	    // setup viewport, projection etc.:
	    glViewport( 0, 0, (GLint)w, (GLint)h );
	    ...
	    glFrustum( ... );
	    ...
	}

	void paintGL()
	{
	    // draw the scene:
	    ...
	    glRotatef( ... );
	    glMaterialfv( ... );
	    glBegin( GL_QUADS );
	    glVertex3f( ... );
	    glVertex3f( ... );
	    ...
	    glEnd();
	    ...
	}

    };
    \endcode

    If you need to trigger a repaint from places other than paintGL()
    (a typical example is when using \link TQTimer timers\endlink to
    animate scenes), you should call the widget's updateGL() function.

    Your widget's OpenGL rendering context is made current when
    paintGL(), resizeGL(), or initializeGL() is called. If you need to
    call the standard OpenGL API functions from other places (e.g. in
    your widget's constructor or in your own paint functions), you
    must call makeCurrent() first.

    TQGLWidget provides functions for requesting a new display \link
    TQGLFormat format\endlink and you can also create widgets with
    customized rendering \link TQGLContext contexts\endlink.

    You can also share OpenGL display lists between TQGLWidgets (see
    the documentation of the TQGLWidget constructors for details).

    \section1 Overlays

    The TQGLWidget creates a GL overlay context in addition to the
    normal context if overlays are supported by the underlying system.

    If you want to use overlays, you specify it in the \link TQGLFormat
    format\endlink. (Note: Overlay must be requested in the format
    passed to the TQGLWidget constructor.) Your GL widget should also
    implement some or all of these virtual methods:

    \list
    \i paintOverlayGL()
    \i resizeOverlayGL()
    \i initializeOverlayGL()
    \endlist

    These methods work in the same way as the normal paintGL() etc.
    functions, except that they will be called when the overlay
    context is made current. You can explicitly make the overlay
    context current by using makeOverlayCurrent(), and you can access
    the overlay context directly (e.g. to ask for its transparent
    color) by calling overlayContext().

    On X servers in which the default visual is in an overlay plane,
    non-GL TQt windows can also be used for overlays. See the
    examples/opengl/overlay_x11 example program for details.

    <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
    United States and other countries.
*/

// ### BCI - fix in 4.0

// the display list cache can't be global because display lists are
// tied to the GL contexts for each individual widget

class TQGLWidgetPrivate
{
public:
    TQMap<TQString, int> displayListCache;
};

static TQPtrDict<TQGLWidgetPrivate> * qgl_d_ptr = 0;
static TQSingleCleanupHandler< TQPtrDict<TQGLWidgetPrivate> > qgl_cleanup_d_ptr;

static TQGLWidgetPrivate * qgl_d( const TQGLWidget * w )
{
    if ( !qgl_d_ptr ) {
	qgl_d_ptr = new TQPtrDict<TQGLWidgetPrivate>;
	qgl_cleanup_d_ptr.set( &qgl_d_ptr );
	qgl_d_ptr->setAutoDelete( TRUE );
    }
    TQGLWidgetPrivate * ret = qgl_d_ptr->find( (void *) w );
    if ( !ret ) {
	ret = new TQGLWidgetPrivate;
	qgl_d_ptr->replace( (void *) w, ret );
    }
    return ret;
}

void qgl_delete_d( const TQGLWidget * w )
{
    if ( qgl_d_ptr )
	qgl_d_ptr->remove( (void *) w );
}

/*!
    Constructs an OpenGL widget with a \a parent widget and a \a name.

    The \link TQGLFormat::defaultFormat() default format\endlink is
    used. The widget will be \link isValid() invalid\endlink if the
    system has no \link TQGLFormat::hasOpenGL() OpenGL support\endlink.

    The \a parent, \a name and widget flag, \a f, arguments are passed
    to the TQWidget constructor.

    If the \a shareWidget parameter points to a valid TQGLWidget, this
    widget will share OpenGL display lists with \a shareWidget. If
    this widget and \a shareWidget have different \link format()
    formats\endlink, display list sharing may fail. You can check
    whether display list sharing succeeded by calling isSharing().

    The initialization of OpenGL rendering state, etc. should be done
    by overriding the initializeGL() function, rather than in the
    constructor of your TQGLWidget subclass.

    \sa TQGLFormat::defaultFormat()
*/

TQGLWidget::TQGLWidget( TQWidget *parent, const char *name,
		      const TQGLWidget* shareWidget, WFlags f )
    : TQWidget( parent, name, f | TQt::WWinOwnDC | TQt::WNoAutoErase )
{
    init( new TQGLContext(TQGLFormat::defaultFormat(), this), shareWidget );
}


/*!
    Constructs an OpenGL widget with parent \a parent, called \a name.

    The \a format argument specifies the desired \link TQGLFormat
    rendering options \endlink. If the underlying OpenGL/Window system
    cannot satisfy all the features requested in \a format, the
    nearest subset of features will be used. After creation, the
    format() method will return the actual format obtained.

    The widget will be \link isValid() invalid\endlink if the system
    has no \link TQGLFormat::hasOpenGL() OpenGL support\endlink.

    The \a parent, \a name and widget flag, \a f, arguments are passed
    to the TQWidget constructor.

    If the \a shareWidget parameter points to a valid TQGLWidget, this
    widget will share OpenGL display lists with \a shareWidget. If
    this widget and \a shareWidget have different \link format()
    formats\endlink, display list sharing may fail. You can check
    whether display list sharing succeeded by calling isSharing().

    The initialization of OpenGL rendering state, etc. should be done
    by overriding the initializeGL() function, rather than in the
    constructor of your TQGLWidget subclass.

    \sa TQGLFormat::defaultFormat(), isValid()
*/

TQGLWidget::TQGLWidget( const TQGLFormat &format, TQWidget *parent,
		      const char *name, const TQGLWidget* shareWidget,
		      WFlags f )
    : TQWidget( parent, name, f | TQt::WWinOwnDC | TQt::WNoAutoErase )
{
    init( new TQGLContext(format, this), shareWidget );
}

/*!
    Constructs an OpenGL widget with parent \a parent, called \a name.

    The \a context argument is a pointer to the TQGLContext that
    you wish to be bound to this widget. This allows you to pass in
    your own TQGLContext sub-classes.

    The widget will be \link isValid() invalid\endlink if the system
    has no \link TQGLFormat::hasOpenGL() OpenGL support\endlink.

    The \a parent, \a name and widget flag, \a f, arguments are passed
    to the TQWidget constructor.

    If the \a shareWidget parameter points to a valid TQGLWidget, this
    widget will share OpenGL display lists with \a shareWidget. If
    this widget and \a shareWidget have different \link format()
    formats\endlink, display list sharing may fail. You can check
    whether display list sharing succeeded by calling isSharing().

    The initialization of OpenGL rendering state, etc. should be done
    by overriding the initializeGL() function, rather than in the
    constructor of your TQGLWidget subclass.

    \sa TQGLFormat::defaultFormat(), isValid()
*/
TQGLWidget::TQGLWidget( TQGLContext *context, TQWidget *parent,
		      const char *name, const TQGLWidget *shareWidget, WFlags f )
    : TQWidget( parent, name, f | TQt::WWinOwnDC | TQt::WNoAutoErase )
{
    init( context, shareWidget );
}

/*!
    Destroys the widget.
*/

TQGLWidget::~TQGLWidget()
{
#if defined(GLX_MESA_release_buffers) && defined(TQGL_USE_MESA_EXT)
    bool doRelease = ( glcx && glcx->windowCreated() );
#endif
    qgl_delete_d( this );
    delete glcx;
#if defined(Q_WGL)
    delete olcx;
#endif
#if defined(GLX_MESA_release_buffers) && defined(TQGL_USE_MESA_EXT)
    if ( doRelease )
	glXReleaseBuffersMESA( x11Display(), winId() );
#endif
#if defined(TQ_WS_MAC)
    if(gl_pix) {
	delete gl_pix;
	gl_pix = NULL;
    }
#endif
    cleanupColormaps();
}





/*!
    \fn TQGLFormat TQGLWidget::format() const

    Returns the format of the contained GL rendering context.
*/

/*!
    \fn bool TQGLWidget::doubleBuffer() const

    Returns TRUE if the contained GL rendering context has double
    buffering; otherwise returns FALSE.

    \sa TQGLFormat::doubleBuffer()
*/

/*!
    \fn void TQGLWidget::setAutoBufferSwap( bool on )

    If \a on is TRUE automatic GL buffer swapping is switched on;
    otherwise it is switched off.

    If \a on is TRUE and the widget is using a double-buffered format,
    the background and foreground GL buffers will automatically be
    swapped after each paintGL() call.

    The buffer auto-swapping is on by default.

    \sa autoBufferSwap(), doubleBuffer(), swapBuffers()
*/

/*!
    \fn bool TQGLWidget::autoBufferSwap() const

    Returns TRUE if the widget is doing automatic GL buffer swapping;
    otherwise returns FALSE.

    \sa setAutoBufferSwap()
*/

/*!
    \fn bool TQGLWidget::isValid() const

    Returns TRUE if the widget has a valid GL rendering context;
    otherwise returns FALSE. A widget will be invalid if the system
    has no \link TQGLFormat::hasOpenGL() OpenGL support\endlink.
*/

bool TQGLWidget::isValid() const
{
    return glcx->isValid();
}

/*!
    \fn bool TQGLWidget::isSharing() const

    Returns TRUE if display list sharing with another TQGLWidget was
    requested in the constructor, and the GL system was able to
    provide it; otherwise returns FALSE. The GL system may fail to
    provide display list sharing if the two TQGLWidgets use different
    formats.

    \sa format()
*/

bool TQGLWidget::isSharing() const
{
    return glcx->isSharing();
}

/*!
    \fn void TQGLWidget::makeCurrent()

    Makes this widget the current widget for OpenGL operations, i.e.
    makes the widget's rendering context the current OpenGL rendering
    context.
*/

void TQGLWidget::makeCurrent()
{
#if defined( TQ_WS_MAC )
    macInternalDoubleBuffer(); //make sure the correct context is used
#endif
    glcx->makeCurrent();
}

/*!
    \fn void TQGLWidget::doneCurrent()

    Makes no GL context the current context. Normally, you do not need
    to call this function; TQGLContext calls it as necessary. However,
    it may be useful in multithreaded environments.
*/

void TQGLWidget::doneCurrent()
{
    glcx->doneCurrent();
}

/*!
    \fn void TQGLWidget::swapBuffers()

    Swaps the screen contents with an off-screen buffer. This only
    works if the widget's format specifies double buffer mode.

    Normally, there is no need to explicitly call this function
    because it is done automatically after each widget repaint, i.e.
    each time after paintGL() has been executed.

    \sa doubleBuffer(), setAutoBufferSwap(), TQGLFormat::setDoubleBuffer()
*/

void TQGLWidget::swapBuffers()
{
    glcx->swapBuffers();
#if defined(TQ_WS_MAC)
    if(macInternalDoubleBuffer() && gl_pix)
	bitBlt(this, 0, 0, gl_pix);
#endif
}


/*!
    \fn const TQGLContext* TQGLWidget::overlayContext() const

    Returns the overlay context of this widget, or 0 if this widget
    has no overlay.

    \sa context()
*/



/*!
    \fn void TQGLWidget::makeOverlayCurrent()

    Makes the overlay context of this widget current. Use this if you
    need to issue OpenGL commands to the overlay context outside of
    initializeOverlayGL(), resizeOverlayGL(), and paintOverlayGL().

    Does nothing if this widget has no overlay.

    \sa makeCurrent()
*/


/*
  \obsolete

  Sets a new format for this widget.

  If the underlying OpenGL/Window system cannot satisfy all the
  features requested in \a format, the nearest subset of features will
  be used. After creation, the format() method will return the actual
  rendering context format obtained.

  The widget will be assigned a new TQGLContext, and the initializeGL()
  function will be executed for this new context before the first
  resizeGL() or paintGL().

  This method will try to keep any existing display list sharing with
  other TQGLWidgets, but it may fail. Use isSharing() to test.

  \sa format(), isSharing(), isValid()
*/

void TQGLWidget::setFormat( const TQGLFormat &format )
{
    setContext( new TQGLContext(format,this) );
}




/*!
    \fn const TQGLContext *TQGLWidget::context() const

    Returns the context of this widget.

    It is possible that the context is not valid (see isValid()), for
    example, if the underlying hardware does not support the format
    attributes that were requested.
*/

/*
  \obsolete

  \fn void TQGLWidget::setContext( TQGLContext *context,
				  const TQGLContext* shareContext,
				  bool deleteOldContext )

  Sets a new context for this widget. The TQGLContext \a context must
  be created using \e new. TQGLWidget will delete \a context when
  another context is set or when the widget is destroyed.

  If \a context is invalid, TQGLContext::create() is performed on
  it. The initializeGL() function will then be executed for the new
  context before the first resizeGL() or paintGL().

  If \a context is invalid, this method will try to keep any existing
  display list sharing with other TQGLWidgets this widget currently
  has, or (if \a shareContext points to a valid context) start display
  list sharing with that context, but it may fail. Use isSharing() to
  test.

  If \a deleteOldContext is TRUE (the default), the existing context
  will be deleted. You may use FALSE here if you have kept a pointer
  to the old context (as returned by context()), and want to restore
  that context later.

  \sa context(), isSharing()
*/



/*!
    \fn void TQGLWidget::updateGL()

    Updates the widget by calling glDraw().
*/

void TQGLWidget::updateGL()
{
    glDraw();
}


/*!
    \fn void TQGLWidget::updateOverlayGL()

    Updates the widget's overlay (if any). Will cause the virtual
    function paintOverlayGL() to be executed.

    The widget's rendering context will become the current context and
    initializeGL() will be called if it hasn't already been called.
*/


/*!
    This virtual function is called once before the first call to
    paintGL() or resizeGL(), and then once whenever the widget has
    been assigned a new TQGLContext. Reimplement it in a subclass.

    This function should set up any required OpenGL context rendering
    flags, defining display lists, etc.

    There is no need to call makeCurrent() because this has already
    been done when this function is called.
*/

void TQGLWidget::initializeGL()
{
}


/*!
    This virtual function is called whenever the widget needs to be
    painted. Reimplement it in a subclass.

    There is no need to call makeCurrent() because this has already
    been done when this function is called.
*/

void TQGLWidget::paintGL()
{
}


/*!
    \fn void TQGLWidget::resizeGL( int width , int height )

    This virtual function is called whenever the widget has been
    resized. The new size is passed in \a width and \a height.
    Reimplement it in a subclass.

    There is no need to call makeCurrent() because this has already
    been done when this function is called.
*/

void TQGLWidget::resizeGL( int, int )
{
}



/*!
    This virtual function is used in the same manner as initializeGL()
    except that it operates on the widget's overlay context instead of
    the widget's main context. This means that initializeOverlayGL()
    is called once before the first call to paintOverlayGL() or
    resizeOverlayGL(). Reimplement it in a subclass.

    This function should set up any required OpenGL context rendering
    flags, defining display lists, etc. for the overlay context.

    There is no need to call makeOverlayCurrent() because this has
    already been done when this function is called.
*/

void TQGLWidget::initializeOverlayGL()
{
}


/*!
    This virtual function is used in the same manner as paintGL()
    except that it operates on the widget's overlay context instead of
    the widget's main context. This means that paintOverlayGL() is
    called whenever the widget's overlay needs to be painted.
    Reimplement it in a subclass.

    There is no need to call makeOverlayCurrent() because this has
    already been done when this function is called.
*/

void TQGLWidget::paintOverlayGL()
{
}


/*!
    \fn void TQGLWidget::resizeOverlayGL( int width , int height )

    This virtual function is used in the same manner as paintGL()
    except that it operates on the widget's overlay context instead of
    the widget's main context. This means that resizeOverlayGL() is
    called whenever the widget has been resized. The new size is
    passed in \a width and \a height. Reimplement it in a subclass.

    There is no need to call makeOverlayCurrent() because this has
    already been done when this function is called.
*/

void TQGLWidget::resizeOverlayGL( int, int )
{
}




/*!
    Handles paint events. Will cause the virtual paintGL() function to
    be called.

    The widget's rendering context will become the current context and
    initializeGL() will be called if it hasn't already been called.
*/

void TQGLWidget::paintEvent( TQPaintEvent * )
{
    glDraw();
    updateOverlayGL();
}


/*!
    \fn void TQGLWidget::resizeEvent( TQResizeEvent * )

    Handles resize events. Calls the virtual function resizeGL().
*/


/*!
  \fn void TQGLWidget::setMouseTracking( bool enable )

  \reimp
*/


/*!
    Renders the current scene on a pixmap and returns the pixmap.

    You can use this method on both visible and invisible TQGLWidgets.

    This method will create a pixmap and a temporary TQGLContext to
    render on the pixmap. It will then call initializeGL(),
    resizeGL(), and paintGL() on this context. Finally, the widget's
    original GL context is restored.

    The size of the pixmap will be \a w pixels wide and \a h pixels
    high unless one of these parameters is 0 (the default), in which
    case the pixmap will have the same size as the widget.

    If \a useContext is TRUE, this method will try to be more
    efficient by using the existing GL context to render the pixmap.
    The default is FALSE. Only use TRUE if you understand the risks.

    Overlays are not rendered onto the pixmap.

    If the GL rendering context and the desktop have different bit
    depths, the result will most likely look surprising.

    Note that the creation of display lists, modifications of the view
    frustum etc. should be done from within initializeGL(). If this is
    not done, the temporary TQGLContext will not be initialized
    properly, and the rendered pixmap may be incomplete/corrupted.
*/

TQPixmap TQGLWidget::renderPixmap( int w, int h, bool useContext )
{
    TQSize sz = size();
    if ( (w > 0) && (h > 0) )
	sz = TQSize( w, h );

#if defined(TQ_WS_X11)
    TQPixmap pm( sz.width(), sz.height(), x11Depth() );
    bool needConversion = x11Visual() != TQPaintDevice::x11AppVisual();

    // make sure the pixmap uses the same visual as the widget itself
    if ( needConversion ) {
        TQPaintDeviceX11Data* xd = pm.getX11Data( TRUE );
        xd->x_depth = x11Depth();
        xd->x_visual = (Visual *) x11Visual();
        pm.setX11Data( xd );
    }
#else
    TQPixmap pm;
    pm.resize( sz );
#endif

    glcx->doneCurrent();

    bool success = TRUE;

    if ( useContext && isValid() && renderCxPm( &pm ) )
	return pm;

    TQGLFormat fmt = glcx->requestedFormat();
    fmt.setDirectRendering( FALSE );		// Direct is unlikely to work
    fmt.setDoubleBuffer( FALSE );		// We don't need dbl buf

    TQGLContext* ocx = glcx;
    bool wasCurrent = (TQGLContext::currentContext() == ocx );
    ocx->doneCurrent();
    glcx = new TQGLContext( fmt, &pm );
    glcx->create();

    if ( glcx->isValid() )
	updateGL();
    else
	success = FALSE;

    delete glcx;
    glcx = ocx;

    if ( wasCurrent )
	ocx->makeCurrent();

    if ( success ) {
#if defined(TQ_WS_X11)
	if ( needConversion ) {
	    TQImage image = pm.convertToImage();
	    TQPixmap p;
	    p = image;
	    return p;
	}
#endif
	return pm;
    } else
	return TQPixmap();
}



/*!
    Returns an image of the frame buffer. If \a withAlpha is TRUE the
    alpha channel is included.

    Depending on your hardware, you can explicitly select which color
    buffer to grab with a glReadBuffer() call before calling this
    function.
*/
TQImage TQGLWidget::grabFrameBuffer( bool withAlpha )
{
#if defined( TQ_WS_MAC )
    if(dblbuf == macInternalDoubleBuffer(FALSE) && gl_pix) //why not optimize?
	return ((TQPixmap*)gl_pix)->convertToImage();
#endif
    makeCurrent();
    TQImage res;
    int w = width();
    int h = height();
    if ( format().rgba() ) {
	res = TQImage( w, h, 32 );
	glReadPixels( 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, res.bits() );
	if ( TQImage::systemByteOrder() == TQImage::BigEndian ) {
	    // OpenGL gives RGBA; TQt wants ARGB
	    uint *p = (uint*)res.bits();
	    uint *end = p + w*h;
	    if ( withAlpha && format().alpha() ) {
		while ( p < end ) {
		    uint a = *p << 24;
		    *p = (*p >> 8) | a;
		    p++;
		}
	    }
	    else {
		while ( p < end )
		    *p++ >>= 8;
	    }
	}
	else {
	    // OpenGL gives ABGR (i.e. RGBA backwards); TQt wants ARGB
	    res = res.swapRGB();
	}
	res.setAlphaBuffer( withAlpha && format().alpha() );
    }
    else {
#if defined (TQ_WS_WIN)
	res = TQImage( w, h, 8 );
	glReadPixels( 0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE,
		      res.bits() );
	int palSize = 0;
	const TQRgb* pal = TQColor::palette( &palSize );
	if ( pal && palSize ) {
	    res.setNumColors( palSize );
	    for ( int i = 0; i < palSize; i++ )
		res.setColor( i, pal[i] );
	}
#endif
    }

    return res.mirror();
}



/*!
    Initializes OpenGL for this widget's context. Calls the virtual
    function initializeGL().
*/

void TQGLWidget::glInit()
{
    if ( !isValid() )
	return;
    makeCurrent();
    initializeGL();
    glcx->setInitialized( TRUE );
}


/*!
    Executes the virtual function paintGL().

    The widget's rendering context will become the current context and
    initializeGL() will be called if it hasn't already been called.
*/

void TQGLWidget::glDraw()
{
    if ( !isValid() )
	return;
    makeCurrent();
    if ( glcx->deviceIsPixmap() )
	glDrawBuffer( GL_FRONT );
    if ( !glcx->initialized() ) {
	glInit();
	TQPaintDeviceMetrics dm( glcx->device() );
	resizeGL( dm.width(), dm.height() ); // New context needs this "resize"
    }
    paintGL();
    if ( doubleBuffer() ) {
	if ( autoSwap )
	    swapBuffers();
    } else {
	glFlush();
#if defined( TQ_WS_MAC )
	if(dblbuf && gl_pix)
	    bitBlt(this, 0, 0, gl_pix);
#endif
    }
}


/*!
    Convenience function for specifying a drawing color to OpenGL.
    Calls glColor3 (in RGBA mode) or glIndex (in color-index mode)
    with the color \a c. Applies to the current GL context.

    \sa qglClearColor(), TQGLContext::currentContext(), TQColor
*/

void TQGLWidget::qglColor( const TQColor& c ) const
{
    const TQGLContext* ctx = TQGLContext::currentContext();
    if ( ctx ) {
	if ( ctx->format().rgba() )
	    glColor3ub( c.red(), c.green(), c.blue() );

	else if ( ctx->device() == context()->device()
                  && !cmap.isEmpty() ) { // TQGLColormap in use?
	    int i = cmap.find( c.rgb() );
	    if ( i < 0 )
		i = cmap.findNearest( c.rgb() );
	    glIndexi( i );
	} else
	    glIndexi( ctx->colorIndex( c ) );
    }
}

/*!
    Convenience function for specifying the clearing color to OpenGL.
    Calls glClearColor (in RGBA mode) or glClearIndex (in color-index
    mode) with the color \a c. Applies to the current GL context.

    \sa qglColor(), TQGLContext::currentContext(), TQColor
*/

void TQGLWidget::qglClearColor( const TQColor& c ) const
{
    const TQGLContext* ctx = TQGLContext::currentContext();
    if ( ctx ) {
	if ( ctx->format().rgba() )
	    glClearColor( (GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0,
			  (GLfloat)c.blue() / 255.0, (GLfloat) 0.0 );
	else if ( ctx->device() == context()->device()
                  && !cmap.isEmpty() ) { // TQGLColormap in use?
	    int i = cmap.find( c.rgb() );
	    if ( i < 0 )
		i = cmap.findNearest( c.rgb() );
	    glClearIndex( i );
	} else
	    glClearIndex( ctx->colorIndex( c ) );
    }
}


/*!
    Converts the image \a img into the unnamed format expected by
    OpenGL functions such as glTexImage2D(). The returned image is not
    usable as a TQImage, but TQImage::width(), TQImage::height() and
    TQImage::bits() may be used with OpenGL. The following few lines
    are from the texture example. Most of the code is irrelevant, so
    we just quote the relevant bits:

    \quotefile opengl/texture/gltexobj.cpp
    \skipto tex1
    \printline tex1
    \printline gllogo.bmp

    We create \e tex1 (and another variable) for OpenGL, and load a real
    image into \e buf.

    \skipto convertToGLFormat
    \printline convertToGLFormat

    A few lines later, we convert \e buf into OpenGL format and store it
    in \e tex1.

    \skipto glTexImage2D
    \printline glTexImage2D
    \printline tex1.bits

    Note the dimension restrictions for texture images as described in
    the glTexImage2D() documentation. The width must be 2^m + 2*border
    and the height 2^n + 2*border where m and n are integers and
    border is either 0 or 1.

    Another function in the same example uses \e tex1 with OpenGL.
*/


TQImage TQGLWidget::convertToGLFormat( const TQImage& img )
{
    TQImage res = img.convertDepth( 32 );
    res = res.mirror();

    if ( TQImage::systemByteOrder() == TQImage::BigEndian ) {
	// TQt has ARGB; OpenGL wants RGBA
	for ( int i=0; i < res.height(); i++ ) {
	    uint *p = (uint*)res.scanLine( i );
	    uint *end = p + res.width();
	    while ( p < end ) {
		*p = (*p << 8) | ((*p >> 24) & 0xFF);
		p++;
	    }
	}
    }
    else {
	// TQt has ARGB; OpenGL wants ABGR (i.e. RGBA backwards)
	res = res.swapRGB();
    }
    return res;
}


/*!
    \fn TQGLColormap & TQGLWidget::colormap() const

    Returns the colormap for this widget.

    Usually it is only top-level widgets that can have different
    colormaps installed. Asking for the colormap of a child widget
    will return the colormap for the child's top-level widget.

    If no colormap has been set for this widget, the TQColormap
    returned will be empty.

    \sa setColormap()
*/

/*!
    \fn void TQGLWidget::setColormap( const TQGLColormap & cmap )

    Set the colormap for this widget to \a cmap. Usually it is only
    top-level widgets that can have colormaps installed.

    \sa colormap()
*/

int TQGLWidget::displayListBase( const TQFont & fnt, int listBase )
{
    int base;

    TQGLWidgetPrivate * d = qgl_d( this );
    if ( !d || !glcx ) { // this can't happen unless we run out of mem
	return 0;
    }

    // always regenerate font disp. lists for pixmaps - hw accelerated
    // contexts can't handle this otherwise
    bool regenerate = glcx->deviceIsPixmap();

#if 0 // TQT_NO_XFTFREETYPE
    // font color needs to be part of the font cache key when using
    // antialiased fonts since one set of glyphs needs to be generated
    // for each font color
    TQString color_key;
    if (fnt.styleStrategy() != TQFont::NoAntialias) {
	GLfloat color[4];
	glGetFloatv(GL_CURRENT_COLOR, color);
	color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]);
    }
    TQString key = fnt.key() + color_key + TQString::number((int) regenerate);
#else
    TQString key = fnt.key() + TQString::number((int) regenerate);
#endif

    if ( !regenerate && (d->displayListCache.find( key ) != d->displayListCache.end()) ) {
	base = d->displayListCache[ key ];
    } else {
	int maxBase = listBase - 256;
	TQMapConstIterator<TQString,int> it;
	for ( it = d->displayListCache.begin(); it != d->displayListCache.end(); ++it ) {
	    if ( maxBase < it.data() ) {
		maxBase = it.data();
	    }
	}
	maxBase += 256;
	glcx->generateFontDisplayLists( fnt, maxBase );
	d->displayListCache[ key ] = maxBase;
	base = maxBase;
    }
    return base;
}

/*!
   Renders the string \a str into the GL context of this widget.

   \a x and \a y are specified in window coordinates, with the origin
   in the upper left-hand corner of the window. If \a fnt is not
   specified, the currently set application font will be used to
   render the string. To change the color of the rendered text you can
   use the glColor() call (or the qglColor() convenience function),
   just before the renderText() call. Note that if you have
   GL_LIGHTING enabled, the string will not appear in the color you
   want. You should therefore switch lighting off before using
   renderText().

   \a listBase specifies the index of the first display list that is
   generated by this function. The default value is 2000. 256 display
   lists will be generated, one for each of the first 256 characters
   in the font that is used to render the string. If several fonts are
   used in the same widget, the display lists for these fonts will
   follow the last generated list. You would normally not have to
   change this value unless you are using lists in the same range. The
   lists are deleted when the widget is destroyed.

   Note: This function only works reliably with ASCII strings.
*/

void TQGLWidget::renderText( int x, int y, const TQString & str, const TQFont & fnt, int listBase )
{
    if (str.isEmpty())
        return;
    makeCurrent();
    glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT | GL_LIST_BIT | GL_CURRENT_BIT );
    glMatrixMode( GL_PROJECTION );
    glPushMatrix();
    glLoadIdentity();
    glOrtho( 0, width(), height(), 0, -1, 1 );
    glMatrixMode( GL_MODELVIEW );
    glPushMatrix();
    glLoadIdentity();

    glRasterPos2i( 0, 0 );
    glBitmap(0, 0, 0, 0, x, -y, NULL);
    glListBase( displayListBase( fnt, listBase ) );
    const char *cstr = str.latin1();
    glCallLists( tqstrlen(cstr), GL_UNSIGNED_BYTE, cstr );

    // restore the matrix stacks and GL state
    glPopMatrix();
    glMatrixMode( GL_PROJECTION );
    glPopMatrix();
    glPopAttrib();
}

/*! \overload

    \a x, \a y and \a z are specified in scene or object coordinates
    relative to the currently set projection and model matrices. This
    can be useful if you want to annotate models with text labels and
    have the labels move with the model as it is rotated etc.
*/
void TQGLWidget::renderText( double x, double y, double z, const TQString & str, const TQFont & fnt,
			    int listBase )
{
    if (str.isEmpty())
        return;
    makeCurrent();
    glRasterPos3d( x, y, z );
    glPushAttrib( GL_LIST_BIT );
    glListBase( displayListBase( fnt, listBase ) );
    const char *cstr = str.latin1();
    glCallLists( tqstrlen(cstr), GL_UNSIGNED_BYTE, cstr );
    glPopAttrib();
}

/*****************************************************************************
  TQGL classes overview documentation.
 *****************************************************************************/

/*!

\page opengl.html

\title TQt OpenGL 3D Graphics

\if defined(commercial)
This module is part of the \link commercialeditions.html TQt Enterprise
Edition\endlink.
\endif

\section1 Introduction

OpenGL is a standard API for rendering 3D graphics.

OpenGL only deals with 3D rendering and provides little or no support
for GUI programming issues. The user interface for an
OpenGL<sup>*</sup> application must be created with another toolkit,
such as Motif on the X platform, Microsoft Foundation Classes (MFC)
under Windows, or TQt on \e both platforms.

The TQt OpenGL module makes it easy to use OpenGL in TQt applications.
It provides an OpenGL widget class that can be used just like any
other TQt widget, except that it opens an OpenGL display buffer where
you can use the OpenGL API to render the contents.

The TQt OpenGL module is implemented as a platform-independent TQt/C++
wrapper around the platform-dependent GLX, WGL, or AGL C APIs. The
functionality provided is very similar to Mark Kilgard's GLUT library,
but with much more non-OpenGL-specific GUI functionality, i.e. the
whole TQt API.

\section1 Installation

When you install TQt for X11, the configure script will autodetect if
OpenGL headers and libraries are installed on your system, and if so,
it will include the TQt OpenGL module in the TQt library. (If your
OpenGL headers or libraries are placed in a non-standard directory,
you may need to change the QMAKE_INCDIR_OPENGL and/or
QMAKE_LIBDIR_OPENGL in the config file for your system). Some
configurations require threading to be enabled for OpenGL, so if
OpenGL is not detected, try \c{configure -thread}.

When you install TQt for Windows, the TQt OpenGL module is always
included.

The TQt OpenGL module is not licensed for use with the TQt Professional
Edition. Consider upgrading to the TQt Enterprise Edition if you
require OpenGL support.

Note about using Mesa on X11: Mesa versions earlier than 3.1 would use
the name "MesaGL" and "MesaGLU" for the libraries, instead of "GL" and
"GLU". If you want to use a pre-3.1 version of Mesa, you must change
the Makefiles to use these library names instead. The easiest way to
do this is to edit the QMAKE_LIBS_OPENGL line in the config file you
are using, changing "-lGL -lGLU" to "-lMesaGL -lMesaGLU"; then run
"configure" again.

\section1 The TQGL Classes

The OpenGL support classes in TQt are:
\list
\i \link TQGLWidget TQGLWidget\endlink: An easy-to-use TQt
  widget for rendering OpenGL scenes.
\i \link TQGLContext TQGLContext\endlink: Encapsulates an OpenGL rendering context.
\i \link TQGLFormat TQGLFormat\endlink: Specifies the
display format of a rendering context.
\i \link TQGLColormap TQGLColormap\endlink: Handles indexed
colormaps in GL-index mode.
\endlist

Many applications only need the high-level TQGLWidget class. The other
TQGL classes provide advanced features. X11 users might like to read
the notes on \link opengl-x11-overlays.html overlays\endlink.

See also the \link opengl-examples.html OpenGL examples\endlink.

The TQGL documentation assumes that you are familiar with OpenGL
programming. If you're new to the subject a good starting point is
\l{http://www.opengl.org/}.


<sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
United States and other countries.

*/

/*!
    \enum TQGL::FormatOption

    This enum specifies the format options.

    \value DoubleBuffer
    \value DepthBuffer
    \value Rgba
    \value AlphaChannel
    \value AccumBuffer
    \value StencilBuffer
    \value StereoBuffers
    \value DirectRendering
    \value HasOverlay
    \value SingleBuffer
    \value NoDepthBuffer
    \value ColorIndex
    \value NoAlphaChannel
    \value NoAccumBuffer
    \value NoStencilBuffer
    \value NoStereoBuffers
    \value IndirectRendering
    \value NoOverlay
*/