File: Texture

package info (click to toggle)
openscenegraph 3.2.3%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 32,820 kB
  • ctags: 34,610
  • sloc: cpp: 370,040; ansic: 9,071; java: 1,020; yacc: 548; objc: 288; makefile: 285; xml: 155; lex: 151
file content (1456 lines) | stat: -rw-r--r-- 66,039 bytes parent folder | download | duplicates (2)
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
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSG_TEXTURE
#define OSG_TEXTURE 1

#include <osg/GL>
#include <osg/Image>
#include <osg/StateAttribute>
#include <osg/GraphicsContext>
#include <osg/ref_ptr>
#include <osg/Vec4>
#include <osg/Vec4d>
#include <osg/Vec4i>
#include <osg/buffered_value>
#include <osg/GL2Extensions>

#include <list>
#include <map>

// If not defined by gl.h use the definition found in:
// http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_filter_anisotropic.txt
#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
    #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#endif

// If not defined, use the definition found in:
// http://www.opengl.org/registry/specs/ARB/texture_swizzle.txt
#ifndef GL_TEXTURE_SWIZZLE_RGBA
    #define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
#endif

#ifndef GL_ARB_texture_compression
    #define GL_COMPRESSED_ALPHA_ARB                 0x84E9
    #define GL_COMPRESSED_LUMINANCE_ARB             0x84EA
    #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB       0x84EB
    #define GL_COMPRESSED_INTENSITY_ARB             0x84EC
    #define GL_COMPRESSED_RGB_ARB                   0x84ED
    #define GL_COMPRESSED_RGBA_ARB                  0x84EE
    #define GL_TEXTURE_COMPRESSION_HINT_ARB         0x84EF
    #define GL_TEXTURE_COMPRESSED_ARB               0x86A1
    #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB   0x86A2
    #define GL_COMPRESSED_TEXTURE_FORMATS_ARB       0x86A3
#endif

#ifndef GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB
    #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB    0x86A0
#endif

#ifndef GL_EXT_texture_compression_s3tc
    #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT         0x83F0
    #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT        0x83F1
    #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT        0x83F2
    #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT        0x83F3
#endif

#ifndef GL_EXT_texture_compression_rgtc
  #define GL_COMPRESSED_RED_RGTC1_EXT                0x8DBB
  #define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT         0x8DBC
  #define GL_COMPRESSED_RED_GREEN_RGTC2_EXT          0x8DBD
  #define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT   0x8DBE
#endif

#ifndef GL_IMG_texture_compression_pvrtc
    #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG      0x8C00
    #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG      0x8C01
    #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG     0x8C02
    #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG     0x8C03
#endif

#ifndef GL_OES_compressed_ETC1_RGB8_texture
    #define GL_ETC1_RGB8_OES                            0x8D64
#endif

#ifndef GL_ARB_INTERNAL_TEXTURE_FORMAT
    #define GL_RGBA32F_ARB                           0x8814
    #define GL_RGB32F_ARB                            0x8815
    #define GL_ALPHA32F_ARB                          0x8816
    #define GL_INTENSITY32F_ARB                      0x8817
    #define GL_LUMINANCE32F_ARB                      0x8818
    #define GL_LUMINANCE_ALPHA32F_ARB                0x8819
    #define GL_RGBA16F_ARB                           0x881A
    #define GL_RGB16F_ARB                            0x881B
    #define GL_ALPHA16F_ARB                          0x881C
    #define GL_INTENSITY16F_ARB                      0x881D
    #define GL_LUMINANCE16F_ARB                      0x881E
    #define GL_LUMINANCE_ALPHA16F_ARB                0x881F
#endif

#ifndef GL_HALF_FLOAT
    #define GL_HALF_FLOAT                            0x140B
#endif

#ifndef GL_NV_texture_shader
    #define GL_HILO_NV                              0x86F4
    #define GL_DSDT_NV                              0x86F5
    #define GL_DSDT_MAG_NV                          0x86F6
    #define GL_DSDT_MAG_VIB_NV                      0x86F7
    #define GL_HILO16_NV                            0x86F8
    #define GL_SIGNED_HILO_NV                       0x86F9
    #define GL_SIGNED_HILO16_NV                     0x86FA
    #define GL_SIGNED_RGBA_NV                       0x86FB
    #define GL_SIGNED_RGBA8_NV                      0x86FC
    #define GL_SIGNED_RGB_NV                        0x86FE
    #define GL_SIGNED_RGB8_NV                       0x86FF
    #define GL_SIGNED_LUMINANCE_NV                  0x8701
    #define GL_SIGNED_LUMINANCE8_NV                 0x8702
    #define GL_SIGNED_LUMINANCE_ALPHA_NV            0x8703
    #define GL_SIGNED_LUMINANCE8_ALPHA8_NV          0x8704
    #define GL_SIGNED_ALPHA_NV                      0x8705
    #define GL_SIGNED_ALPHA8_NV                     0x8706
    #define GL_SIGNED_INTENSITY_NV                  0x8707
    #define GL_SIGNED_INTENSITY8_NV                 0x8708
    #define GL_DSDT8_NV                             0x8709
    #define GL_DSDT8_MAG8_NV                        0x870A
    #define GL_DSDT8_MAG8_INTENSITY8_NV             0x870B
    #define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV         0x870C
    #define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV       0x870D
#endif

#ifndef GL_NV_float_buffer
    #define GL_FLOAT_R_NV                           0x8880
    #define GL_FLOAT_RG_NV                          0x8881
    #define GL_FLOAT_RGB_NV                         0x8882
    #define GL_FLOAT_RGBA_NV                        0x8883
    #define GL_FLOAT_R16_NV                         0x8884
    #define GL_FLOAT_R32_NV                         0x8885
    #define GL_FLOAT_RG16_NV                        0x8886
    #define GL_FLOAT_RG32_NV                        0x8887
    #define GL_FLOAT_RGB16_NV                       0x8888
    #define GL_FLOAT_RGB32_NV                       0x8889
    #define GL_FLOAT_RGBA16_NV                      0x888A
    #define GL_FLOAT_RGBA32_NV                      0x888B
#endif

#ifndef GL_ATI_texture_float
    #define GL_RGBA_FLOAT32_ATI                     0x8814
    #define GL_RGB_FLOAT32_ATI                      0x8815
    #define GL_ALPHA_FLOAT32_ATI                    0x8816
    #define GL_INTENSITY_FLOAT32_ATI                0x8817
    #define GL_LUMINANCE_FLOAT32_ATI                0x8818
    #define GL_LUMINANCE_ALPHA_FLOAT32_ATI          0x8819
    #define GL_RGBA_FLOAT16_ATI                     0x881A
    #define GL_RGB_FLOAT16_ATI                      0x881B
    #define GL_ALPHA_FLOAT16_ATI                    0x881C
    #define GL_INTENSITY_FLOAT16_ATI                0x881D
    #define GL_LUMINANCE_FLOAT16_ATI                0x881E
    #define GL_LUMINANCE_ALPHA_FLOAT16_ATI          0x881F
#endif

#ifndef GL_MIRRORED_REPEAT_IBM
    #define GL_MIRRORED_REPEAT_IBM            0x8370
#endif

#ifndef GL_CLAMP_TO_EDGE
    #define GL_CLAMP_TO_EDGE                  0x812F
#endif

#ifndef GL_CLAMP
    #define GL_CLAMP                          0x2900
#endif

#ifndef GL_CLAMP_TO_BORDER_ARB
    #define GL_CLAMP_TO_BORDER_ARB            0x812D
#endif

#ifndef GL_INTENSITY
    // OpenGL ES1 and ES2 doesn't provide GL_INTENSITY
    #define GL_INTENSITY 0x8049
#endif

#ifndef GL_GENERATE_MIPMAP_SGIS
    #define GL_GENERATE_MIPMAP_SGIS           0x8191
    #define GL_GENERATE_MIPMAP_HINT_SGIS      0x8192
#endif

#ifndef GL_TEXTURE_3D
    #define GL_TEXTURE_3D                     0x806F
#endif

#ifndef GL_TEXTURE_2D_ARRAY_EXT
    #define GL_TEXTURE_2D_ARRAY_EXT           0x8C1A
    #define GL_TEXTURE_2D_ARRAY_EXT                        0x8C1A
    #define GL_PROXY_TEXTURE_2D_ARRAY_EXT                  0x8C1B
    #define GL_TEXTURE_BINDING_2D_ARRAY_EXT                0x8C1D
    #define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT                0x88FF
    #define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT            0x884E
    #define GL_SAMPLER_2D_ARRAY_EXT                        0x8DC1
    #define GL_SAMPLER_2D_ARRAY_SHADOW_EXT                 0x8DC4
    #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT    0x8CD4
#endif

#ifndef GL_TEXTURE_CUBE_MAP
    #define GL_TEXTURE_CUBE_MAP             0x8513
    #define GL_TEXTURE_BINDING_CUBE_MAP     0x8514
    #define GL_TEXTURE_CUBE_MAP_POSITIVE_X  0x8515
    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X  0x8516
    #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y  0x8517
    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y  0x8518
    #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z  0x8519
    #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z  0x851A
    #define GL_PROXY_TEXTURE_CUBE_MAP       0x851B
    #define GL_MAX_CUBE_MAP_TEXTURE_SIZE    0x851C
#endif

#ifndef GL_TEXTURE_BINDING_3D
    #define GL_TEXTURE_BINDING_3D             0x806A
#endif

#ifndef GL_DEPTH_TEXTURE_MODE_ARB
    #define GL_DEPTH_TEXTURE_MODE_ARB         0x884B
#endif

#ifndef GL_TEXTURE_COMPARE_MODE_ARB
    #define GL_TEXTURE_COMPARE_MODE_ARB       0x884C
#endif
#ifndef GL_TEXTURE_COMPARE_FUNC_ARB
    #define GL_TEXTURE_COMPARE_FUNC_ARB       0x884D
#endif
#ifndef GL_COMPARE_R_TO_TEXTURE_ARB
    #define GL_COMPARE_R_TO_TEXTURE_ARB       0x884E
#endif

#ifndef TEXTURE_COMPARE_FAIL_VALUE_ARB
    #define TEXTURE_COMPARE_FAIL_VALUE_ARB    0x80BF
#endif

#if !defined( GL_MAX_TEXTURE_UNITS )
    #define GL_MAX_TEXTURE_UNITS              0x84E2
#endif

#ifndef  GL_TEXTURE_DEPTH
    #define GL_TEXTURE_DEPTH                  0x8071
#endif

#ifndef GL_TEXTURE_2D_MULTISAMPLE
    #define GL_TEXTURE_2D_MULTISAMPLE         0x9100
#endif

// Integer texture extension as in http://www.opengl.org/registry/specs/EXT/texture_integer.txt
#ifndef GL_EXT_texture_integer
    #define GL_RGBA32UI_EXT                                    0x8D70
    #define GL_RGB32UI_EXT                                     0x8D71
    #define GL_ALPHA32UI_EXT                                   0x8D72
    #define GL_INTENSITY32UI_EXT                               0x8D73
    #define GL_LUMINANCE32UI_EXT                               0x8D74
    #define GL_LUMINANCE_ALPHA32UI_EXT                         0x8D75

    #define GL_RGBA16UI_EXT                                    0x8D76
    #define GL_RGB16UI_EXT                                     0x8D77
    #define GL_ALPHA16UI_EXT                                   0x8D78
    #define GL_INTENSITY16UI_EXT                               0x8D79
    #define GL_LUMINANCE16UI_EXT                               0x8D7A
    #define GL_LUMINANCE_ALPHA16UI_EXT                         0x8D7B

    #define GL_RGBA8UI_EXT                                     0x8D7C
    #define GL_RGB8UI_EXT                                      0x8D7D
    #define GL_ALPHA8UI_EXT                                    0x8D7E
    #define GL_INTENSITY8UI_EXT                                0x8D7F
    #define GL_LUMINANCE8UI_EXT                                0x8D80
    #define GL_LUMINANCE_ALPHA8UI_EXT                          0x8D81

    #define GL_RGBA32I_EXT                                     0x8D82
    #define GL_RGB32I_EXT                                      0x8D83
    #define GL_ALPHA32I_EXT                                    0x8D84
    #define GL_INTENSITY32I_EXT                                0x8D85
    #define GL_LUMINANCE32I_EXT                                0x8D86
    #define GL_LUMINANCE_ALPHA32I_EXT                          0x8D87

    #define GL_RGBA16I_EXT                                     0x8D88
    #define GL_RGB16I_EXT                                      0x8D89
    #define GL_ALPHA16I_EXT                                    0x8D8A
    #define GL_INTENSITY16I_EXT                                0x8D8B
    #define GL_LUMINANCE16I_EXT                                0x8D8C
    #define GL_LUMINANCE_ALPHA16I_EXT                          0x8D8D

    #define GL_RGBA8I_EXT                                      0x8D8E
    #define GL_RGB8I_EXT                                       0x8D8F
    #define GL_ALPHA8I_EXT                                     0x8D90
    #define GL_INTENSITY8I_EXT                                 0x8D91
    #define GL_LUMINANCE8I_EXT                                 0x8D92
    #define GL_LUMINANCE_ALPHA8I_EXT                           0x8D93

    #define GL_RED_INTEGER_EXT                                 0x8D94
    #define GL_GREEN_INTEGER_EXT                               0x8D95
    #define GL_BLUE_INTEGER_EXT                                0x8D96
    #define GL_ALPHA_INTEGER_EXT                               0x8D97
    #define GL_RGB_INTEGER_EXT                                 0x8D98
    #define GL_RGBA_INTEGER_EXT                                0x8D99
    #define GL_BGR_INTEGER_EXT                                 0x8D9A
    #define GL_BGRA_INTEGER_EXT                                0x8D9B
    #define GL_LUMINANCE_INTEGER_EXT                           0x8D9C
    #define GL_LUMINANCE_ALPHA_INTEGER_EXT                     0x8D9D

    #define GL_RGBA_INTEGER_MODE_EXT                           0x8D9E
#endif

#ifndef GL_VERSION_1_1
#define GL_R3_G3_B2                       0x2A10
#define GL_RGB4                           0x804F
#define GL_RGB5                           0x8050
#define GL_RGB8                           0x8051
#define GL_RGB10                          0x8052
#define GL_RGB12                          0x8053
#define GL_RGB16                          0x8054
#define GL_RGBA2                          0x8055
#define GL_RGBA4                          0x8056
#define GL_RGB5_A1                        0x8057
#define GL_RGBA8                          0x8058
#define GL_RGB10_A2                       0x8059
#define GL_RGBA12                         0x805A
#define GL_RGBA16                         0x805B
#define GL_BGR_EXT                        0x80E0
#define GL_BGRA_EXT                       0x80E1
#endif

#ifndef GL_ARB_texture_rg
    #define GL_RG                             0x8227
    #define GL_RG_INTEGER                     0x8228
    #define GL_R8                             0x8229
    #define GL_R16                            0x822A
    #define GL_RG8                            0x822B
    #define GL_RG16                           0x822C
    #define GL_R16F                           0x822D
    #define GL_R32F                           0x822E
    #define GL_RG16F                          0x822F
    #define GL_RG32F                          0x8230
    #define GL_R8I                            0x8231
    #define GL_R8UI                           0x8232
    #define GL_R16I                           0x8233
    #define GL_R16UI                          0x8234
    #define GL_R32I                           0x8235
    #define GL_R32UI                          0x8236
    #define GL_RG8I                           0x8237
    #define GL_RG8UI                          0x8238
    #define GL_RG16I                          0x8239
    #define GL_RG16UI                         0x823A
    #define GL_RG32I                          0x823B
    #define GL_RG32UI                         0x823C
#endif

#ifndef GL_ARB_shader_image_load_store
    #define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
    #define GL_ELEMENT_ARRAY_BARRIER_BIT      0x00000002
    #define GL_UNIFORM_BARRIER_BIT            0x00000004
    #define GL_TEXTURE_FETCH_BARRIER_BIT      0x00000008
    #define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
    #define GL_COMMAND_BARRIER_BIT            0x00000040
    #define GL_PIXEL_BUFFER_BARRIER_BIT       0x00000080
    #define GL_TEXTURE_UPDATE_BARRIER_BIT     0x00000100
    #define GL_BUFFER_UPDATE_BARRIER_BIT      0x00000200
    #define GL_FRAMEBUFFER_BARRIER_BIT        0x00000400
    #define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
    #define GL_ATOMIC_COUNTER_BARRIER_BIT     0x00001000
    #define GL_ALL_BARRIER_BITS               0xFFFFFFFF
    #define GL_MAX_IMAGE_UNITS                0x8F38
    #define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
    #define GL_IMAGE_BINDING_NAME             0x8F3A
    #define GL_IMAGE_BINDING_LEVEL            0x8F3B
    #define GL_IMAGE_BINDING_LAYERED          0x8F3C
    #define GL_IMAGE_BINDING_LAYER            0x8F3D
    #define GL_IMAGE_BINDING_ACCESS           0x8F3E
    #define GL_IMAGE_1D                       0x904C
    #define GL_IMAGE_2D                       0x904D
    #define GL_IMAGE_3D                       0x904E
    #define GL_IMAGE_2D_RECT                  0x904F
    #define GL_IMAGE_CUBE                     0x9050
    #define GL_IMAGE_BUFFER                   0x9051
    #define GL_IMAGE_1D_ARRAY                 0x9052
    #define GL_IMAGE_2D_ARRAY                 0x9053
    #define GL_IMAGE_CUBE_MAP_ARRAY           0x9054
    #define GL_IMAGE_2D_MULTISAMPLE           0x9055
    #define GL_IMAGE_2D_MULTISAMPLE_ARRAY     0x9056
    #define GL_INT_IMAGE_1D                   0x9057
    #define GL_INT_IMAGE_2D                   0x9058
    #define GL_INT_IMAGE_3D                   0x9059
    #define GL_INT_IMAGE_2D_RECT              0x905A
    #define GL_INT_IMAGE_CUBE                 0x905B
    #define GL_INT_IMAGE_BUFFER               0x905C
    #define GL_INT_IMAGE_1D_ARRAY             0x905D
    #define GL_INT_IMAGE_2D_ARRAY             0x905E
    #define GL_INT_IMAGE_CUBE_MAP_ARRAY       0x905F
    #define GL_INT_IMAGE_2D_MULTISAMPLE       0x9060
    #define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
    #define GL_UNSIGNED_INT_IMAGE_1D          0x9062
    #define GL_UNSIGNED_INT_IMAGE_2D          0x9063
    #define GL_UNSIGNED_INT_IMAGE_3D          0x9064
    #define GL_UNSIGNED_INT_IMAGE_2D_RECT     0x9065
    #define GL_UNSIGNED_INT_IMAGE_CUBE        0x9066
    #define GL_UNSIGNED_INT_IMAGE_BUFFER      0x9067
    #define GL_UNSIGNED_INT_IMAGE_1D_ARRAY    0x9068
    #define GL_UNSIGNED_INT_IMAGE_2D_ARRAY    0x9069
    #define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
    #define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
    #define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
    #define GL_MAX_IMAGE_SAMPLES              0x906D
    #define GL_IMAGE_BINDING_FORMAT           0x906E
    #define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
    #define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
    #define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
    #define GL_MAX_VERTEX_IMAGE_UNIFORMS      0x90CA
    #define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
    #define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
    #define GL_MAX_GEOMETRY_IMAGE_UNIFORMS    0x90CD
    #define GL_MAX_FRAGMENT_IMAGE_UNIFORMS    0x90CE
    #define GL_MAX_COMBINED_IMAGE_UNIFORMS    0x90CF
#endif

namespace osg {


/** Texture pure virtual base class that encapsulates OpenGL texture
  * functionality common to the various types of OSG textures.
*/
class OSG_EXPORT Texture : public osg::StateAttribute
{

    public :

        Texture();

        /** Copy constructor using CopyOp to manage deep vs shallow copy. */
        Texture(const Texture& text,const CopyOp& copyop=CopyOp::SHALLOW_COPY);

        virtual osg::Object* cloneType() const = 0;
        virtual osg::Object* clone(const CopyOp& copyop) const = 0;
        virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const Texture *>(obj)!=NULL; }
        virtual const char* libraryName() const { return "osg"; }
        virtual const char* className() const { return "Texture"; }

        /** Fast alternative to dynamic_cast<> for determining if state attribute is a Texture.*/
        virtual Texture* asTexture() { return this; }

        /** Fast alternative to dynamic_cast<> for determining if state attribute is a Texture.*/
        virtual const Texture* asTexture() const { return this; }

        virtual Type getType() const { return TEXTURE; }

        virtual bool isTextureAttribute() const { return true; }

        virtual GLenum getTextureTarget() const = 0;

        virtual bool getModeUsage(StateAttribute::ModeUsage& usage) const
        {
            usage.usesTextureMode(getTextureTarget());
            return true;
        }

        virtual int getTextureWidth() const { return 0; }
        virtual int getTextureHeight() const { return 0; }
        virtual int getTextureDepth() const { return 0; }

        enum WrapParameter {
            WRAP_S,
            WRAP_T,
            WRAP_R
        };

        enum WrapMode {
            CLAMP  = GL_CLAMP,
            CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE,
            CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER_ARB,
            REPEAT = GL_REPEAT,
            MIRROR = GL_MIRRORED_REPEAT_IBM
        };

        /** Sets the texture wrap mode. */
        void setWrap(WrapParameter which, WrapMode wrap);
        /** Gets the texture wrap mode. */
        WrapMode getWrap(WrapParameter which) const;


        /** Sets the border color. Only used when wrap mode is CLAMP_TO_BORDER.
         * The border color will be casted to the appropriate type to match the
         * internal pixel format of the texture. */
        void setBorderColor(const Vec4d& color) { _borderColor = color; dirtyTextureParameters(); }

        /** Gets the border color. */
        const Vec4d& getBorderColor() const { return _borderColor; }

        /** Sets the border width. */
        void setBorderWidth(GLint width) { _borderWidth = width; dirtyTextureParameters(); }

        GLint getBorderWidth() const { return _borderWidth; }

        enum FilterParameter {
            MIN_FILTER,
            MAG_FILTER
        };

        enum FilterMode {
            LINEAR                    = GL_LINEAR,
            LINEAR_MIPMAP_LINEAR      = GL_LINEAR_MIPMAP_LINEAR,
            LINEAR_MIPMAP_NEAREST     = GL_LINEAR_MIPMAP_NEAREST,
            NEAREST                   = GL_NEAREST,
            NEAREST_MIPMAP_LINEAR     = GL_NEAREST_MIPMAP_LINEAR,
            NEAREST_MIPMAP_NEAREST    = GL_NEAREST_MIPMAP_NEAREST
        };

        /** Sets the texture filter mode. */
        void setFilter(FilterParameter which, FilterMode filter);

        /** Gets the texture filter mode. */
        FilterMode getFilter(FilterParameter which) const;

        /** Sets the maximum anisotropy value, default value is 1.0 for no
          * anisotropic filtering. If hardware does not support anisotropic
          * filtering, use normal filtering (equivalent to a max anisotropy
          * value of 1.0. Valid range is 1.0f upwards.  The maximum value
          * depends on the graphics system. */
        void setMaxAnisotropy(float anis);

        /** Gets the maximum anisotropy value. */
        inline float getMaxAnisotropy() const { return _maxAnisotropy; }

        /** Configure the source of texture swizzling for all channels */
        inline void setSwizzle(const Vec4i& swizzle) { _swizzle = swizzle; dirtyTextureParameters(); };

        /** Gets the source of texture swizzling for all channels */
        inline const Vec4i& getSwizzle() const { return _swizzle; }

        /** Sets the hardware mipmap generation hint. If enabled, it will
          * only be used if supported in the graphics system. */
        inline void setUseHardwareMipMapGeneration(bool useHardwareMipMapGeneration) { _useHardwareMipMapGeneration = useHardwareMipMapGeneration; }

        /** Gets the hardware mipmap generation hint. */
        inline bool getUseHardwareMipMapGeneration() const { return _useHardwareMipMapGeneration; }

        /** Sets whether or not the apply() function will unreference the image
          * data. If enabled, and the image data is only referenced by this
          * Texture, apply() will delete the image data. */
        inline void setUnRefImageDataAfterApply(bool flag) { _unrefImageDataAfterApply = flag; }

        /** Gets whether or not apply() unreferences image data. */
        inline bool getUnRefImageDataAfterApply() const { return _unrefImageDataAfterApply; }

        /** Sets whether to use client storage for the texture, if supported
          * by the graphics system. Note: If enabled, and the graphics system
          * supports it, the osg::Image(s) associated with this texture cannot
          * be deleted, so the UnRefImageDataAfterApply flag would be ignored. */
        inline void setClientStorageHint(bool flag) { _clientStorageHint = flag; }

        /** Gets whether to use client storage for the texture. */
        inline bool getClientStorageHint() const { return _clientStorageHint; }

        /** Sets whether to force the texture to resize images that have dimensions
          * that are not a power of two. If enabled, NPOT images will be resized,
          * whether or not NPOT textures are supported by the hardware. If disabled,
          * NPOT images will not be resized if supported by hardware. */
        inline void setResizeNonPowerOfTwoHint(bool flag) { _resizeNonPowerOfTwoHint = flag; }

        /** Gets whether texture will force non power to two images to be resized. */
        inline bool getResizeNonPowerOfTwoHint() const { return _resizeNonPowerOfTwoHint; }

        enum InternalFormatMode {
            USE_IMAGE_DATA_FORMAT,
            USE_USER_DEFINED_FORMAT,
            USE_ARB_COMPRESSION,
            USE_S3TC_DXT1_COMPRESSION,
            USE_S3TC_DXT3_COMPRESSION,
            USE_S3TC_DXT5_COMPRESSION,
            USE_PVRTC_2BPP_COMPRESSION,
            USE_PVRTC_4BPP_COMPRESSION,
            USE_ETC_COMPRESSION,
            USE_RGTC1_COMPRESSION,
            USE_RGTC2_COMPRESSION,
            USE_S3TC_DXT1c_COMPRESSION,
            USE_S3TC_DXT1a_COMPRESSION
        };

        /** Sets the internal texture format mode. Note: If the texture format is
          * USE_IMAGE_DATA_FORMAT, USE_ARB_COMPRESSION, or USE_S3TC_COMPRESSION,
          * the internal format mode is set automatically and will overwrite the
          * previous _internalFormat. */
        inline void setInternalFormatMode(InternalFormatMode mode) { _internalFormatMode = mode; }

        /** Gets the internal texture format mode. */
        inline InternalFormatMode getInternalFormatMode() const { return _internalFormatMode; }

        /** Sets the internal texture format. Implicitly sets the
          * internalFormatMode to USE_USER_DEFINED_FORMAT.
          * The corresponding internal format type will be computed. */
        inline void setInternalFormat(GLint internalFormat)
        {
            _internalFormatMode = USE_USER_DEFINED_FORMAT;
            _internalFormat = internalFormat;
            computeInternalFormatType();
        }


        /** Gets the internal texture format. */
        inline GLint getInternalFormat() const { if (_internalFormat==0) computeInternalFormat(); return _internalFormat; }

        /** Return true if the internal format is one of the compressed formats.*/
        bool isCompressedInternalFormat() const;

        /** Sets the external source image format, used as a fallback when no osg::Image is attached to provide the source image format. */
        inline void setSourceFormat(GLenum sourceFormat) { _sourceFormat = sourceFormat; }

        /** Gets the external source image format. */
        inline GLenum getSourceFormat() const { return _sourceFormat; }

        /** Sets the external source data type, used as a fallback when no osg::Image is attached to provide the source image format.*/
        inline void setSourceType(GLenum sourceType) { _sourceType = sourceType; }

        /** Gets the external source data type.*/
        inline GLenum getSourceType() const { return _sourceType; }

        /** Texture type determined by the internal texture format */
        enum InternalFormatType{

            //! default OpenGL format (clamped values to [0,1) or [0,255])
            NORMALIZED = 0x0,

            //! float values, Shader Model 3.0 (see ARB_texture_float)
            FLOAT = 0x1,

            //! Signed integer values (see EXT_texture_integer)
            SIGNED_INTEGER = 0x2,

            //! Unsigned integer value (see EXT_texture_integer)
            UNSIGNED_INTEGER = 0x4
        };

        /** Get the internal texture format type. */
        inline InternalFormatType getInternalFormatType() const { return _internalFormatType; }

        class TextureObject;

        /** Returns a pointer to the TextureObject for the current context. */
        inline TextureObject* getTextureObject(unsigned int contextID) const
        {
            return _textureObjectBuffer[contextID].get();
        }

        inline void setTextureObject(unsigned int contextID, TextureObject* to)
        {
            _textureObjectBuffer[contextID] = to;
        }

        /** Forces a recompile on next apply() of associated OpenGL texture
          * objects. */
        void dirtyTextureObject();

        /** Returns true if the texture objects for all the required graphics
          * contexts are loaded. */
        bool areAllTextureObjectsLoaded() const;


        /** Gets the dirty flag for the current contextID. */
        inline unsigned int& getTextureParameterDirty(unsigned int contextID) const
        {
            return _texParametersDirtyList[contextID];
        }


        /** Force a reset on next apply() of associated OpenGL texture
          * parameters. */
        void dirtyTextureParameters();

        /** Force a manual allocation of the mipmap levels on the next apply() call.
          * User is responsible for filling the mipmap levels with valid data.
          * The OpenGL's glGenerateMipmapEXT function is used to generate the mipmap levels.
          * If glGenerateMipmapEXT is not supported or texture's internal format is not supported
          * by the glGenerateMipmapEXT, then empty mipmap levels will
          * be allocated manually. The mipmap levels are also allocated if a non-mipmapped
          * min filter is used. */
        void allocateMipmapLevels();

        /** Encapsulates texture image load/store attributes */
        struct ImageAttachment
        {
            GLuint unit;
            GLint level;
            GLboolean layered;
            GLint layer;
            GLenum access;
            GLenum format;
            
            ImageAttachment()
            : unit(0), level(0), layered(GL_FALSE), layer(0), access(0), format(0) {}
        };

        /** Type of access that will be performed on the texture image. */
        enum ImageAccess
        {
             NOT_USED = 0,
             READ_ONLY = GL_READ_ONLY_ARB,
             WRITE_ONLY = GL_WRITE_ONLY_ARB,
             READ_WRITE = GL_READ_WRITE_ARB
        };

        /** Bind texture to an image unit (available only if GL version is 4.2 or greater)
          * The format parameter for the image unit need not exactly match the texture internal format,
          * but if it is set to 0, the texture internal format will be used.
          * See http://www.opengl.org/registry/specs/ARB/shader_image_load_store.txt */
        void bindToImageUnit(unsigned int unit, GLenum access, GLenum format=0, int level=0, bool layered=false, int layer=0);

        ImageAttachment& getImageAttachment() { return _imageAttachment; }
        const ImageAttachment& getImageAttachment() const { return _imageAttachment; }

        /** Sets GL_TEXTURE_COMPARE_MODE_ARB to GL_COMPARE_R_TO_TEXTURE_ARB
          * See http://oss.sgi.com/projects/ogl-sample/registry/ARB/shadow.txt. */
        void setShadowComparison(bool flag) { _use_shadow_comparison = flag; }
        bool getShadowComparison() const { return _use_shadow_comparison; }

        enum ShadowCompareFunc {
            NEVER = GL_NEVER,
            LESS = GL_LESS,
            EQUAL = GL_EQUAL,
            LEQUAL = GL_LEQUAL,
            GREATER = GL_GREATER,
            NOTEQUAL = GL_NOTEQUAL,
            GEQUAL = GL_GEQUAL,
            ALWAYS = GL_ALWAYS
        };

        /** Sets shadow texture comparison function. */
        void setShadowCompareFunc(ShadowCompareFunc func) { _shadow_compare_func = func; }
        ShadowCompareFunc getShadowCompareFunc() const { return _shadow_compare_func; }

        enum ShadowTextureMode {
            LUMINANCE = GL_LUMINANCE,
            INTENSITY = GL_INTENSITY,
            ALPHA = GL_ALPHA
        };

        /** Sets shadow texture mode after comparison. */
        void setShadowTextureMode(ShadowTextureMode mode) { _shadow_texture_mode = mode; }
        ShadowTextureMode getShadowTextureMode() const { return _shadow_texture_mode; }

        /** Sets the TEXTURE_COMPARE_FAIL_VALUE_ARB texture parameter. See
          * http://oss.sgi.com/projects/ogl-sample/registry/ARB/shadow_ambient.txt. */
        void setShadowAmbient(float shadow_ambient) { _shadow_ambient = shadow_ambient; }
        float getShadowAmbient() const { return _shadow_ambient; }


        /** Sets the texture image for the specified face. */
        virtual void setImage(unsigned int face, Image* image) = 0;

        /** Gets the texture image for the specified face. */
        virtual Image* getImage(unsigned int face) = 0;

        /** Gets the const texture image for specified face. */
        virtual const Image* getImage(unsigned int face) const = 0;

        /** Gets the number of images that can be assigned to this Texture. */
        virtual unsigned int getNumImages() const = 0;


        /** Set the PBuffer graphics context to read from when using PBuffers for RenderToTexture.*/
        void setReadPBuffer(GraphicsContext* context) { _readPBuffer = context; }

        /** Get the PBuffer graphics context to read from when using PBuffers for RenderToTexture.*/
        GraphicsContext* getReadPBuffer() { return _readPBuffer.get(); }

        /** Get the const PBuffer graphics context to read from when using PBuffers for RenderToTexture.*/
        const GraphicsContext* getReadPBuffer() const { return _readPBuffer.get(); }

        /** Texture is a pure virtual base class, apply must be overridden. */
        virtual void apply(State& state) const = 0;

        /** Calls apply(state) to compile the texture. */
        virtual void compileGLObjects(State& state) const;

        /** Resize any per context GLObject buffers to specified size. */
        virtual void resizeGLObjectBuffers(unsigned int maxSize);

        /** If State is non-zero, this function releases OpenGL objects for
          * the specified graphics context. Otherwise, releases OpenGL objects
          * for all graphics contexts. */
        virtual void releaseGLObjects(State* state=0) const;

        /** Encapsulates queries of extension availability, obtains extension
          * function pointers, and provides convenience wrappers for
          * calling extension functions. */
        class OSG_EXPORT Extensions : public osg::Referenced
        {
            public:
                Extensions(unsigned int contextID);

                void setMultiTexturingSupported(bool flag) { _isMultiTexturingSupported=flag; }
                bool isMultiTexturingSupported() const { return _isMultiTexturingSupported; }

                void setTextureFilterAnisotropicSupported(bool flag) { _isTextureFilterAnisotropicSupported=flag; }
                bool isTextureFilterAnisotropicSupported() const { return _isTextureFilterAnisotropicSupported; }

                void setTextureSwizzleSupported(bool flag) { _isTextureSwizzleSupported=flag; }
                bool isTextureSwizzleSupported() const { return _isTextureSwizzleSupported; }

                void setTextureCompressionARBSupported(bool flag) { _isTextureCompressionARBSupported=flag; }
                bool isTextureCompressionARBSupported() const { return _isTextureCompressionARBSupported; }

                void setTextureCompressionS3TCSupported(bool flag) { _isTextureCompressionS3TCSupported=flag; }
                bool isTextureCompressionS3TCSupported() const { return _isTextureCompressionS3TCSupported; }

                void setTextureCompressionPVRTC2BPPSupported(bool flag) { _isTextureCompressionPVRTC2BPPSupported=flag; }
                bool isTextureCompressionPVRTC2BPPSupported() const { return _isTextureCompressionPVRTC2BPPSupported; }

                void setTextureCompressionPVRTC4BPPSupported(bool flag) { _isTextureCompressionPVRTC4BPPSupported=flag; }
                bool isTextureCompressionPVRTC4BPPSupported() const { return _isTextureCompressionPVRTC4BPPSupported; }

                void setTextureCompressionETCSupported(bool flag) { _isTextureCompressionETCSupported=flag; }
                bool isTextureCompressionETCSupported() const { return _isTextureCompressionETCSupported; }

                void setTextureCompressionRGTCSupported(bool flag) { _isTextureCompressionRGTCSupported=flag; }
                bool isTextureCompressionRGTCSupported() const { return _isTextureCompressionRGTCSupported; }

                void setTextureCompressionPVRTCSupported(bool flag) { _isTextureCompressionPVRTCSupported=flag; }
                bool isTextureCompressionPVRTCSupported() const { return _isTextureCompressionPVRTCSupported; }

                void setTextureMirroredRepeatSupported(bool flag) { _isTextureMirroredRepeatSupported=flag; }
                bool isTextureMirroredRepeatSupported() const { return _isTextureMirroredRepeatSupported; }

                void setTextureEdgeClampSupported(bool flag) { _isTextureEdgeClampSupported=flag; }
                bool isTextureEdgeClampSupported() const { return _isTextureEdgeClampSupported; }

                void setTextureBorderClampSupported(bool flag) { _isTextureBorderClampSupported=flag; }
                bool isTextureBorderClampSupported() const { return _isTextureBorderClampSupported; }

                void setGenerateMipMapSupported(bool flag) { _isGenerateMipMapSupported=flag; }
                bool isGenerateMipMapSupported() const { return _isGenerateMipMapSupported; }

                void setPreferGenerateMipmapSGISForPowerOfTwo(bool flag) { _preferGenerateMipmapSGISForPowerOfTwo = flag; }
                bool getPreferGenerateMipmapSGISForPowerOfTwo() const { return _preferGenerateMipmapSGISForPowerOfTwo; }

                void setTextureMultisampledSupported(bool flag) { _isTextureMultisampledSupported=flag; }
                bool isTextureMultisampledSupported() const { return _isTextureMultisampledSupported; }

                void setShadowSupported(bool flag) { _isShadowSupported = flag; }
                bool isShadowSupported() const { return _isShadowSupported; }

                void setShadowAmbientSupported(bool flag) { _isShadowAmbientSupported = flag; }
                bool isShadowAmbientSupported() const { return _isShadowAmbientSupported; }

                void setTextureMaxLevelSupported(bool flag) { _isTextureMaxLevelSupported = flag; }
                bool isTextureMaxLevelSupported() const { return _isTextureMaxLevelSupported; }

                void setMaxTextureSize(GLint maxsize) { _maxTextureSize=maxsize; }
                GLint maxTextureSize() const { return _maxTextureSize; }

                void setNumTextureUnits(GLint nunits ) { _numTextureUnits=nunits; }
                GLint numTextureUnits() const { return _numTextureUnits; }

                bool isCompressedTexImage2DSupported() const { return _glCompressedTexImage2D!=0; }
                bool isCompressedTexSubImage2DSupported() const { return _glCompressedTexSubImage2D!=0; }

                bool isClientStorageSupported() const { return _isClientStorageSupported; }

                bool isNonPowerOfTwoTextureSupported(GLenum filter) const
                {
                    return (filter==GL_LINEAR || filter==GL_NEAREST) ?
                            _isNonPowerOfTwoTextureNonMipMappedSupported :
                            _isNonPowerOfTwoTextureMipMappedSupported;
                }

                void setTextureIntegerSupported(bool flag) { _isTextureIntegerEXTSupported=flag; }
                bool isTextureIntegerSupported() const { return _isTextureIntegerEXTSupported; }

                bool isBindImageTextureSupported() const { return _glBindImageTexture!=0; }

                void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) const
                {
                    _glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
                }

                void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) const
                {
                    _glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
                }

                void glGetCompressedTexImage(GLenum target, GLint level, GLvoid *data) const
                {
                    _glGetCompressedTexImage(target, level, data);
                }

                void glTexImage2DMultisample(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) const
                {
                    _glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);
                }

                void glTexParameterIiv(GLenum target, GLenum pname, const GLint* data) const
                {
                    _glTexParameterIiv(target, pname, data);
                }

                void glTexParameterIuiv(GLenum target, GLenum pname, const GLuint* data) const
                {
                    _glTexParameterIuiv(target, pname, data);
                }

                // ARB_shader_image_load_store
                void glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) const
                {
                    _glBindImageTexture(unit, texture, level, layered, layer, access, format);
                }

            protected:

                ~Extensions() {}

                typedef void (GL_APIENTRY * CompressedTexImage2DArbProc) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
                typedef void (GL_APIENTRY * CompressedTexSubImage2DArbProc) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
                typedef void (GL_APIENTRY * GetCompressedTexImageArbProc) (GLenum target, GLint level, GLvoid *data);
                typedef void (GL_APIENTRY * TexImage2DMultisample)(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
                typedef void (GL_APIENTRY * TexParameterIivProc)(GLenum target, GLenum pname, const GLint* data);
                typedef void (GL_APIENTRY * TexParameterIuivProc)(GLenum target, GLenum pname, const GLuint* data);
                typedef void (GL_APIENTRY * BindImageTextureProc)( GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format );

                CompressedTexImage2DArbProc     _glCompressedTexImage2D;
                CompressedTexSubImage2DArbProc  _glCompressedTexSubImage2D;
                GetCompressedTexImageArbProc    _glGetCompressedTexImage;
                TexImage2DMultisample           _glTexImage2DMultisample;
                TexParameterIivProc             _glTexParameterIiv;
                TexParameterIuivProc            _glTexParameterIuiv;

                // ARB_shader_image_load_store
                BindImageTextureProc            _glBindImageTexture;

                bool    _isMultiTexturingSupported;
                bool    _isTextureFilterAnisotropicSupported;
                bool    _isTextureSwizzleSupported;
                bool    _isTextureCompressionARBSupported;
                bool    _isTextureCompressionS3TCSupported;
                bool    _isTextureCompressionPVRTC2BPPSupported;
                bool    _isTextureCompressionPVRTC4BPPSupported;
                bool    _isTextureCompressionETCSupported;
                bool    _isTextureCompressionRGTCSupported;
                bool    _isTextureCompressionPVRTCSupported;
                bool    _isTextureMirroredRepeatSupported;
                bool    _isTextureEdgeClampSupported;
                bool    _isTextureBorderClampSupported;
                bool    _isGenerateMipMapSupported;
                bool    _preferGenerateMipmapSGISForPowerOfTwo;
                bool    _isTextureMultisampledSupported;
                bool    _isShadowSupported;
                bool    _isShadowAmbientSupported;
                bool    _isClientStorageSupported;
                bool    _isNonPowerOfTwoTextureMipMappedSupported;
                bool    _isNonPowerOfTwoTextureNonMipMappedSupported;
                bool    _isTextureIntegerEXTSupported;
                bool    _isTextureMaxLevelSupported;

                GLint   _maxTextureSize;
                GLint   _numTextureUnits;
        };

        /** Gets the extension for the specified context. Creates the
          * Extensions object for that context if it doesn't exist.
          * Returns NULL if the Extensions object for the context doesn't
          * exist and the createIfNotInitalized flag is false. */
        static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized);

        /** Overrides Extensions objects across graphics contexts. Typically
          * used to ensure the same lowest common denominator of extensions
          * on systems with different graphics pipes. */
        static void setExtensions(unsigned int contextID,Extensions* extensions);

        /** Determine whether the given internalFormat is a compressed
          * image format. */
        static bool isCompressedInternalFormat(GLint internalFormat);

        /** Determine the size of a compressed image, given the internalFormat,
          * the width, the height, and the depth of the image. The block size
          * and the size are output parameters. */
        static void getCompressedSize(GLenum internalFormat, GLint width, GLint height, GLint depth, GLint& blockSize, GLint& size);


        /** Helper method. Creates the texture, but doesn't set or use a
          * texture binding. Note: Don't call this method directly unless
          * you're implementing a subload callback. */
        void applyTexImage2D_load(State& state, GLenum target, const Image* image, GLsizei width, GLsizei height,GLsizei numMipmapLevels) const;

        /** Helper method. Subloads images into the texture, but doesn't set
          * or use a texture binding. Note: Don't call this method directly
          * unless you're implementing a subload callback. */
        void applyTexImage2D_subload(State& state, GLenum target, const Image* image, GLsizei width, GLsizei height, GLint inInternalFormat, GLsizei numMipmapLevels) const;


        /** Returned by mipmapBeforeTexImage() to indicate what
          * mipmapAfterTexImage() should do */
        enum GenerateMipmapMode
        {
            GENERATE_MIPMAP_NONE,
            GENERATE_MIPMAP,
            GENERATE_MIPMAP_TEX_PARAMETER
        };

    protected :

        virtual ~Texture();

        virtual void computeInternalFormat() const = 0;

        /** Computes the internal format from Image parameters. */
        void computeInternalFormatWithImage(const osg::Image& image) const;

        /** Computes the texture dimension for the given Image. */
        void computeRequiredTextureDimensions(State& state, const osg::Image& image,GLsizei& width, GLsizei& height,GLsizei& numMipmapLevels) const;

        /** Computes the internal format type. */
        void computeInternalFormatType() const;

        /** Helper method. Sets texture parameters. */
        void applyTexParameters(GLenum target, State& state) const;

        /** Returns true if _useHardwareMipMapGeneration is true and either
          * glGenerateMipmapEXT() or GL_GENERATE_MIPMAP_SGIS are supported. */
        bool isHardwareMipmapGenerationEnabled(const State& state) const;

        /** Returns true if the associated Image should be released and it's safe to do so. */
        bool isSafeToUnrefImageData(const State& state) const {
            return (_unrefImageDataAfterApply && state.getMaxTexturePoolSize()==0 && areAllTextureObjectsLoaded());
        }

        /** Helper methods to be called before and after calling
          * gl[Compressed][Copy]Tex[Sub]Image2D to handle generating mipmaps. */
        GenerateMipmapMode mipmapBeforeTexImage(const State& state, bool hardwareMipmapOn) const;
        void mipmapAfterTexImage(State& state, GenerateMipmapMode beforeResult) const;

        /** Helper method to generate mipmap levels by calling of glGenerateMipmapEXT.
          * If it is not supported, then call the virtual allocateMipmap() method */
        void generateMipmap(State& state) const;

        /** Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. */
        virtual void allocateMipmap(State& state) const = 0;

        /** Returns -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
        int compareTexture(const Texture& rhs) const;

        /** Returns -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
        int compareTextureObjects(const Texture& rhs) const;

        typedef buffered_value<unsigned int> TexParameterDirtyList;
        mutable TexParameterDirtyList _texParametersDirtyList;
        mutable TexParameterDirtyList _texMipmapGenerationDirtyList;

        WrapMode _wrap_s;
        WrapMode _wrap_t;
        WrapMode _wrap_r;

        FilterMode      _min_filter;
        FilterMode      _mag_filter;
        float           _maxAnisotropy;
        Vec4i           _swizzle;
        bool            _useHardwareMipMapGeneration;
        bool            _unrefImageDataAfterApply;
        bool            _clientStorageHint;
        bool            _resizeNonPowerOfTwoHint;

        Vec4d           _borderColor;
        GLint           _borderWidth;

        InternalFormatMode          _internalFormatMode;
        mutable InternalFormatType  _internalFormatType;
        mutable GLint       _internalFormat;
        mutable GLenum      _sourceFormat;
        mutable GLenum      _sourceType;

        bool                _use_shadow_comparison;
        ShadowCompareFunc   _shadow_compare_func;
        ShadowTextureMode   _shadow_texture_mode;
        float               _shadow_ambient;

        ImageAttachment _imageAttachment;

    public:

        struct OSG_EXPORT TextureProfile
        {
            inline TextureProfile(GLenum target):
                _target(target),
                _numMipmapLevels(0),
                _internalFormat(0),
                _width(0),
                _height(0),
                _depth(0),
                _border(0),
                _size(0) {}

            inline TextureProfile(GLenum    target,
                                 GLint     numMipmapLevels,
                                 GLenum    internalFormat,
                                 GLsizei   width,
                                 GLsizei   height,
                                 GLsizei   depth,
                                 GLint     border):
                _target(target),
                _numMipmapLevels(numMipmapLevels),
                _internalFormat(internalFormat),
                _width(width),
                _height(height),
                _depth(depth),
                _border(border),
                _size(0) { computeSize(); }


            #define LESSTHAN(A,B) if (A<B) return true; if (B<A) return false;
            #define FINALLESSTHAN(A,B) return (A<B);

            bool operator < (const TextureProfile& rhs) const
            {
                LESSTHAN(_size,rhs._size);
                LESSTHAN(_target,rhs._target);
                LESSTHAN(_numMipmapLevels,rhs._numMipmapLevels);
                LESSTHAN(_internalFormat,rhs._internalFormat);
                LESSTHAN(_width,rhs._width);
                LESSTHAN(_height,rhs._height);
                LESSTHAN(_depth,rhs._depth);
                FINALLESSTHAN(_border, rhs._border);
            }

            bool operator == (const TextureProfile& rhs) const
            {
                return _target == rhs._target &&
                       _numMipmapLevels == rhs._numMipmapLevels &&
                       _internalFormat == rhs._internalFormat &&
                       _width == rhs._width &&
                       _height == rhs._height &&
                       _depth == rhs._depth &&
                       _border == rhs._border;
            }

            inline void set(GLint numMipmapLevels,
                            GLenum    internalFormat,
                            GLsizei   width,
                            GLsizei   height,
                            GLsizei   depth,
                            GLint     border)
            {
                _numMipmapLevels = numMipmapLevels;
                _internalFormat = internalFormat;
                _width = width;
                _height = height;
                _depth = depth;
                _border = border;
                computeSize();
            }

            inline bool match(GLenum    target,
                       GLint     numMipmapLevels,
                       GLenum    internalFormat,
                       GLsizei   width,
                       GLsizei   height,
                       GLsizei   depth,
                       GLint     border)
            {
                return (_target == target) &&
                       (_numMipmapLevels == numMipmapLevels) &&
                       (_internalFormat == internalFormat) &&
                       (_width == width) &&
                       (_height == height) &&
                       (_depth == depth) &&
                       (_border == border);
            }

            void computeSize();

            GLenum       _target;
            GLint        _numMipmapLevels;
            GLenum       _internalFormat;
            GLsizei      _width;
            GLsizei      _height;
            GLsizei      _depth;
            GLint        _border;
            unsigned int _size;
        };

        // forward declare
        class TextureObjectSet;
        class TextureObjectManager;

        class OSG_EXPORT TextureObject : public osg::Referenced
        {
        public:

            inline TextureObject(Texture* texture, GLuint id, GLenum target):
                _id(id),
                _profile(target),
                _set(0),
                _previous(0),
                _next(0),
                _texture(texture),
                _allocated(false),
                _timeStamp(0) {}

            inline TextureObject(Texture* texture, GLuint id, const TextureProfile& profile):
                _id(id),
                _profile(profile),
                _set(0),
                _previous(0),
                _next(0),
                _texture(texture),
                _allocated(false),
                _timeStamp(0) {}

            inline TextureObject(Texture* texture,
                          GLuint    id,
                          GLenum    target,
                          GLint     numMipmapLevels,
                          GLenum    internalFormat,
                          GLsizei   width,
                          GLsizei   height,
                          GLsizei   depth,
                          GLint     border):
                _id(id),
                _profile(target,numMipmapLevels,internalFormat,width,height,depth,border),
                _set(0),
                _previous(0),
                _next(0),
                _texture(texture),
                _allocated(false),
                _timeStamp(0) {}

            inline bool match(GLenum    target,
                       GLint     numMipmapLevels,
                       GLenum    internalFormat,
                       GLsizei   width,
                       GLsizei   height,
                       GLsizei   depth,
                       GLint     border)
            {
                return isReusable() &&
                       _profile.match(target,numMipmapLevels,internalFormat,width,height,depth,border);
            }


            void bind();

            inline GLenum id() const { return _id; }
            inline GLenum target() const { return _profile._target; }

            inline unsigned int size() const { return _profile._size; }

            inline void setTexture(Texture* texture) { _texture = texture; }
            inline Texture* getTexture() const { return _texture; }

            inline void setTimeStamp(double timestamp) { _timeStamp = timestamp; }
            inline double getTimeStamp() const { return _timeStamp; }

            inline void setAllocated(bool allocated=true) { _allocated = allocated; }

            void setAllocated(GLint     numMipmapLevels,
                              GLenum    internalFormat,
                              GLsizei   width,
                              GLsizei   height,
                              GLsizei   depth,
                              GLint     border);

            inline bool isAllocated() const { return _allocated; }

            inline bool isReusable() const { return _allocated && _profile._width!=0; }


            GLuint              _id;
            TextureProfile      _profile;
            TextureObjectSet*   _set;
            TextureObject*      _previous;
            TextureObject*      _next;
            Texture*            _texture;
            bool                _allocated;
            unsigned int        _frameLastUsed;
            double              _timeStamp;

        protected:
            virtual ~TextureObject();

        };

        typedef std::list< ref_ptr<TextureObject> > TextureObjectList;

        class OSG_EXPORT TextureObjectSet : public Referenced
        {
        public:
            TextureObjectSet(TextureObjectManager* parent, const TextureProfile& profile);

            const TextureProfile& getProfile() const { return _profile; }

            void handlePendingOrphandedTextureObjects();

            void deleteAllTextureObjects();
            void discardAllTextureObjects();
            void flushAllDeletedTextureObjects();
            void discardAllDeletedTextureObjects();
            void flushDeletedTextureObjects(double currentTime, double& availableTime);

            TextureObject* takeFromOrphans(Texture* texture);
            TextureObject* takeOrGenerate(Texture* texture);
            void moveToBack(TextureObject* to);
            void addToBack(TextureObject* to);
            void orphan(TextureObject* to);
            void remove(TextureObject* to);
            void moveToSet(TextureObject* to, TextureObjectSet* set);

            unsigned int size() const { return _profile._size * _numOfTextureObjects; }

            bool makeSpace(unsigned int& size);

            bool checkConsistency() const;

            TextureObjectManager* getParent() { return _parent; }

            unsigned int computeNumTextureObjectsInList() const;
            unsigned int getNumOfTextureObjects() const { return _numOfTextureObjects; }
            unsigned int getNumOrphans() const { return static_cast<unsigned int>(_orphanedTextureObjects.size()); }
            unsigned int getNumPendingOrphans() const { return static_cast<unsigned int>(_pendingOrphanedTextureObjects.size()); }

        protected:

            virtual ~TextureObjectSet();

            OpenThreads::Mutex  _mutex;

            TextureObjectManager*       _parent;
            unsigned int                _contextID;
            TextureProfile              _profile;
            unsigned int                _numOfTextureObjects;
            TextureObjectList           _orphanedTextureObjects;
            TextureObjectList           _pendingOrphanedTextureObjects;

            TextureObject*              _head;
            TextureObject*              _tail;

        };

        class OSG_EXPORT TextureObjectManager : public osg::Referenced
        {
        public:
            TextureObjectManager(unsigned int contextID);

            unsigned int getContextID() const { return _contextID; }



            void setNumberActiveTextureObjects(unsigned int size) { _numActiveTextureObjects = size; }
            unsigned int& getNumberActiveTextureObjects() { return _numActiveTextureObjects; }
            unsigned int getNumberActiveTextureObjects() const { return _numActiveTextureObjects; }

            void setNumberOrphanedTextureObjects(unsigned int size) { _numOrphanedTextureObjects = size; }
            unsigned int& getNumberOrphanedTextureObjects() { return _numOrphanedTextureObjects; }
            unsigned int getNumberOrphanedTextureObjects() const { return _numOrphanedTextureObjects; }

            void setCurrTexturePoolSize(unsigned int size) { _currTexturePoolSize = size; }
            unsigned int& getCurrTexturePoolSize() { return _currTexturePoolSize; }
            unsigned int getCurrTexturePoolSize() const { return _currTexturePoolSize; }

            void setMaxTexturePoolSize(unsigned int size);
            unsigned int getMaxTexturePoolSize() const { return _maxTexturePoolSize; }

            bool hasSpace(unsigned int size) const { return (_currTexturePoolSize+size)<=_maxTexturePoolSize; }
            bool makeSpace(unsigned int size);

            TextureObject* generateTextureObject(const Texture* texture, GLenum target);
            TextureObject* generateTextureObject(const Texture* texture,
                                                        GLenum    target,
                                                        GLint     numMipmapLevels,
                                                        GLenum    internalFormat,
                                                        GLsizei   width,
                                                        GLsizei   height,
                                                        GLsizei   depth,
                                                        GLint     border);
            void handlePendingOrphandedTextureObjects();
            void deleteAllTextureObjects();
            void discardAllTextureObjects();
            void flushAllDeletedTextureObjects();
            void discardAllDeletedTextureObjects();
            void flushDeletedTextureObjects(double currentTime, double& availableTime);
            void releaseTextureObject(TextureObject* to);

            TextureObjectSet* getTextureObjectSet(const TextureProfile& profile);

            void newFrame(osg::FrameStamp* fs);
            void resetStats();
            void reportStats(std::ostream& out);
            void recomputeStats(std::ostream& out) const;
            bool checkConsistency() const;

            unsigned int& getFrameNumber() { return _frameNumber; }
            unsigned int& getNumberFrames() { return _numFrames; }

            unsigned int& getNumberDeleted() { return _numDeleted; }
            double& getDeleteTime() { return _deleteTime; }

            unsigned int& getNumberGenerated() { return _numGenerated; }
            double& getGenerateTime() { return _generateTime; }

            unsigned int& getNumberApplied() { return _numApplied; }
            double& getApplyTime() { return _applyTime; }


        protected:

            typedef std::map< TextureProfile, osg::ref_ptr<TextureObjectSet> > TextureSetMap;
            unsigned int        _contextID;
            unsigned int        _numActiveTextureObjects;
            unsigned int        _numOrphanedTextureObjects;
            unsigned int        _currTexturePoolSize;
            unsigned int        _maxTexturePoolSize;
            TextureSetMap       _textureSetMap;

            unsigned int        _frameNumber;

            unsigned int        _numFrames;
            unsigned int        _numDeleted;
            double              _deleteTime;

            unsigned int        _numGenerated;
            double              _generateTime;

            unsigned int        _numApplied;
            double              _applyTime;

        };

        static osg::ref_ptr<Texture::TextureObjectManager>&  getTextureObjectManager(unsigned int contextID);

        static TextureObject* generateTextureObject(const Texture* texture, unsigned int contextID,GLenum target);

        static TextureObject* generateTextureObject(const Texture* texture,
                                                     unsigned int contextID,
                                                     GLenum    target,
                                                     GLint     numMipmapLevels,
                                                     GLenum    internalFormat,
                                                     GLsizei   width,
                                                     GLsizei   height,
                                                     GLsizei   depth,
                                                     GLint     border);

        static void deleteAllTextureObjects(unsigned int contextID);
        static void discardAllTextureObjects(unsigned int contextID);
        static void flushAllDeletedTextureObjects(unsigned int contextID);
        static void discardAllDeletedTextureObjects(unsigned int contextID);
        static void flushDeletedTextureObjects(unsigned int contextID,double currentTime, double& availableTime);
        static void releaseTextureObject(unsigned int contextID, TextureObject* to);

    protected:

        typedef buffered_object< ref_ptr<TextureObject> >  TextureObjectBuffer;
        mutable TextureObjectBuffer         _textureObjectBuffer;
        mutable ref_ptr<GraphicsContext>    _readPBuffer;

};

}

#endif