]> git.cworth.org Git - apitrace/blobdiff - glstate.py
Fix glCompressed*Image*DARB tracing/retracing
[apitrace] / glstate.py
index afcfa8282cb9295c4b8ee933348ddd829dc9c4c9..4c590769c585c2169a018771763aa780ec9656fb 100644 (file)
 
 from stdapi import *
 
-from glenum import GLenum
+from glapi import *
 
 
 X = None # To be determined
-B = Bool
-I = Int
+B = GLboolean
+I = GLint
 E = GLenum
-F = Float
-D = Double
+F = GLfloat
+D = GLdouble
 P = OpaquePointer(Void)
 S = CString
 
@@ -150,9 +150,9 @@ parameters = [
     ("glGet",  I,      1,      "GL_CULL_FACE"),        # 0x0B44
     ("glGet",  E,      1,      "GL_CULL_FACE_MODE"),   # 0x0B45
     ("glGet",  E,      1,      "GL_FRONT_FACE"),       # 0x0B46
-    ("glGet",  I,      1,      "GL_LIGHTING"), # 0x0B50
-    ("glGet",  I,      1,      "GL_LIGHT_MODEL_LOCAL_VIEWER"), # 0x0B51
-    ("glGet",  I,      1,      "GL_LIGHT_MODEL_TWO_SIDE"),     # 0x0B52
+    ("glGet",  B,      1,      "GL_LIGHTING"), # 0x0B50
+    ("glGet",  B,      1,      "GL_LIGHT_MODEL_LOCAL_VIEWER"), # 0x0B51
+    ("glGet",  B,      1,      "GL_LIGHT_MODEL_TWO_SIDE"),     # 0x0B52
     ("glGet",  F,      4,      "GL_LIGHT_MODEL_AMBIENT"),      # 0x0B53
     ("glGet",  E,      1,      "GL_SHADE_MODEL"),      # 0x0B54
     ("glGet",  E,      1,      "GL_COLOR_MATERIAL_FACE"),      # 0x0B55
@@ -268,7 +268,7 @@ parameters = [
     ("glGet",  F,      1,      "GL_GREEN_BIAS"),       # 0x0D19
     ("glGet",  F,      1,      "GL_BLUE_SCALE"),       # 0x0D1A
     ("glGet",  F,      1,      "GL_BLUE_BIAS"),        # 0x0D1B
-    ("glGet",  F,      1,      "GL_ALPHA_SCALE"),      # 0x0D1C
+    ("glGet,glGetTexEnv",      F,      1,      "GL_ALPHA_SCALE"),      # 0x0D1C
     ("glGet",  F,      1,      "GL_ALPHA_BIAS"),       # 0x0D1D
     ("glGet",  F,      1,      "GL_DEPTH_SCALE"),      # 0x0D1E
     ("glGet",  F,      1,      "GL_DEPTH_BIAS"),       # 0x0D1F
@@ -335,16 +335,16 @@ parameters = [
     ("glGet",  X,      1,      "GL_DONT_CARE"),        # 0x1100
     ("glGet",  X,      1,      "GL_FASTEST"),  # 0x1101
     ("glGet",  X,      1,      "GL_NICEST"),   # 0x1102
-    ("glGet",  X,      1,      "GL_AMBIENT"),  # 0x1200
-    ("glGet",  X,      1,      "GL_DIFFUSE"),  # 0x1201
-    ("glGet",  X,      1,      "GL_SPECULAR"), # 0x1202
-    ("glGet",  X,      1,      "GL_POSITION"), # 0x1203
-    ("glGet",  X,      1,      "GL_SPOT_DIRECTION"),   # 0x1204
-    ("glGet",  X,      1,      "GL_SPOT_EXPONENT"),    # 0x1205
-    ("glGet",  X,      1,      "GL_SPOT_CUTOFF"),      # 0x1206
-    ("glGet",  X,      1,      "GL_CONSTANT_ATTENUATION"),     # 0x1207
-    ("glGet",  X,      1,      "GL_LINEAR_ATTENUATION"),       # 0x1208
-    ("glGet",  X,      1,      "GL_QUADRATIC_ATTENUATION"),    # 0x1209
+    ("glGetLight,glGetMaterial",       F,      4,      "GL_AMBIENT"),  # 0x1200
+    ("glGetLight,glGetMaterial",       F,      4,      "GL_DIFFUSE"),  # 0x1201
+    ("glGetLight,glGetMaterial",       F,      4,      "GL_SPECULAR"), # 0x1202
+    ("glGetLight",     F,      4,      "GL_POSITION"), # 0x1203
+    ("glGetLight",     F,      3,      "GL_SPOT_DIRECTION"),   # 0x1204
+    ("glGetLight",     F,      1,      "GL_SPOT_EXPONENT"),    # 0x1205
+    ("glGetLight",     F,      1,      "GL_SPOT_CUTOFF"),      # 0x1206
+    ("glGetLight",     F,      1,      "GL_CONSTANT_ATTENUATION"),     # 0x1207
+    ("glGetLight",     F,      1,      "GL_LINEAR_ATTENUATION"),       # 0x1208
+    ("glGetLight",     F,      1,      "GL_QUADRATIC_ATTENUATION"),    # 0x1209
     ("glGet",  X,      1,      "GL_COMPILE"),  # 0x1300
     ("glGet",  X,      1,      "GL_COMPILE_AND_EXECUTE"),      # 0x1301
     ("glGet",  X,      1,      "GL_BYTE"),     # 0x1400
@@ -378,10 +378,10 @@ parameters = [
     ("glGet",  X,      1,      "GL_OR_INVERTED"),      # 0x150D
     ("glGet",  X,      1,      "GL_NAND"),     # 0x150E
     ("glGet",  X,      1,      "GL_SET"),      # 0x150F
-    ("glGet",  X,      1,      "GL_EMISSION"), # 0x1600
-    ("glGet",  X,      1,      "GL_SHININESS"),        # 0x1601
-    ("glGet",  X,      1,      "GL_AMBIENT_AND_DIFFUSE"),      # 0x1602
-    ("glGet",  X,      1,      "GL_COLOR_INDEXES"),    # 0x1603
+    ("glGetMaterial",  F,      4,      "GL_EMISSION"), # 0x1600
+    ("glGetMaterial",  F,      1,      "GL_SHININESS"),        # 0x1601
+    (None,     F,      4,      "GL_AMBIENT_AND_DIFFUSE"),      # 0x1602
+    ("glGetMaterial",  F,      3,      "GL_COLOR_INDEXES"),    # 0x1603
     ("glGet",  X,      1,      "GL_MODELVIEW"),        # 0x1700
     ("glGet",  X,      1,      "GL_PROJECTION"),       # 0x1701
     ("glGet",  X,      1,      "GL_TEXTURE"),  # 0x1702
@@ -447,15 +447,15 @@ parameters = [
     ("glGet",  X,      1,      "GL_Q"),        # 0x2003
     ("glGet",  X,      1,      "GL_MODULATE"), # 0x2100
     ("glGet",  X,      1,      "GL_DECAL"),    # 0x2101
-    ("glGet",  X,      1,      "GL_TEXTURE_ENV_MODE"), # 0x2200
-    ("glGet",  X,      1,      "GL_TEXTURE_ENV_COLOR"),        # 0x2201
-    ("glGet",  X,      1,      "GL_TEXTURE_ENV"),      # 0x2300
+    ("glGetTexEnv",    E,      1,      "GL_TEXTURE_ENV_MODE"), # 0x2200
+    ("glGetTexEnv",    F,      4,      "GL_TEXTURE_ENV_COLOR"),        # 0x2201
+    (None,     X,      1,      "GL_TEXTURE_ENV"),      # 0x2300
     ("glGet",  X,      1,      "GL_EYE_LINEAR"),       # 0x2400
     ("glGet",  X,      1,      "GL_OBJECT_LINEAR"),    # 0x2401
     ("glGet",  X,      1,      "GL_SPHERE_MAP"),       # 0x2402
-    ("glGet",  X,      1,      "GL_TEXTURE_GEN_MODE"), # 0x2500
-    ("glGet",  X,      1,      "GL_OBJECT_PLANE"),     # 0x2501
-    ("glGet",  X,      1,      "GL_EYE_PLANE"),        # 0x2502
+    ("glGetTexGen",    E,      1,      "GL_TEXTURE_GEN_MODE"), # 0x2500
+    ("glGetTexGen",    F,      4,      "GL_OBJECT_PLANE"),     # 0x2501
+    ("glGetTexGen",    F,      4,      "GL_EYE_PLANE"),        # 0x2502
     ("glGet",  X,      1,      "GL_NEAREST"),  # 0x2600
     ("glGet",  X,      1,      "GL_LINEAR"),   # 0x2601
     ("glGet",  X,      1,      "GL_NEAREST_MIPMAP_NEAREST"),   # 0x2700
@@ -494,14 +494,14 @@ parameters = [
     ("glGet",  B,      1,      "GL_CLIP_PLANE5"),      # 0x3005
     ("glGet",  X,      1,      "GL_CLIP_DISTANCE6"),   # 0x3006
     ("glGet",  X,      1,      "GL_CLIP_DISTANCE7"),   # 0x3007
-    ("glGet",  I,      1,      "GL_LIGHT0"),   # 0x4000
-    ("glGet",  I,      1,      "GL_LIGHT1"),   # 0x4001
-    ("glGet",  I,      1,      "GL_LIGHT2"),   # 0x4002
-    ("glGet",  I,      1,      "GL_LIGHT3"),   # 0x4003
-    ("glGet",  I,      1,      "GL_LIGHT4"),   # 0x4004
-    ("glGet",  I,      1,      "GL_LIGHT5"),   # 0x4005
-    ("glGet",  I,      1,      "GL_LIGHT6"),   # 0x4006
-    ("glGet",  I,      1,      "GL_LIGHT7"),   # 0x4007
+    (None,     B,      1,      "GL_LIGHT0"),   # 0x4000
+    (None,     B,      1,      "GL_LIGHT1"),   # 0x4001
+    (None,     B,      1,      "GL_LIGHT2"),   # 0x4002
+    (None,     B,      1,      "GL_LIGHT3"),   # 0x4003
+    (None,     B,      1,      "GL_LIGHT4"),   # 0x4004
+    (None,     B,      1,      "GL_LIGHT5"),   # 0x4005
+    (None,     B,      1,      "GL_LIGHT6"),   # 0x4006
+    (None,     B,      1,      "GL_LIGHT7"),   # 0x4007
     ("glGet",  X,      1,      "GL_ABGR_EXT"), # 0x8000
     ("glGet",  X,      1,      "GL_CONSTANT_COLOR"),   # 0x8001
     ("glGet",  X,      1,      "GL_ONE_MINUS_CONSTANT_COLOR"), # 0x8002
@@ -604,7 +604,7 @@ parameters = [
     ("glGet",  X,      1,      "GL_PROXY_TEXTURE_1D"), # 0x8063
     ("glGet",  X,      1,      "GL_PROXY_TEXTURE_2D"), # 0x8064
     ("glGet",  X,      1,      "GL_TEXTURE_TOO_LARGE_EXT"),    # 0x8065
-    ("glGetTexParameter",      I,      1,      "GL_TEXTURE_PRIORITY"), # 0x8066
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_PRIORITY"), # 0x8066
     ("glGetTexParameter",      B,      1,      "GL_TEXTURE_RESIDENT"), # 0x8067
     ("glGet",  I,      1,      "GL_TEXTURE_BINDING_1D"),       # 0x8068
     ("glGet",  I,      1,      "GL_TEXTURE_BINDING_2D"),       # 0x8069
@@ -693,7 +693,7 @@ parameters = [
     ("glGet",  I,      1,      "GL_TEXTURE_COLOR_TABLE_SGI"),  # 0x80BC
     ("glGet",  X,      1,      "GL_PROXY_TEXTURE_COLOR_TABLE_SGI"),    # 0x80BD
     ("glGet",  X,      1,      "GL_TEXTURE_ENV_BIAS_SGIX"),    # 0x80BE
-    ("glGet",  X,      1,      "GL_TEXTURE_COMPARE_FAIL_VALUE_ARB"),   # 0x80BF
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_COMPARE_FAIL_VALUE_ARB"),   # 0x80BF
     ("glGet",  X,      1,      "GL_BLEND_DST_RGB"),    # 0x80C8
     ("glGet",  X,      1,      "GL_BLEND_SRC_RGB"),    # 0x80C9
     ("glGet",  X,      1,      "GL_BLEND_DST_ALPHA"),  # 0x80CA
@@ -822,16 +822,16 @@ parameters = [
     ("glGet",  X,      1,      "GL_TEXTURE_POST_SPECULAR_HP"), # 0x8168
     ("glGet",  X,      1,      "GL_TEXTURE_PRE_SPECULAR_HP"),  # 0x8169
     ("glGet",  X,      1,      "GL_LINEAR_CLIPMAP_LINEAR_SGIX"),       # 0x8170
-    ("glGet",  X,      1,      "GL_TEXTURE_CLIPMAP_CENTER_SGIX"),      # 0x8171
-    ("glGet",  X,      1,      "GL_TEXTURE_CLIPMAP_FRAME_SGIX"),       # 0x8172
-    ("glGet",  X,      1,      "GL_TEXTURE_CLIPMAP_OFFSET_SGIX"),      # 0x8173
-    ("glGet",  X,      1,      "GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX"),       # 0x8174
+    ("glGetTexParameter",      I,      2,      "GL_TEXTURE_CLIPMAP_CENTER_SGIX"),      # 0x8171
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_CLIPMAP_FRAME_SGIX"),       # 0x8172
+    ("glGetTexParameter",      I,      2,      "GL_TEXTURE_CLIPMAP_OFFSET_SGIX"),      # 0x8173
+    ("glGetTexParameter",      I,      3,      "GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX"),       # 0x8174
     ("glGet",  X,      1,      "GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX"),  # 0x8175
     ("glGet",  X,      1,      "GL_TEXTURE_CLIPMAP_DEPTH_SGIX"),       # 0x8176
     ("glGet",  I,      1,      "GL_MAX_CLIPMAP_DEPTH_SGIX"),   # 0x8177
     ("glGet",  I,      1,      "GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX"),   # 0x8178
-    ("glGet",  X,      1,      "GL_POST_TEXTURE_FILTER_BIAS_SGIX"),    # 0x8179
-    ("glGet",  X,      1,      "GL_POST_TEXTURE_FILTER_SCALE_SGIX"),   # 0x817A
+    ("glGetTexParameter",      F,      1,      "GL_POST_TEXTURE_FILTER_BIAS_SGIX"),    # 0x8179
+    ("glGetTexParameter",      F,      1,      "GL_POST_TEXTURE_FILTER_SCALE_SGIX"),   # 0x817A
     ("glGet",  F,      2,      "GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX"),      # 0x817B
     ("glGet",  F,      2,      "GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX"),     # 0x817C
     ("glGet",  I,      1,      "GL_REFERENCE_PLANE_SGIX"),     # 0x817D
@@ -851,9 +851,9 @@ parameters = [
     ("glGet",  I,      1,      "GL_FRAMEZOOM_SGIX"),   # 0x818B
     ("glGet",  I,      1,      "GL_FRAMEZOOM_FACTOR_SGIX"),    # 0x818C
     ("glGet",  I,      1,      "GL_MAX_FRAMEZOOM_FACTOR_SGIX"),        # 0x818D
-    ("glGet",  X,      1,      "GL_TEXTURE_LOD_BIAS_S_SGIX"),  # 0x818E
-    ("glGet",  X,      1,      "GL_TEXTURE_LOD_BIAS_T_SGIX"),  # 0x818F
-    ("glGet",  X,      1,      "GL_TEXTURE_LOD_BIAS_R_SGIX"),  # 0x8190
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_LOD_BIAS_S_SGIX"),  # 0x818E
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_LOD_BIAS_T_SGIX"),  # 0x818F
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_LOD_BIAS_R_SGIX"),  # 0x8190
     ("glGetTexParameter",      B,      1,      "GL_GENERATE_MIPMAP"),  # 0x8191
     ("glGet",  E,      1,      "GL_GENERATE_MIPMAP_HINT"),     # 0x8192
     ("glGet",  X,      1,      "GL_GEOMETRY_DEFORMATION_SGIX"),        # 0x8194
@@ -862,10 +862,10 @@ parameters = [
     ("glGet",  X,      1,      "GL_MAX_DEFORMATION_ORDER_SGIX"),       # 0x8197
     ("glGet",  I,      1,      "GL_FOG_OFFSET_SGIX"),  # 0x8198
     ("glGet",  F,      4,      "GL_FOG_OFFSET_VALUE_SGIX"),    # 0x8199
-    ("glGet",  X,      1,      "GL_TEXTURE_COMPARE_SGIX"),     # 0x819A
-    ("glGet",  X,      1,      "GL_TEXTURE_COMPARE_OPERATOR_SGIX"),    # 0x819B
-    ("glGet",  X,      1,      "GL_TEXTURE_LEQUAL_R_SGIX"),    # 0x819C
-    ("glGet",  X,      1,      "GL_TEXTURE_GEQUAL_R_SGIX"),    # 0x819D
+    ("glGetTexParameter",      B,      1,      "GL_TEXTURE_COMPARE_SGIX"),     # 0x819A
+    ("glGetTexParameter",      E,      1,      "GL_TEXTURE_COMPARE_OPERATOR_SGIX"),    # 0x819B
+    (None,     X,      1,      "GL_TEXTURE_LEQUAL_R_SGIX"),    # 0x819C
+    (None,     X,      1,      "GL_TEXTURE_GEQUAL_R_SGIX"),    # 0x819D
     ("glGet",  X,      1,      "GL_DEPTH_COMPONENT16"),        # 0x81A5
     ("glGet",  X,      1,      "GL_DEPTH_COMPONENT24"),        # 0x81A6
     ("glGet",  X,      1,      "GL_DEPTH_COMPONENT32"),        # 0x81A7
@@ -1037,9 +1037,9 @@ parameters = [
     ("glGet",  X,      1,      "GL_UNSIGNED_SHORT_1_5_5_5_REV"),       # 0x8366
     ("glGet",  X,      1,      "GL_UNSIGNED_INT_8_8_8_8_REV"), # 0x8367
     ("glGet",  X,      1,      "GL_UNSIGNED_INT_2_10_10_10_REV"),      # 0x8368
-    ("glGet",  X,      1,      "GL_TEXTURE_MAX_CLAMP_S_SGIX"), # 0x8369
-    ("glGet",  X,      1,      "GL_TEXTURE_MAX_CLAMP_T_SGIX"), # 0x836A
-    ("glGet",  X,      1,      "GL_TEXTURE_MAX_CLAMP_R_SGIX"), # 0x836B
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_MAX_CLAMP_S_SGIX"), # 0x8369
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_MAX_CLAMP_T_SGIX"), # 0x836A
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_MAX_CLAMP_R_SGIX"), # 0x836B
     ("glGet",  X,      1,      "GL_MIRRORED_REPEAT"),  # 0x8370
     ("glGet",  X,      1,      "GL_RGB_S3TC"), # 0x83A0
     ("glGet",  X,      1,      "GL_RGB4_S3TC"),        # 0x83A1
@@ -1177,11 +1177,11 @@ parameters = [
     ("glGet",  X,      1,      "GL_MAX_RECTANGLE_TEXTURE_SIZE"),       # 0x84F8
     ("glGet",  X,      1,      "GL_DEPTH_STENCIL"),    # 0x84F9
     ("glGet",  X,      1,      "GL_UNSIGNED_INT_24_8"),        # 0x84FA
-    ("glGet",  X,      1,      "GL_MAX_TEXTURE_LOD_BIAS"),     # 0x84FD
-    ("glGet",  X,      1,      "GL_TEXTURE_MAX_ANISOTROPY_EXT"),       # 0x84FE
-    ("glGet",  X,      1,      "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT"),   # 0x84FF
-    ("glGet",  X,      1,      "GL_TEXTURE_FILTER_CONTROL"),   # 0x8500
-    ("glGet",  X,      1,      "GL_TEXTURE_LOD_BIAS"), # 0x8501
+    ("glGet",  F,      1,      "GL_MAX_TEXTURE_LOD_BIAS"),     # 0x84FD
+    ("glGetTexParameter",      F,      1,      "GL_TEXTURE_MAX_ANISOTROPY_EXT"),       # 0x84FE
+    ("glGet",  F,      1,      "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT"),   # 0x84FF
+    ("glGetTexEnv",    E,      1,      "GL_TEXTURE_FILTER_CONTROL"),   # 0x8500
+    ("glGetTexParameter,glGetTexEnv",  F,      1,      "GL_TEXTURE_LOD_BIAS"), # 0x8501
     ("glGet",  X,      1,      "GL_MODELVIEW1_STACK_DEPTH_EXT"),       # 0x8502
     ("glGet",  X,      1,      "GL_COMBINE4_NV"),      # 0x8503
     ("glGet",  X,      1,      "GL_MAX_SHININESS_NV"), # 0x8504
@@ -1270,9 +1270,9 @@ parameters = [
     ("glGet",  X,      1,      "GL_COMBINER7_NV"),     # 0x8557
     ("glGet",  X,      1,      "GL_PRIMITIVE_RESTART_NV"),     # 0x8558
     ("glGet",  X,      1,      "GL_PRIMITIVE_RESTART_INDEX_NV"),       # 0x8559
-    ("glGet",  X,      1,      "GL_FOG_DISTANCE_MODE_NV"),     # 0x855A
-    ("glGet",  X,      1,      "GL_EYE_RADIAL_NV"),    # 0x855B
-    ("glGet",  X,      1,      "GL_EYE_PLANE_ABSOLUTE_NV"),    # 0x855C
+    ("glGet",  E,      1,      "GL_FOG_DISTANCE_MODE_NV"),     # 0x855A
+    (None,     X,      1,      "GL_EYE_RADIAL_NV"),    # 0x855B
+    (None,     X,      1,      "GL_EYE_PLANE_ABSOLUTE_NV"),    # 0x855C
     ("glGet",  X,      1,      "GL_EMBOSS_LIGHT_NV"),  # 0x855D
     ("glGet",  X,      1,      "GL_EMBOSS_CONSTANT_NV"),       # 0x855E
     ("glGet",  X,      1,      "GL_EMBOSS_MAP_NV"),    # 0x855F
@@ -1286,29 +1286,29 @@ parameters = [
     ("glGet",  X,      1,      "GL_ALPHA_MAX_CLAMP_INGR"),     # 0x8567
     ("glGet",  X,      1,      "GL_INTERLACE_READ_INGR"),      # 0x8568
     ("glGet",  X,      1,      "GL_COMBINE"),  # 0x8570
-    ("glGet",  X,      1,      "GL_COMBINE_RGB"),      # 0x8571
-    ("glGet",  X,      1,      "GL_COMBINE_ALPHA"),    # 0x8572
-    ("glGet",  X,      1,      "GL_RGB_SCALE"),        # 0x8573
+    ("glGetTexEnv",    E,      1,      "GL_COMBINE_RGB"),      # 0x8571
+    ("glGetTexEnv",    E,      1,      "GL_COMBINE_ALPHA"),    # 0x8572
+    ("glGetTexEnv",    F,      1,      "GL_RGB_SCALE"),        # 0x8573
     ("glGet",  X,      1,      "GL_ADD_SIGNED"),       # 0x8574
     ("glGet",  X,      1,      "GL_INTERPOLATE"),      # 0x8575
     ("glGet",  X,      1,      "GL_CONSTANT"), # 0x8576
     ("glGet",  X,      1,      "GL_PRIMARY_COLOR"),    # 0x8577
     ("glGet",  X,      1,      "GL_PREVIOUS"), # 0x8578
-    ("glGet",  X,      1,      "GL_SRC0_RGB"), # 0x8580
-    ("glGet",  X,      1,      "GL_SRC1_RGB"), # 0x8581
-    ("glGet",  X,      1,      "GL_SRC2_RGB"), # 0x8582
-    ("glGet",  X,      1,      "GL_SOURCE3_RGB_NV"),   # 0x8583
-    ("glGet",  X,      1,      "GL_SRC0_ALPHA"),       # 0x8588
-    ("glGet",  X,      1,      "GL_SRC1_ALPHA"),       # 0x8589
-    ("glGet",  X,      1,      "GL_SRC2_ALPHA"),       # 0x858A
-    ("glGet",  X,      1,      "GL_SOURCE3_ALPHA_NV"), # 0x858B
-    ("glGet",  X,      1,      "GL_OPERAND0_RGB"),     # 0x8590
-    ("glGet",  X,      1,      "GL_OPERAND1_RGB"),     # 0x8591
-    ("glGet",  X,      1,      "GL_OPERAND2_RGB"),     # 0x8592
-    ("glGet",  X,      1,      "GL_OPERAND0_ALPHA"),   # 0x8598
-    ("glGet",  X,      1,      "GL_OPERAND1_ALPHA"),   # 0x8599
-    ("glGet",  X,      1,      "GL_OPERAND2_ALPHA"),   # 0x859A
-    ("glGet",  X,      1,      "GL_OPERAND3_ALPHA_NV"),        # 0x859B
+    ("glGetTexEnv",    E,      1,      "GL_SRC0_RGB"), # 0x8580
+    ("glGetTexEnv",    E,      1,      "GL_SRC1_RGB"), # 0x8581
+    ("glGetTexEnv",    E,      1,      "GL_SRC2_RGB"), # 0x8582
+    ("glGetTexEnv",    E,      1,      "GL_SOURCE3_RGB_NV"),   # 0x8583
+    ("glGetTexEnv",    E,      1,      "GL_SRC0_ALPHA"),       # 0x8588
+    ("glGetTexEnv",    E,      1,      "GL_SRC1_ALPHA"),       # 0x8589
+    ("glGetTexEnv",    E,      1,      "GL_SRC2_ALPHA"),       # 0x858A
+    ("glGetTexEnv",    E,      1,      "GL_SOURCE3_ALPHA_NV"), # 0x858B
+    ("glGetTexEnv",    E,      1,      "GL_OPERAND0_RGB"),     # 0x8590
+    ("glGetTexEnv",    E,      1,      "GL_OPERAND1_RGB"),     # 0x8591
+    ("glGetTexEnv",    E,      1,      "GL_OPERAND2_RGB"),     # 0x8592
+    ("glGetTexEnv",    E,      1,      "GL_OPERAND0_ALPHA"),   # 0x8598
+    ("glGetTexEnv",    E,      1,      "GL_OPERAND1_ALPHA"),   # 0x8599
+    ("glGetTexEnv",    E,      1,      "GL_OPERAND2_ALPHA"),   # 0x859A
+    ("glGetTexEnv",    E,      1,      "GL_OPERAND3_ALPHA_NV"),        # 0x859B
     ("glGet",  X,      1,      "GL_PACK_SUBSAMPLE_RATE_SGIX"), # 0x85A0
     ("glGet",  X,      1,      "GL_UNPACK_SUBSAMPLE_RATE_SGIX"),       # 0x85A1
     ("glGet",  X,      1,      "GL_PIXEL_SUBSAMPLE_4444_SGIX"),        # 0x85A2
@@ -1322,15 +1322,15 @@ parameters = [
     ("glGet",  X,      1,      "GL_BUFFER_OBJECT_APPLE"),      # 0x85B3
     ("glGet",  X,      1,      "GL_STORAGE_CLIENT_APPLE"),     # 0x85B4
     ("glGet",  I,      1,      "GL_VERTEX_ARRAY_BINDING"),     # 0x85B5
-    ("glGet",  X,      1,      "GL_TEXTURE_RANGE_LENGTH_APPLE"),       # 0x85B7
-    ("glGet",  X,      1,      "GL_TEXTURE_RANGE_POINTER_APPLE"),      # 0x85B8
+    ("glGetTexParameter",      X,      1,      "GL_TEXTURE_RANGE_LENGTH_APPLE"),       # 0x85B7
+    (None,     P,      1,      "GL_TEXTURE_RANGE_POINTER_APPLE"),      # 0x85B8
     ("glGet",  X,      1,      "GL_YCBCR_422_APPLE"),  # 0x85B9
     ("glGet",  X,      1,      "GL_UNSIGNED_SHORT_8_8_MESA"),  # 0x85BA
     ("glGet",  X,      1,      "GL_UNSIGNED_SHORT_8_8_REV_MESA"),      # 0x85BB
-    ("glGet",  X,      1,      "GL_TEXTURE_STORAGE_HINT_APPLE"),       # 0x85BC
-    ("glGet",  X,      1,      "GL_STORAGE_PRIVATE_APPLE"),    # 0x85BD
-    ("glGet",  X,      1,      "GL_STORAGE_CACHED_APPLE"),     # 0x85BE
-    ("glGet",  X,      1,      "GL_STORAGE_SHARED_APPLE"),     # 0x85BF
+    ("glGetTexParameter",      E,      1,      "GL_TEXTURE_STORAGE_HINT_APPLE"),       # 0x85BC
+    (None,     X,      1,      "GL_STORAGE_PRIVATE_APPLE"),    # 0x85BD
+    (None,     X,      1,      "GL_STORAGE_CACHED_APPLE"),     # 0x85BE
+    (None,     X,      1,      "GL_STORAGE_SHARED_APPLE"),     # 0x85BF
     ("glGet",  X,      1,      "GL_REPLACEMENT_CODE_ARRAY_SUN"),       # 0x85C0
     ("glGet",  E,      1,      "GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN"),  # 0x85C1
     ("glGet",  X,      1,      "GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN"),        # 0x85C2
@@ -1346,7 +1346,7 @@ parameters = [
     ("glGet",  X,      1,      "GL_SLICE_ACCUM_SUN"),  # 0x85CC
     ("glGet",  X,      1,      "GL_QUAD_MESH_SUN"),    # 0x8614
     ("glGet",  X,      1,      "GL_TRIANGLE_MESH_SUN"),        # 0x8615
-    ("glGet",  X,      1,      "GL_VERTEX_PROGRAM_ARB"),       # 0x8620
+    ("glGet",  B,      1,      "GL_VERTEX_PROGRAM_ARB"),       # 0x8620
     ("glGet",  X,      1,      "GL_VERTEX_STATE_PROGRAM_NV"),  # 0x8621
     ("glGetVertexAttrib",      B,      1,      "GL_VERTEX_ATTRIB_ARRAY_ENABLED"),      # 0x8622
     ("glGetVertexAttrib",      I,      1,      "GL_VERTEX_ATTRIB_ARRAY_SIZE"), # 0x8623
@@ -1360,8 +1360,8 @@ parameters = [
     ("glGet",  X,      1,      "GL_INVERSE_NV"),       # 0x862B
     ("glGet",  X,      1,      "GL_TRANSPOSE_NV"),     # 0x862C
     ("glGet",  X,      1,      "GL_INVERSE_TRANSPOSE_NV"),     # 0x862D
-    ("glGet",  X,      1,      "GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB"),       # 0x862E
-    ("glGet",  X,      1,      "GL_MAX_PROGRAM_MATRICES_ARB"), # 0x862F
+    ("glGet",  I,      1,      "GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB"),       # 0x862E
+    ("glGet",  I,      1,      "GL_MAX_PROGRAM_MATRICES_ARB"), # 0x862F
     ("glGet",  X,      1,      "GL_MATRIX0_NV"),       # 0x8630
     ("glGet",  X,      1,      "GL_MATRIX1_NV"),       # 0x8631
     ("glGet",  X,      1,      "GL_MATRIX2_NV"),       # 0x8632
@@ -1372,8 +1372,8 @@ parameters = [
     ("glGet",  X,      1,      "GL_MATRIX7_NV"),       # 0x8637
     ("glGet",  X,      1,      "GL_CURRENT_MATRIX_STACK_DEPTH_ARB"),   # 0x8640
     ("glGet",  X,      1,      "GL_CURRENT_MATRIX_ARB"),       # 0x8641
-    ("glGet",  X,      1,      "GL_VERTEX_PROGRAM_POINT_SIZE"),        # 0x8642
-    ("glGet",  X,      1,      "GL_VERTEX_PROGRAM_TWO_SIDE"),  # 0x8643
+    ("glGet",  B,      1,      "GL_VERTEX_PROGRAM_POINT_SIZE"),        # 0x8642
+    ("glGet",  B,      1,      "GL_VERTEX_PROGRAM_TWO_SIDE"),  # 0x8643
     ("glGet",  X,      1,      "GL_PROGRAM_PARAMETER_NV"),     # 0x8644
     ("glGetVertexAttrib",      P,      1,      "GL_VERTEX_ATTRIB_ARRAY_POINTER"),      # 0x8645
     ("glGet",  X,      1,      "GL_PROGRAM_TARGET_NV"),        # 0x8646
@@ -1488,12 +1488,12 @@ parameters = [
     ("glGet",  X,      1,      "GL_SHADER_CONSISTENT_NV"),     # 0x86DD
     ("glGet",  X,      1,      "GL_TEXTURE_SHADER_NV"),        # 0x86DE
     ("glGet",  X,      1,      "GL_SHADER_OPERATION_NV"),      # 0x86DF
-    ("glGet",  X,      1,      "GL_CULL_MODES_NV"),    # 0x86E0
-    ("glGet",  X,      1,      "GL_OFFSET_TEXTURE_MATRIX_NV"), # 0x86E1
+    ("glGetTexEnv",    F,      4,      "GL_CULL_MODES_NV"),    # 0x86E0
+    ("glGetTexEnv",    F,      4,      "GL_OFFSET_TEXTURE_MATRIX_NV"), # 0x86E1
     ("glGet",  X,      1,      "GL_OFFSET_TEXTURE_SCALE_NV"),  # 0x86E2
     ("glGet",  X,      1,      "GL_OFFSET_TEXTURE_BIAS_NV"),   # 0x86E3
     ("glGet",  X,      1,      "GL_PREVIOUS_TEXTURE_INPUT_NV"),        # 0x86E4
-    ("glGet",  X,      1,      "GL_CONST_EYE_NV"),     # 0x86E5
+    ("glGetTexEnv",    F,      3,      "GL_CONST_EYE_NV"),     # 0x86E5
     ("glGet",  X,      1,      "GL_PASS_THROUGH_NV"),  # 0x86E6
     ("glGet",  X,      1,      "GL_CULL_FRAGMENT_NV"), # 0x86E7
     ("glGet",  X,      1,      "GL_OFFSET_TEXTURE_2D_NV"),     # 0x86E8
@@ -1754,7 +1754,7 @@ parameters = [
     ("glGet",  E,      1,      "GL_STENCIL_BACK_FAIL"),        # 0x8801
     ("glGet",  E,      1,      "GL_STENCIL_BACK_PASS_DEPTH_FAIL"),     # 0x8802
     ("glGet",  E,      1,      "GL_STENCIL_BACK_PASS_DEPTH_PASS"),     # 0x8803
-    ("glGet",  X,      1,      "GL_FRAGMENT_PROGRAM_ARB"),     # 0x8804
+    ("glGet",  B,      1,      "GL_FRAGMENT_PROGRAM_ARB"),     # 0x8804
     ("glGet",  X,      1,      "GL_PROGRAM_ALU_INSTRUCTIONS_ARB"),     # 0x8805
     ("glGet",  X,      1,      "GL_PROGRAM_TEX_INSTRUCTIONS_ARB"),     # 0x8806
     ("glGet",  X,      1,      "GL_PROGRAM_TEX_INDIRECTIONS_ARB"),     # 0x8807
@@ -1833,7 +1833,7 @@ parameters = [
     ("glGet",  X,      1,      "GL_SIGNED_HILO8_NV"),  # 0x885F
     ("glGet",  X,      1,      "GL_FORCE_BLUE_TO_ONE_NV"),     # 0x8860
     ("glGet",  X,      1,      "GL_POINT_SPRITE"),     # 0x8861
-    ("glGet",  X,      1,      "GL_COORD_REPLACE"),    # 0x8862
+    ("glGetTexEnv",    B,      1,      "GL_COORD_REPLACE"),    # 0x8862
     ("glGet",  X,      1,      "GL_POINT_SPRITE_R_MODE_NV"),   # 0x8863
     ("glGet",  X,      1,      "GL_QUERY_COUNTER_BITS"),       # 0x8864
     ("glGet",  X,      1,      "GL_CURRENT_QUERY"),    # 0x8865
@@ -1850,7 +1850,7 @@ parameters = [
     ("glGet",  I,      1,      "GL_MAX_TEXTURE_COORDS"),       # 0x8871
     ("glGet",  I,      1,      "GL_MAX_TEXTURE_IMAGE_UNITS"),  # 0x8872
     ("glGet",  I,      1,      "GL_FRAGMENT_PROGRAM_BINDING_NV"),      # 0x8873
-    ("glGet",  X,      1,      "GL_PROGRAM_ERROR_STRING_ARB"), # 0x8874
+    ("glGet",  S,      1,      "GL_PROGRAM_ERROR_STRING_ARB"), # 0x8874
     ("glGet",  X,      1,      "GL_PROGRAM_FORMAT_ASCII_ARB"), # 0x8875
     ("glGet",  X,      1,      "GL_PROGRAM_FORMAT_ARB"),       # 0x8876
     ("glGet",  X,      1,      "GL_WRITE_PIXEL_DATA_RANGE_NV"),        # 0x8878
@@ -1875,7 +1875,7 @@ parameters = [
     ("glGet",  X,      1,      "GL_TEXTURE_FLOAT_COMPONENTS_NV"),      # 0x888C
     ("glGet",  X,      1,      "GL_FLOAT_CLEAR_COLOR_VALUE_NV"),       # 0x888D
     ("glGet",  X,      1,      "GL_FLOAT_RGBA_MODE_NV"),       # 0x888E
-    ("glGet",  X,      1,      "GL_TEXTURE_UNSIGNED_REMAP_MODE_NV"),   # 0x888F
+    ("glGetTexParameter",      E,      1,      "GL_TEXTURE_UNSIGNED_REMAP_MODE_NV"),   # 0x888F
     ("glGet",  X,      1,      "GL_DEPTH_BOUNDS_TEST_EXT"),    # 0x8890
     ("glGet",  X,      1,      "GL_DEPTH_BOUNDS_EXT"), # 0x8891
     ("glGet",  X,      1,      "GL_ARRAY_BUFFER"),     # 0x8892
@@ -2521,11 +2521,11 @@ parameters = [
     ("glGet",  X,      1,      "GL_PROGRAM_MATRIX_EXT"),       # 0x8E2D
     ("glGet",  X,      1,      "GL_TRANSPOSE_PROGRAM_MATRIX_EXT"),     # 0x8E2E
     ("glGet",  X,      1,      "GL_PROGRAM_MATRIX_STACK_DEPTH_EXT"),   # 0x8E2F
-    ("glGet",  X,      1,      "GL_TEXTURE_SWIZZLE_R"),        # 0x8E42
-    ("glGet",  X,      1,      "GL_TEXTURE_SWIZZLE_G"),        # 0x8E43
-    ("glGet",  X,      1,      "GL_TEXTURE_SWIZZLE_B"),        # 0x8E44
-    ("glGet",  X,      1,      "GL_TEXTURE_SWIZZLE_A"),        # 0x8E45
-    ("glGet",  X,      1,      "GL_TEXTURE_SWIZZLE_RGBA"),     # 0x8E46
+    ("glGetTexParameter",      E,      1,      "GL_TEXTURE_SWIZZLE_R"),        # 0x8E42
+    ("glGetTexParameter",      E,      1,      "GL_TEXTURE_SWIZZLE_G"),        # 0x8E43
+    ("glGetTexParameter",      E,      1,      "GL_TEXTURE_SWIZZLE_B"),        # 0x8E44
+    ("glGetTexParameter",      E,      1,      "GL_TEXTURE_SWIZZLE_A"),        # 0x8E45
+    ("glGetTexParameter",      E,      4,      "GL_TEXTURE_SWIZZLE_RGBA"),     # 0x8E46
     ("glGet",  X,      1,      "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS"),      # 0x8E47
     ("glGet",  X,      1,      "GL_ACTIVE_SUBROUTINE_MAX_LENGTH"),     # 0x8E48
     ("glGet",  X,      1,      "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH"),     # 0x8E49
@@ -2837,67 +2837,131 @@ texture_targets = [
 ]
 
 
-class GlGetter(Visitor):
-    '''Type visitor
-    Determine which glGet*v function that matches the specified type.'''
+class GetInflector:
+    '''Objects that describes how to inflect.'''
 
-    def __init__(self, prefix = 'glGet', long_suffix = True):
-        self.prefix = prefix
-        self.long_suffix = long_suffix
+    reduced_types = {
+        B: I,
+        E: I,
+        I: F,
+    }
 
-        if prefix == 'glGet':
-            self.suffixes = {
-                'GLboolean': 'Booleanv',
-                'GLint': 'Intv',
-                'GLfloat': 'Floatv',
-                'GLdouble': 'Doublev',
-                'GLstring': 'String',
-            }
-        else:
-            self.suffixes = {
-                'GLint': 'iv',
-                'GLfloat': 'fv',
-                'GLdouble': 'Doublev',
-                'GLstring': 'String',
-            }
-
-
-    def visit_const(self, const):
-        return self.visit(const.type)
-
-    def visit_alias(self, alias):
-        if alias.expr == 'GLboolean':
-            if self.long_suffix:
-                return self.prefix + 'Booleanv', alias.expr
-            else:
-                return self.prefix + 'iv', 'GLint'
-        elif alias.expr == 'GLdouble':
-            if self.long_suffix:
-                return self.prefix + 'Doublev', alias.expr
-            else:
-                return self.prefix + 'dv', alias.expr
-        elif alias.expr == 'GLfloat':
-            if self.long_suffix:
-                return self.prefix + 'Floatv', alias.expr
-            else:
-                return self.prefix + 'fv', alias.expr
-        elif alias.expr in ('GLint', 'GLuint', 'GLsizei'):
-            if self.long_suffix:
-                return self.prefix + 'Integerv', 'GLint'
-            else:
-                return self.prefix + 'iv', 'GLint'
+    def __init__(self, radical, suffixes):
+        self.radical = radical
+        self.suffixes = suffixes
+
+    def reduced_type(self, type):
+        if type in self.suffixes:
+            return type
+        if type in self.reduced_types:
+            return self.reduced_type(self.reduced_types[type])
+        raise NotImplementedError
+
+    def inflect(self, type):
+        return self.radical + self.suffix(type)
+
+    def suffix(self, type):
+        type = self.reduced_type(type)
+        assert type in self.suffixes
+        return self.suffixes[type]
+
+
+class StateGetter(Visitor):
+    '''Type visitor that is able to extract the state via one of the glGet*
+    functions.
+
+    It will declare any temporary variable
+    '''
+
+    def __init__(self, radical, suffixes):
+        self.inflector = GetInflector(radical, suffixes)
+
+    def __call__(self, *args):
+        pname = args[-1]
+
+        for function, type, count, name in parameters:
+            if type is X:
+                continue
+            if name == pname:
+                if count != 1:
+                    type = Array(type, str(count))
+
+                return type, self.visit(type, args)
+
+        raise NotImplementedError
+
+    def temp_name(self, args):
+        '''Return the name of a temporary variable to hold the state.'''
+        pname = args[-1]
+
+        return pname[3:].lower()
+
+    def visit_const(self, const, args):
+        return self.visit(const.type, args)
+
+    def visit_scalar(self, type, args):
+        temp_name = self.temp_name(args)
+        elem_type = self.inflector.reduced_type(type)
+        inflection = self.inflector.inflect(type)
+        if inflection.endswith('v'):
+            print '    %s %s = 0;' % (elem_type, temp_name)
+            print '    %s(%s, &%s);' % (inflection, ', '.join(args), temp_name)
         else:
-            print alias.expr
-            assert False
-    
-    def visit_enum(self, enum):
-        return self.visit(glapi.GLint)
+            print '    %s %s = %s(%s);' % (elem_type, temp_name, inflection, ', '.join(args))
+        return temp_name
 
-    def visit_bitmask(self, bitmask):
-        return self.visit(glapi.GLint)
+    def visit_string(self, string, args):
+        temp_name = self.temp_name(args)
+        inflection = self.inflector.inflect(string)
+        assert not inflection.endswith('v')
+        print '    %s %s = (%s)%s(%s);' % (string, temp_name, string, inflection, ', '.join(args))
+        return temp_name
 
-    def visit_opaque(self, pointer):
-        return self.prefix + 'Pointerv', 'GLvoid *'
+    def visit_alias(self, alias, args):
+        return self.visit_scalar(alias, args)
+
+    def visit_enum(self, enum, args):
+        return self.visit(GLint, args)
+
+    def visit_bitmask(self, bitmask, args):
+        return self.visit(GLint, args)
+
+    def visit_array(self, array, args):
+        temp_name = self.temp_name(args)
+        if array.length == '1':
+            return self.visit(array.type)
+        elem_type = self.inflector.reduced_type(array.type)
+        inflection = self.inflector.inflect(array.type)
+        assert inflection.endswith('v')
+        print '    %s %s[%s];' % (elem_type, temp_name, array.length)
+        print '    memset(%s, 0, %s * sizeof *%s);' % (temp_name, array.length, temp_name)
+        print '    %s(%s, %s);' % (inflection, ', '.join(args), temp_name)
+        return temp_name
+
+    def visit_opaque(self, pointer, args):
+        temp_name = self.temp_name(args)
+        inflection = self.inflector.inflect(pointer)
+        assert inflection.endswith('v')
+        print '    GLvoid *%s;' % temp_name
+        print '    %s(%s, &%s);' % (inflection, ', '.join(args), temp_name)
+        return temp_name
+
+
+glGet = StateGetter('glGet', {
+    B: 'Booleanv',
+    I: 'Integerv',
+    F: 'Floatv',
+    D: 'Doublev',
+    S: 'String',
+    P: 'Pointerv',
+})
+
+glGetMaterial = StateGetter('glGetMaterial', {I: 'iv', F: 'fv'})
+glGetLight = StateGetter('glGetLight', {I: 'iv', F: 'fv'})
+glGetVertexAttrib = StateGetter('glGetVertexAttrib', {I: 'iv', F: 'fv', D: 'dv', P: 'Pointerv'})
+glGetTexParameter = StateGetter('glGetTexParameter', {I: 'iv', F: 'fv'})
+glGetTexEnv = StateGetter('glGetTexEnv', {I: 'iv', F: 'fv'})
+glGetTexLevelParameter = StateGetter('glGetTexLevelParameter', {I: 'iv', F: 'fv'})
 
 
 class JsonWriter(Visitor):
@@ -2947,6 +3011,8 @@ class JsonWriter(Visitor):
 
 
 class StateDumper:
+    '''Class to generate code to dump all GL state in JSON format via
+    stdout.'''
 
     def __init__(self):
         self.level = 0
@@ -2954,94 +3020,158 @@ class StateDumper:
     def dump(self):
         print '#include <string.h>'
         print '#include <iostream>'
+        print '#include <algorithm>'
         print
+        print '#include "image.hpp"'
         print '#include "json.hpp"'
         print '#include "glimports.hpp"'
         print '#include "glproc.hpp"'
+        print '#include "glsize.hpp"'
         print '#include "glretrace.hpp"'
         print
 
-        print 'static void'
-        print 'writeEnum(JSONWriter &json, GLenum pname)'
+        print 'static const char *'
+        print '_enum_string(GLenum pname)'
         print '{'
         print '    switch(pname) {'
         for name in GLenum.values:
             print '    case %s:' % name
-            print '        json.writeString("%s");' % name
-            print '        break;'
+            print '        return "%s";' % name
         print '    default:'
-        print '        json.writeNumber(pname);'
+        print '        return NULL;'
         print '    }'
         print '}'
         print
 
-        # shaders
-        print 'static void'
-        print 'writeShader(JSONWriter &json, GLuint shader)'
+        print 'static const char *'
+        print 'enum_string(GLenum pname)'
         print '{'
-        print '    if (!shader) {'
-        print '        json.writeNull();'
-        print '        return;'
-        print '    }'
-        print
-        print '    json.beginObject();'
-        print '    GLint source_length = 0;'
-        print '    glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);'
-        print '    json.beginMember("source");'
-        print '    if (source_length) {'
-        print '        GLchar *source = new GLchar[source_length];'
-        print '        GLsizei length = 0;'
-        print '        source[0] = 0;'
-        print '        glGetShaderSource(shader, source_length, &length, source);'
-        print '        json.writeString(source);'
-        print '        delete [] source;'
+        print '    const char *s = _enum_string(pname);'
+        print '    if (s) {'
+        print '        return s;'
         print '    } else {'
-        print '        json.writeNull();'
+        print '        static char buf[16];'
+        print '        snprintf(buf, sizeof buf, "0x%04x", pname);'
+        print '        return buf;'
         print '    }'
-        print '    json.endMember(); // source'
-        print '    json.endObject();'
         print '}'
         print
 
-        # programs
         print 'static inline void'
-        print 'writeProgram(JSONWriter &json, GLuint program)'
+        print 'writeEnum(JSONWriter &json, GLenum pname)'
         print '{'
-        print '    if (!program) {'
-        print '        json.writeNull();'
-        print '        return;'
-        print '    }'
-        print
-        print '    json.beginObject();'
-        print '    json.beginMember("attached_shaders");'
-        print '    GLint attached_shaders = 0;'
-        print '    glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);'
-        print '    json.beginArray();'
-        print '    if (attached_shaders) {'
-        print '        GLuint *shaders = new GLuint[attached_shaders];'
-        print '        GLsizei count = 0;'
-        print '        glGetAttachedShaders(program, attached_shaders, &count, shaders);'
-        print '        for (GLsizei i = 0; i < count; ++ i) {'
-        print '           writeShader(json, shaders[i]);'
-        print '        }'
-        print '        delete [] shaders;'
+        print '    const char *s = _enum_string(pname);'
+        print '    if (s) {'
+        print '        json.writeString(s);'
+        print '    } else {'
+        print '        json.writeNumber(pname);'
         print '    }'
-        print '    json.endArray();'
-        print '    json.endMember();'
-        print '    json.endObject();'
         print '}'
         print
 
+        # shaders
+        print '''
+static void
+writeShader(JSONWriter &json, GLuint shader)
+{
+    if (!shader) {
+        return;
+    }
+
+    GLint shader_type = 0;
+    glGetShaderiv(shader, GL_SHADER_TYPE, &shader_type);
+    if (!shader_type) {
+        return;
+    }
+
+    GLint source_length = 0;
+    glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
+    if (!source_length) {
+        return;
+    }
+
+    GLchar *source = new GLchar[source_length];
+    GLsizei length = 0;
+    source[0] = 0;
+    glGetShaderSource(shader, source_length, &length, source);
+
+    json.beginMember(enum_string(shader_type));
+    json.writeString(source);
+    json.endMember();
+
+    delete [] source;
+}
+
+static inline void
+writeCurrentProgram(JSONWriter &json)
+{
+    GLint program = 0;
+    glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+    if (!program) {
+        return;
+    }
+
+    GLint attached_shaders = 0;
+    glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
+    if (!attached_shaders) {
+        return;
+    }
+
+    GLuint *shaders = new GLuint[attached_shaders];
+    GLsizei count = 0;
+    glGetAttachedShaders(program, attached_shaders, &count, shaders);
+    for (GLsizei i = 0; i < count; ++ i) {
+       writeShader(json, shaders[i]);
+    }
+    delete [] shaders;
+}
+
+static inline void
+writeArbProgram(JSONWriter &json, GLenum target)
+{
+    if (!glIsEnabled(target)) {
+        return;
+    }
+
+    GLint program_length = 0;
+    glGetProgramivARB(target, GL_PROGRAM_LENGTH_ARB, &program_length);
+    if (!program_length) {
+        return;
+    }
+
+    GLchar *source = new GLchar[program_length + 1];
+    source[0] = 0;
+    glGetProgramStringARB(target, GL_PROGRAM_STRING_ARB, source);
+    source[program_length] = 0;
+
+    json.beginMember(enum_string(target));
+    json.writeString(source);
+    json.endMember();
+
+    delete [] source;
+}
+'''
+
         # texture image
         print '''
 static inline void
 writeTextureImage(JSONWriter &json, GLenum target, GLint level)
 {
-    GLint width = 0, height = 0;
+    GLint width, height = 1, depth = 1;
+
+    width = 0;
     glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width);
-    glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
 
-    if (!width || !height) {
+    if (target != GL_TEXTURE_1D) {
+        height = 0;
+        glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height);
+        if (target == GL_TEXTURE_3D) {
+            depth = 0;
+            glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth);
+        }
+    }
+
+    if (width <= 0 || height <= 0 || depth <= 0) {
         json.writeNull();
     } else {
         json.beginObject();
@@ -3051,20 +3181,24 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level)
 
         json.writeNumberMember("__width__", width);
         json.writeNumberMember("__height__", height);
-        json.writeNumberMember("__depth__", 1);
+        json.writeNumberMember("__depth__", depth);
 
         // Hardcoded for now, but we could chose types more adequate to the
         // texture internal format
-        json.writeStringMember("__type__", "float");
+        json.writeStringMember("__type__", "uint8");
+        json.writeBoolMember("__normalized__", true);
         json.writeNumberMember("__channels__", 4);
         
-        float *pixels = new float[width*height*4];
+        GLubyte *pixels = new GLubyte[depth*width*height*4];
         
-        glGetTexImage(target, level, GL_RGBA, GL_FLOAT, pixels);
+        glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 
-        json.writeStringMember("__encoding__", "base64");
         json.beginMember("__data__");
-        json.writeBase64(pixels, width * height * 4 * sizeof *pixels);
+        char *pngBuffer;
+        int pngBufferSize;
+        Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize);
+        json.writeBase64(pngBuffer, pngBufferSize);
+        free(pngBuffer);
         json.endMember(); // __data__
 
         delete [] pixels;
@@ -3073,11 +3207,13 @@ writeTextureImage(JSONWriter &json, GLenum target, GLint level)
 }
 
 static inline void
-writeDrawBufferImage(JSONWriter &json)
+writeDrawBufferImage(JSONWriter &json, GLenum format)
 {
     GLint width  = glretrace::window_width;
     GLint height = glretrace::window_height;
 
+    GLint channels = __gl_format_channels(format);
+
     if (!width || !height) {
         json.writeNull();
     } else {
@@ -3092,22 +3228,34 @@ writeDrawBufferImage(JSONWriter &json)
 
         // Hardcoded for now, but we could chose types more adequate to the
         // texture internal format
-        json.writeStringMember("__type__", "float");
-        json.writeNumberMember("__channels__", 4);
-        
-        float *pixels = new float[width*height*4];
+        json.writeStringMember("__type__", "uint8");
+        json.writeBoolMember("__normalized__", true);
+        json.writeNumberMember("__channels__", channels);
+
+        GLubyte *pixels = new GLubyte[width*height*channels];
         
         GLint drawbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;
         GLint readbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;
         glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);
         glGetIntegerv(GL_READ_BUFFER, &readbuffer);
         glReadBuffer(drawbuffer);
-        glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+        glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+        glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+        glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels);
+
+        glPopClientAttrib();
         glReadBuffer(readbuffer);
 
-        json.writeStringMember("__encoding__", "base64");
         json.beginMember("__data__");
-        json.writeBase64(pixels, width * height * 4 * sizeof *pixels);
+        char *pngBuffer;
+        int pngBufferSize;
+        Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize);
+        //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels)
+        //          <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize;
+        json.writeBase64(pngBuffer, pngBufferSize);
+        free(pngBuffer);
         json.endMember(); // __data__
 
         delete [] pixels;
@@ -3115,6 +3263,136 @@ writeDrawBufferImage(JSONWriter &json)
     }
 }
 
+static inline GLuint
+downsampledFramebuffer(GLuint oldFbo, GLint drawbuffer,
+                       GLint colorRb, GLint depthRb, GLint stencilRb,
+                       GLuint *rbs, GLint *numRbs)
+{
+    GLuint fbo;
+    GLint format;
+    GLint w, h;
+
+    *numRbs = 0;
+
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+    glBindRenderbuffer(GL_RENDERBUFFER, colorRb);
+    glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                 GL_RENDERBUFFER_WIDTH, &w);
+    glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                 GL_RENDERBUFFER_HEIGHT, &h);
+    glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                 GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
+
+    glGenRenderbuffers(1, &rbs[*numRbs]);
+    glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
+    glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, drawbuffer,
+                              GL_RENDERBUFFER, rbs[*numRbs]);
+
+    glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+    glDrawBuffer(drawbuffer);
+    glReadBuffer(drawbuffer);
+    glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
+                      GL_COLOR_BUFFER_BIT, GL_NEAREST);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    ++*numRbs;
+
+    if (stencilRb == depthRb && stencilRb) {
+        //combined depth and stencil buffer
+        glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
+        glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                     GL_RENDERBUFFER_WIDTH, &w);
+        glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                     GL_RENDERBUFFER_HEIGHT, &h);
+        glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                     GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
+
+        glGenRenderbuffers(1, &rbs[*numRbs]);
+        glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
+        glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+                                  GL_RENDERBUFFER, rbs[*numRbs]);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+        glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
+                          GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        ++*numRbs;
+    } else {
+        if (depthRb) {
+            glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
+            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                         GL_RENDERBUFFER_WIDTH, &w);
+            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                         GL_RENDERBUFFER_HEIGHT, &h);
+            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                         GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
+
+            glGenRenderbuffers(1, &rbs[*numRbs]);
+            glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
+            glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+                                      GL_DEPTH_ATTACHMENT,
+                                      GL_RENDERBUFFER, rbs[*numRbs]);
+            glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
+            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+            glDrawBuffer(GL_DEPTH_ATTACHMENT);
+            glReadBuffer(GL_DEPTH_ATTACHMENT);
+            glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
+                              GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+            ++*numRbs;
+        }
+        if (stencilRb) {
+            glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);
+            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                         GL_RENDERBUFFER_WIDTH, &w);
+            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                         GL_RENDERBUFFER_HEIGHT, &h);
+            glGetRenderbufferParameteriv(GL_RENDERBUFFER,
+                                     GL_RENDERBUFFER_INTERNAL_FORMAT, &format);
+
+            glGenRenderbuffers(1, &rbs[*numRbs]);
+            glBindRenderbuffer(GL_RENDERBUFFER, rbs[*numRbs]);
+            glRenderbufferStorage(GL_RENDERBUFFER, format, w, h);
+            glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+                                      GL_STENCIL_ATTACHMENT,
+                                      GL_RENDERBUFFER, rbs[*numRbs]);
+            glBindFramebuffer(GL_READ_FRAMEBUFFER, oldFbo);
+            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
+            glDrawBuffer(GL_STENCIL_ATTACHMENT);
+            glReadBuffer(GL_STENCIL_ATTACHMENT);
+            glBlitFramebuffer(0, 0, w, h, 0, 0, w, h,
+                              GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+            ++*numRbs;
+        }
+    }
+
+    return fbo;
+}
+
+static void
+writeDrawBuffers(JSONWriter &json, GLboolean writeDepth, GLboolean writeStencil)
+{
+    json.beginMember("GL_RGBA");
+    writeDrawBufferImage(json, GL_RGBA);
+    json.endMember();
+
+    if (writeDepth) {
+        json.beginMember("GL_DEPTH_COMPONENT");
+        writeDrawBufferImage(json, GL_DEPTH_COMPONENT);
+        json.endMember();
+    }
+
+    if (writeStencil) {
+        json.beginMember("GL_STENCIL_INDEX");
+        writeDrawBufferImage(json, GL_STENCIL_INDEX);
+        json.endMember();
+    }
+}
+
 '''
 
         # textures
@@ -3129,17 +3407,6 @@ writeDrawBufferImage(JSONWriter &json)
         print '    }'
         print
         print '    json.beginObject();'
-        print
-        print '    GLfloat param;'
-        for function, type, count, name in parameters:
-            if function != 'glGetTexParameter' or count != 1:
-                continue
-            print '        glGetTexParameterfv(target, %s, &param);' % name
-            print '        json.beginMember("%s");'  % name
-            print '        json.writeNumber(param);'
-            print '        json.endMember();'
-            print
-        print
         print '    json.beginMember("levels");'
         print '    json.beginArray();'
         print '    GLint level = 0;'
@@ -3158,15 +3425,6 @@ writeDrawBufferImage(JSONWriter &json)
         print '        json.writeNumber(texture);'
         print '        json.endMember();'
         print
-        # TODO: Generalize this
-        for function, type, count, name in parameters:
-            if function != 'glGetTexLevelParameter' or count != 1:
-                continue
-            print '        glGetTexLevelParameterfv(target, level, %s, &param);' % name
-            print '        json.beginMember("%s");'  % name
-            print '        json.writeNumber(param);'
-            print '        json.endMember();'
-            print
         print '        json.beginMember("image");'
         print '        writeTextureImage(json, target, level);'
         print '        json.endMember();'
@@ -3192,105 +3450,237 @@ writeDrawBufferImage(JSONWriter &json)
         print
 
     def dump_parameters(self):
-        print '    const GLubyte * sparams[1];'
-        print '    GLboolean bparams[16];'
-        print '    GLint iparams[16];'
-        print '    GLfloat fparams[16];'
-        print '    GLdouble dparams[16];'
-        print '    GLvoid * pparams[16];'
-        print
-        print '    (void)dparams;'
-        print
         print '    json.beginMember("parameters");'
         print '    json.beginObject();'
-        for function, type, count, name in parameters:
-            if function != 'glGet':
-                continue
-            if type is X:
-                continue
-            elif type is B:
-                buf = 'bparams'
-                getter = 'glGetBooleanv'
-            elif type is I:
-                buf = 'iparams'
-                getter = 'glGetIntegerv'
-            elif type is E:
-                buf = 'iparams'
-                getter = 'glGetIntegerv'
-            elif type is F:
-                buf = 'fparams'
-                getter = 'glGetFloatv'
-            elif type is D:
-                buf = 'dparams'
-                getter = 'glGetDoublev'
-            elif type is P:
-                buf = 'pparams'
-                getter = 'glGetPointerv'
-            elif type is S:
-                buf = 'sparams'
-                getter = 'glGetString'
-            else:
-                raise NotImplementedError
-            print '    memset(%s, 0, %u * sizeof *%s);' % (buf, count, buf)
-            if getter.endswith('v'):
-                print '    %s(%s, %s);' % (getter, name, buf)
-            else:
-                assert count == 1
-                print '    %s[0] = %s(%s);' % (buf, getter, name)
-            print '    if (glGetError() != GL_NO_ERROR) {'
-            #print '        std::cerr << "warning: %s(%s) failed\\n";' % (getter, name)
-            print '    } else {'
-            print '        json.beginMember("%s");' % name
-            if count == 1:
-                JsonWriter().visit(type, '%s[0]' % buf)
-            else:
-                JsonWriter().visit(Array(type, str(count)), buf)
-            print '        json.endMember();'
-            print '    }'
+        
+        self.dump_atoms(glGet)
+        
+        self.dump_material_params()
+        self.dump_light_params()
+        self.dump_vertex_attribs()
+        self.dump_texenv_params()
+        self.dump_texture_parameters()
+
         print '    json.endObject();'
         print '    json.endMember(); // parameters'
         print
 
+    def dump_material_params(self):
+        for face in ['GL_FRONT', 'GL_BACK']:
+            print '    json.beginMember("%s");' % face
+            print '    json.beginObject();'
+            self.dump_atoms(glGetMaterial, face)
+            print '    json.endObject();'
+        print
+
+    def dump_light_params(self):
+        print '    GLint max_lights = 0;'
+        print '    __glGetIntegerv(GL_MAX_LIGHTS, &max_lights);'
+        print '    for (GLint index = 0; index < max_lights; ++index) {'
+        print '        GLenum light = GL_LIGHT0 + index;'
+        print '        if (glIsEnabled(light)) {'
+        print '            char name[32];'
+        print '            snprintf(name, sizeof name, "GL_LIGHT%i", index);'
+        print '            json.beginMember(name);'
+        print '            json.beginObject();'
+        self.dump_atoms(glGetLight, '    GL_LIGHT0 + index')
+        print '            json.endObject();'
+        print '            json.endMember(); // GL_LIGHTi'
+        print '        }'
+        print '    }'
+        print
+
+    def dump_texenv_params(self):
+        for target in ['GL_TEXTURE_ENV', 'GL_TEXTURE_FILTER_CONTROL', 'GL_POINT_SPRITE']:
+            print '    json.beginMember("%s");' % target
+            print '    json.beginObject();'
+            self.dump_atoms(glGetTexEnv, target)
+            print '    json.endObject();'
+
+    def dump_vertex_attribs(self):
+        print '    GLint max_vertex_attribs = 0;'
+        print '    __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);'
+        print '    for (GLint index = 0; index < max_vertex_attribs; ++index) {'
+        print '        char name[32];'
+        print '        snprintf(name, sizeof name, "GL_VERTEX_ATTRIB_ARRAY%i", index);'
+        print '        json.beginMember(name);'
+        print '        json.beginObject();'
+        self.dump_atoms(glGetVertexAttrib, 'index')
+        print '        json.endObject();'
+        print '        json.endMember(); // GL_VERTEX_ATTRIB_ARRAYi'
+        print '    }'
+        print
+
+    def dump_texture_parameters(self):
+        print '    {'
+        print '        GLint active_texture = GL_TEXTURE0;'
+        print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
+        print '        GLint max_texture_coords = 0;'
+        print '        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+        print '        GLint max_combined_texture_image_units = 0;'
+        print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
+        print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
+        print '        for (GLint unit = 0; unit < max_units; ++unit) {'
+        print '            char name[32];'
+        print '            snprintf(name, sizeof name, "GL_TEXTURE%i", unit);'
+        print '            json.beginMember(name);'
+        print '            glActiveTexture(GL_TEXTURE0 + unit);'
+        print '            json.beginObject();'
+        print '            GLint texture;'
+        print
+        for target, binding in texture_targets:
+            print '            // %s' % target
+            print '            texture = 0;'
+            print '            glGetIntegerv(%s, &texture);' % binding
+            print '            if (glIsEnabled(%s) || texture) {' % target
+            print '                json.beginMember("%s");' % target
+            print '                json.beginObject();'
+            self.dump_atoms(glGetTexParameter, target)
+            # We only dump the first level parameters
+            self.dump_atoms(glGetTexLevelParameter, target, "0")
+            print '                json.endObject();'
+            print '                json.endMember(); // %s' % target
+            print '            }'
+            print
+        print '            json.endObject();'
+        print '            json.endMember(); // GL_TEXTUREi'
+        print '        }'
+        print '        glActiveTexture(active_texture);'
+        print '    }'
+        print
+
     def dump_current_program(self):
-        print '    GLint current_program = 0;'
-        print '    glGetIntegerv(GL_CURRENT_PROGRAM, &current_program);'
-        print '    json.beginMember("current_program");'
-        print '    writeProgram(json, current_program);'
-        print '    json.endMember();'
+        print '    json.beginMember("shaders");'
+        print '    json.beginObject();'
+        print '    writeCurrentProgram(json);'
+        print '    writeArbProgram(json, GL_FRAGMENT_PROGRAM_ARB);'
+        print '    writeArbProgram(json, GL_VERTEX_PROGRAM_ARB);'
+        print '    json.endObject();'
+        print '    json.endMember(); //shaders'
         print
 
     def dump_textures(self):
-        print '    json.beginMember("textures");'
-        print '    json.beginArray();'
-        print '    GLint active_texture = GL_TEXTURE0;'
-        print '    glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
-        print '    GLint max_texture_coords = 0;'
-        print '    glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
-        print '    for (GLint unit = 0; unit < max_texture_coords; ++unit) {'
-        print '        glActiveTexture(GL_TEXTURE0 + unit);'
-        print '        json.beginObject();'
+        print '    {'
+        print '        json.beginMember("textures");'
+        print '        json.beginArray();'
+        print '        GLint active_texture = GL_TEXTURE0;'
+        print '        glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);'
+        print '        GLint max_texture_coords = 0;'
+        print '        glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);'
+        print '        GLint max_combined_texture_image_units = 0;'
+        print '        glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units);'
+        print '        GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords);'
+        print '        for (GLint unit = 0; unit < max_units; ++unit) {'
+        print '            glActiveTexture(GL_TEXTURE0 + unit);'
+        print '            json.beginObject();'
         for target, binding in texture_targets:
-            print '        json.beginMember("%s");' % target
-            print '        writeTexture(json, %s, %s);' % (target, binding)
-            print '        json.endMember();'
-        print '        json.endObject();'
+            print '            json.beginMember("%s");' % target
+            print '            writeTexture(json, %s, %s);' % (target, binding)
+            print '            json.endMember();'
+        print '            json.endObject();'
+        print '        }'
+        print '        glActiveTexture(active_texture);'
+        print '        json.endArray();'
+        print '        json.endMember(); // texture'
         print '    }'
-        print '    glActiveTexture(active_texture);'
-        print '    json.endArray();'
-        print '    json.endMember(); // texture'
         print
 
     def dump_framebuffer(self):
         print '    json.beginMember("framebuffer");'
         print '    json.beginObject();'
-        print '    json.beginMember("GL_DRAW_BUFFER");'
-        # TODO: Handle FBOs
-        print '    writeDrawBufferImage(json);'
-        print '    json.endMember();'
+        # TODO: Handle real FBOs
+        print
+        print '    GLint boundDrawFbo = 0, boundReadFbo = 0;'
+        print '    glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo);'
+        print '    glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo);'
+        print '    if (!boundDrawFbo) {'
+        print '        GLint depth_bits = 0;'
+        print '        glGetIntegerv(GL_DEPTH_BITS, &depth_bits);'
+        print '        GLint stencil_bits = 0;'
+        print '        glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);'
+        print '        writeDrawBuffers(json, depth_bits, stencil_bits);'
+        print '    } else {'
+        print '        GLint colorRb, stencilRb, depthRb;'
+        print '        GLint boundRb;'
+        print '        glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb);'
+        print '        GLint drawbuffer = glretrace::double_buffer ? GL_BACK : GL_FRONT;'
+        print '        glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);'
+        print
+        print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
+        print '                                              drawbuffer,'
+        print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
+        print '                                              &colorRb);'
+        print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
+        print '                                              GL_DEPTH_ATTACHMENT,'
+        print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
+        print '                                              &depthRb);'
+        print '        glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,'
+        print '                                              GL_STENCIL_ATTACHMENT,'
+        print '                                              GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,'
+        print '                                              &stencilRb);'
+        print
+        print '        GLint colorSamples, depthSamples, stencilSamples;'
+        print '        GLuint rbs[3];'
+        print '        GLint numRbs = 0;'
+        print '        GLuint fboCopy = 0;'
+        print '        glBindRenderbuffer(GL_RENDERBUFFER, colorRb);'
+        print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
+        print '                                     GL_RENDERBUFFER_SAMPLES, &colorSamples);'
+        print '        glBindRenderbuffer(GL_RENDERBUFFER, depthRb);'
+        print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
+        print '                                     GL_RENDERBUFFER_SAMPLES, &depthSamples);'
+        print '        glBindRenderbuffer(GL_RENDERBUFFER, stencilRb);'
+        print '        glGetRenderbufferParameteriv(GL_RENDERBUFFER,'
+        print '                                     GL_RENDERBUFFER_SAMPLES, &stencilSamples);'
+        print '        glBindRenderbuffer(GL_RENDERBUFFER, boundRb);'
+        print
+        print '        if (colorSamples || depthSamples || stencilSamples) {'
+        print '            //glReadPixels doesnt support multisampled buffers so we need'
+        print '            // to blit the fbo to a temporary one'
+        print '            fboCopy = downsampledFramebuffer(boundDrawFbo, drawbuffer,'
+        print '                                             colorRb, depthRb, stencilRb,'
+        print '                                             rbs, &numRbs);'
+        print '        }'
+        print '        glDrawBuffer(drawbuffer);'
+        print '        glReadBuffer(drawbuffer);'
+        print
+        print '        writeDrawBuffers(json, depthRb, stencilRb);'
+        print
+        print '        if (fboCopy) {'
+        print '            glBindFramebuffer(GL_FRAMEBUFFER, boundDrawFbo);'
+        print '            glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo);'
+        print '            glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo);'
+        print '            glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb);'
+        print '            glDeleteRenderbuffers(numRbs, rbs);'
+        print '            glDeleteFramebuffers(1, &fboCopy);'
+        print '        }'
+        print '    }'
+        print
         print '    json.endObject();'
         print '    json.endMember(); // framebuffer'
         pass
 
+    def dump_atoms(self, getter, *args):
+        for function, type, count, name in parameters:
+            if function is None:
+                continue
+            if getter.inflector.radical not in function.split(','):
+                continue
+            if type is X:
+                continue
+            print '        // %s' % name
+            print '        {'
+            type, value = getter(*(args + (name,)))
+            print '            if (glGetError() != GL_NO_ERROR) {'
+            #print '                std::cerr << "warning: %s(%s) failed\\n";' % (glGet.radical, name)
+            print '            } else {'
+            print '                json.beginMember("%s");' % name
+            JsonWriter().visit(type, value)
+            print '                json.endMember();'
+            print '            }'
+            print '        }'
+            print
+
     def write_line(s):
         self.write('  '*self.level + s + '\n')